From otto-kit
Sync plan files to GitHub Issues and Projects using the gh CLI. Creates an epic issue with sub-issues for each task. Used as a tracker adapter by /plan.
How this skill is triggered — by the user, by Claude, or both
Slash command
/otto-kit:gh-planThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Sync a plan file to GitHub Issues (and optionally a GitHub Project). This skill is invoked as a sub-agent by `/plan` — it is not user-invocable directly.
Sync a plan file to GitHub Issues (and optionally a GitHub Project). This skill is invoked as a sub-agent by /plan — it is not user-invocable directly.
gh CLI authenticated (gh auth status succeeds)PLAN_FILE: absolute path to the plan file (epic for complex, single file for simple)PROJECT_NUMBER (optional): GitHub Project number to add issues toFor complex plans, a sibling directory with the same name (minus .md) contains detailed task files:
.claude/plans/2fa-authentication.md ← PLAN_FILE (epic)
.claude/plans/2fa-authentication/ ← task directory
01-okta-sdk-setup.md
02-keychain-service.md
...
Read the plan file. Extract from frontmatter:
feature — used as the epic issue titletype — simple or complexgh repo view --json nameWithOwner -q '.nameWithOwner'
gh label create epic --description "Parent issue tracking a feature" --color "3B82F6" 2>/dev/null || true
gh label create task --description "Implementation task from a plan" --color "10B981" 2>/dev/null || true
Build the epic issue body from the plan file content.
gh issue create --title "<feature>" --body "<plan body>" --label "epic"
Store the returned issue number as EPIC_NUMBER.
Get the epic's node ID (needed for the sub-issue API):
EPIC_NODE_ID=$(gh issue view $EPIC_NUMBER --json id -q '.id')
Derive the task directory path from PLAN_FILE: strip .md extension.
TASK_DIR="${PLAN_FILE%.md}"
ls "$TASK_DIR"/*.md
Read each task file in order (filenames are NN-slug.md). For each task:
a) Create the issue:
gh issue create \
--title "<task title from frontmatter>" \
--body "<full task file content + dependency info>" \
--label "task"
Include in the body:
Parent: #<EPIC_NUMBER>Depends on: #<issue>, #<issue> (map task numbers from the frontmatter depends_on field to the corresponding created issue numbers)Store the returned issue number. Get its node ID:
TASK_NODE_ID=$(gh issue view $TASK_NUMBER --json id -q '.id')
b) Attach as a native sub-issue of the epic:
gh api graphql \
-H "GraphQL-Features: sub_issues" \
-f query='
mutation($parentId: ID!, $childId: ID!) {
addSubIssue(input: { issueId: $parentId, subIssueId: $childId }) {
subIssue { number title }
}
}' \
-f parentId="$EPIC_NODE_ID" \
-f childId="$TASK_NODE_ID"
This creates a proper parent-child relationship visible in GitHub's UI (the "Sub-issues" section on the epic), not just a #reference mention.
c) Repeat for all task files, preserving creation order so sub-issues appear in build order.
After all sub-issues are attached, update the epic body to include a reference checklist:
gh issue edit $EPIC_NUMBER --body "<updated body with issue links>"
The checklist serves as a readable summary alongside the native sub-issues panel:
## Tasks
- [ ] #<issue1> — <task title>
- [ ] #<issue2> — <task title>
If PROJECT_NUMBER is provided:
# Get project ID
PROJECT_ID=$(gh api graphql -f query='
query($owner: String!, $number: Int!) {
user(login: $owner) {
projectV2(number: $number) { id }
}
}' -f owner="$(gh api user -q '.login')" -F number=$PROJECT_NUMBER -q '.data.user.projectV2.id' 2>/dev/null || \
gh api graphql -f query='
query($owner: String!, $number: Int!) {
organization(login: $owner) {
projectV2(number: $number) { id }
}
}' -f owner="$(echo $REPO | cut -d/ -f1)" -F number=$PROJECT_NUMBER -q '.data.organization.projectV2.id')
# Add epic
gh api graphql -f query='
mutation($project: ID!, $content: ID!) {
addProjectV2ItemById(input: {projectId: $project, contentId: $content}) {
item { id }
}
}' -f project="$PROJECT_ID" -f content="$(gh issue view $EPIC_NUMBER --json id -q '.id')"
Add each sub-issue to the project as well.
Only after all issues are created successfully:
rm "<PLAN_FILE>"
rm -rf "${PLAN_FILE%.md}" # task directory (complex plans only, if it exists)
If any step failed, do NOT delete anything. Report the error and leave files intact so the user can retry.
Output a summary:
#<number> with link#<number> (or "no project specified")npx claudepluginhub bardin08/claude-kit --plugin otto-kitSaves the latest implementation plan from docs/plans/ to a GitHub issue with repo, branch, and directory context for execution in a separate Claude Code session.
Syncs Claude Code sessions with GitHub Issues as a shared plan — reads issue context on branch detection, updates progress via comments, checks off tasks, and creates issues from plans.
Creates GitHub issues via gh CLI/API, sets types (Bug/Feature/Task), links subissues, copies parent milestones/project fields. For repo issue management.