A curated library of 12 language-agnostic planning skills and 4 personas for technical project management, product planning, and agile execution.
91
94%
Does it follow best practices?
Impact
91%
1.16xAverage score across 16 eval scenarios
Passed
No known issues
Use this skill when you need to create, track, or manage GitHub issues with project board integration and milestone tracking.
Core principle: Always validate issue drafts with the user before creating. In non-interactive contexts, present the draft with noted assumptions and proceed.
Present and verify every GitHub issue draft before creation.
The preview MUST include title, labels, milestone, and project board
placement. In non-interactive contexts, document assumptions and
proceed with best-effort creation.
For issue updates: verify stage label changes and issue closures before
applying. In non-interactive contexts, document the intended change
and proceed.| Aspect | Rule |
|---|---|
| Input | Approved ticket drafts (from plan-tickets), feature description, or bug report |
| Output | GitHub issues with labels, project board placement, and milestone assignment |
| Stage flow | todo → in-progress → in-review → done (closed) |
| Type labels | bug, new-feature, improvement, refactor, security |
gh CLI installed and authenticated (gh auth status)plan-tickets), or a clear feature/bug descriptionType (required, one): bug, new-feature, improvement, refactor, security
Stage (lifecycle): todo, in-progress, in-review, done
Phase (optional): phase-1, phase-2, etc.
Priority (optional): priority:high, priority:medium, priority:low
All labels use kebab-case. New issues MUST start with stage label todo.
todo → in-progress → in-review → done (closed)Any stage can revert to todo if work is blocked or deprioritized.
Extract or ask for: the problem or feature, why it matters, what "done" looks like, and any examples, links, or error messages.
# Get owner and repo
OWNER_REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner')
OWNER=$(echo $OWNER_REPO | cut -d'/' -f1)
REPO=$(echo $OWNER_REPO | cut -d'/' -f2)
# Check for issue templates
ls -la .github/ISSUE_TEMPLATE/ 2>/dev/null || echo "No templates found"
# Check for Projects V2
gh project list --limit 10 --json number,title,url 2>/dev/null
# Check for Classic projects
gh api graphql -f query="query { repository(owner: \"$OWNER\", name: \"$REPO\") { projects(first: 10) { nodes { name url } } } }" 2>/dev/null
# Check for open milestones
gh api repos/$OWNER/$REPO/milestones?state=open --jq '.[].title'If templates exist in .github/ISSUE_TEMPLATE/, adapt to that format. Otherwise use:
Title: Clear, action-oriented (e.g. "Add password reset email flow with SendGrid integration")
Body template:
## Problem / Motivation
[Describe the problem and its impact — who is affected and why it matters.]
## Expected Outcome / Goal
[Describe the desired end state or user-facing result.]
## Proposed Solution (if known)
[Outline the approach, key components, or implementation notes.]
## Acceptance Criteria
- [ ] Given [context], when [action], then [result]
- [ ] Given [context], when [action], then [result]
- [ ] Given [context], when [action], then [result]Present the draft before creating:
Here's the issue I'm about to create:
**Title:** [title]
**Type:** [type label]
**Stage:** todo
**Phase/Milestone:** [if applicable]
**Project Board:** [if detected]
**Description:**
[formatted body]
Does this look good, or would you like to adjust anything?Wait for user confirmation before proceeding. In non-interactive contexts, document assumptions and proceed.
# Create the issue and capture URL
ISSUE_URL=$(gh issue create \
--title "Your title here" \
--body "Your body here" \
--label "todo,bug" \
--json url --jq '.url')
# Extract issue number from URL (e.g. https://github.com/owner/repo/issues/42)
ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')Add to Projects V2:
# Add issue to a Projects V2 board
gh project item-add PROJECT_NUMBER --owner $OWNER --url $ISSUE_URL
# Query field IDs and status option IDs
gh api graphql -f query='
query($owner: String!, $number: Int!) {
organization(login: $owner) {
projectV2(number: $number) {
fields(first: 20) {
nodes {
... on ProjectV2SingleSelectField {
id name
options { id name }
}
}
}
}
}
}' -F owner=$OWNER -F number=PROJECT_NUMBER
# Set status column via mutation (use field/option IDs from query above)
gh api graphql -f query='
mutation($project: ID!, $item: ID!, $field: ID!, $option: String!) {
updateProjectV2ItemFieldValue(
input: { projectId: $project, itemId: $item,
fieldId: $field, value: { singleSelectOptionId: $option } }
) { projectV2Item { id } }
}' -F project=PROJECT_ID -F item=ITEM_ID -F field=FIELD_ID -F option=OPTION_IDAdd to Classic project board:
# Query column IDs
gh api graphql -f query='
query($owner: String!, $repo: String!) {
repository(owner: $owner, name: $repo) {
projects(first: 10) {
nodes { name columns(first: 10) { nodes { id name } } }
}
}
}' -F owner=$OWNER -F repo=$REPO
# Create card in target column
gh api repos/$OWNER/$REPO/projects/columns/COLUMN_ID/cards \
-f content_id=$ISSUE_NUMBER -f content_type=IssueAdd to milestone:
gh issue edit $ISSUE_NUMBER --milestone "Sprint 6 — Notifications"Report the created issue number, URL, applied labels, project board column, and milestone assignment.
Before moving on, confirm:
bug, new-feature, improvement, etc.)todoA successfully created GitHub issue must conform to this shape:
GitHub Issue #<number>
Title: "<action-oriented, specific title>"
URL: https://github.com/<owner>/<repo>/issues/<number>
State: open
Labels: todo, <type-label>
Project: <board-name> → <column-name>
Milestone: <milestone-title> (if assigned)
Body:
## Problem / Motivation
<concrete description of the current problem>
## Expected Outcome / Goal
<measurable definition of "done">
## Acceptance Criteria
- [ ] Given <context> when <action> then <expected result>Validation before reporting "done":
todo for new issues# By number
gh issue view 42 --json title,body,labels,milestone
# By search
gh issue list --search "password reset email flow" --json number,title,labels,statePresent results to confirm the right issue.
Present the intended stage change for confirmation. In non-interactive contexts, document the change and proceed. Examples: "Move #42 to in-progress", "Mark #42 as done", "Close #42".
# Remove old stage label, add new one
gh issue edit 42 --remove-label "todo" --add-label "in-progress"
# If done, also close
gh issue close 42 --reason completedFor Projects V2, use the QueryProjectV2Fields query (see Creating §Step 5) to look up field/option IDs, then run the updateProjectV2ItemFieldValue mutation to move the item to the new status column. For Classic projects, use QueryClassicProjectColumns and create a card in the target column.
✓ Issue #42 updated
Status: todo → in-progress
Project: Moved to "In Progress" column
URL: https://github.com/owner/repo/issues/42Before confirming the update is complete, verify:
completed or not planned)todo + in-progress simultaneously).tessl-plugin
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10
scenario-11
scenario-12
scenario-13
scenario-14
scenario-15
scenario-16
skills
analysis
requirements-clarifier
backlog
prioritize-backlog
ceremony
create-retrospective
plan-sprint
infrastructure
github-issue
prd
create-prd
review-prd
task-management
estimate-tasks
generate-tasks
plan-tickets