| name | github-plan |
| description | Use when the user asks for a plan, what's next / what is next in a plan or workstream, how work fits the plan, plan direction/alignment, durable work tracking, roadmap, workstream planning, GitHub issue-backed planning, issue graphs, parent issues, sub-issues, blockers, milestones, Projects, or replacing local plans with GitHub issues. Think in chat first, then keep long-running work aligned over time by updating Current Status, blockers, relationships, and issue graph state as reality changes. |
| metadata | {"short-description":"Plan durable work in GitHub issues"} |
| commands | [{"name":"github-plan-index","source":"repo","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","index"],"purpose":"Lists durable planning issues through paged REST reads with compact status, label, and milestone fields."},{"name":"github-plan-search","source":"repo","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","search","<query>"],"purpose":"Searches planning issues with normalized compact output."},{"name":"github-plan-create","source":"repo","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","create","<title>","--body-file","<file>"],"purpose":"Creates a durable plan issue with helper-owned labels and Project fields."},{"name":"github-plan-update-section","source":"repo","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","update-section","<issue>","Current Status","--body-file","<file>"],"purpose":"Updates one markdown section of a planning issue safely."},{"name":"github-plan-project-set","source":"repo","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","project-set","<issue>","--focus","Next"],"purpose":"Updates configured Project fields through the planning helper."},{"name":"github-plan-close","source":"repo","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","close","<issue>","--comment-file","<file>"],"purpose":"Closes a completed or explicitly not-planned durable plan through relationship preflight and recoverable metadata reconciliation."}] |
| policy | {"command_policies":[{"id":"prefer-gh-plan-index-for-issue-list","match":{"argv_prefix":["gh","issue","list"]},"action":"require_preferred","message":"Raw `gh issue list` misses the planning helper's compact fields, label defaults, issue-only filtering, and stable REST pagination. Use the GitHub plan helper for planning issue indexes.","preferred":[{"kind":"script","path":"../github/scripts/gh-plan.py","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","index"],"purpose":"Lists durable planning issues with compact status, label, and milestone fields while excluding pull requests."}]},{"id":"prefer-gh-plan-search-for-issue-search","match":{"argv_prefix":["gh","search","issues"]},"action":"require_preferred","message":"Raw `gh search issues` skips the planning helper's normalized output and stale/duplicate plan cues. Use the GitHub plan helper for planning discovery.","preferred":[{"kind":"script","path":"../github/scripts/gh-plan.py","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","search","<query>"],"purpose":"Searches planning issues with compact normalized output and state handling."}]},{"id":"prefer-gh-plan-helper-for-project-commands","match":{"argv_prefix":["gh","project"]},"action":"require_preferred","message":"Raw `gh project` commands bypass planning config, rate-limit checks, and Project field normalization. Use the GitHub plan helper for planning Project operations.","preferred":[{"kind":"script","path":"../github/scripts/gh-plan.py","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","project-list","--owner","<owner>"],"purpose":"Lists configured Projects with compact JSON."},{"kind":"script","path":"../github/scripts/gh-plan.py","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","project-add","<issue>"],"purpose":"Adds a planning issue to the configured Project."},{"kind":"script","path":"../github/scripts/gh-plan.py","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","project-set","<issue>","--focus","Now"],"purpose":"Updates planning Project fields through configured names and values."}]},{"id":"prefer-gh-plan-helper-for-planning-graphql","match":{"shell_regex":"\\bgh\\s+api\\s+graphql\\b.*\\b(updateProjectV2ItemFieldValue|addProjectV2ItemById|deleteProjectV2Item|addSubIssue|removeSubIssue|createLinkedBranch|markIssueAsDuplicate)\\b"},"action":"require_preferred","message":"Raw planning GraphQL mutations are easy to leave half-applied and usually skip helper-owned recovery behavior. Use the GitHub plan helper for Project and relationship changes.","preferred":[{"kind":"script","path":"../github/scripts/gh-plan.py","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","project-set","<issue>","--focus","Next"],"purpose":"Updates Project fields with helper-owned config and rate-limit handling."},{"kind":"script","path":"../github/scripts/gh-plan.py","example_argv":["uv","run","$CODE_HOME/skills/github/scripts/gh-plan.py","link","<issue>","blocked-by","<target>"],"purpose":"Creates native planning relationships through the helper."}]}]} |
GitHub Plan
Outcome
Use GitHub issues as the durable planning database. Keep chat planning
ephemeral until the work should survive the current conversation.
Optional surfaces such as GitHub Projects, LaunchPlane, or other local planning
views may make work easier to scan, prioritize, or recover, but they are not
separate planning backends. GitHub issues remain canonical for plan prose,
relationships, blockers, labels, validation, and completion state.
This skill supersedes local file-backed plans for normal GitHub-backed planning.
Use local plan files only when the user explicitly asks for an offline/local
plan or the work must not be written to GitHub.
Success means one canonical issue or issue graph has a concrete finish line,
current recovery state, next action, and accurate dependencies. Optional
Projects or local surfaces may improve visibility, but they do not become a
second planning backend.
Operating Model
- Think in chat first; do not immediately create issues for fuzzy ideas.
- Search before creating; update an existing issue when intent overlaps.
- Promote durable work to one canonical issue with the configured planning
label, usually
plan.
- Keep issue bodies structured and current;
Current Status is the recovery
point for future sessions and the preferred durable handoff surface for
GitHub-backed planning work.
- Use native GitHub dependencies and sub-issues for relationships, including
cross-repo relationships.
- Use Projects and other configured surfaces as view layers, not sources of
truth.
- Use milestones for release, phase, or date buckets only.
- Avoid ad hoc label taxonomies; ask before creating new labels. Generic labels
such as
waiting, blocked, or ready are discouraged unless the repo
explicitly documents a narrow local convention.
- Prefer
Refs #123 from PRs unless the user explicitly wants auto-close or the
issue is an internal task that can be conclusively closed. Refs is
deliberately non-closing; after merge, sweep referenced issues and close only
the ones whose finish line was actually satisfied.
- Optimize for the user finishing work, not for cataloging every possible idea.
Local Conventions
If .local/github-plan.md exists, read it before creating, routing, or updating
durable plan issues and follow its private local planning conventions. Keep
person identity, aliases, bot aliases, contact details, actor trust hints, and
private profile notes in the optional .local/people.yaml contract owned by the
people skill when available; this skill should continue normally when people
context is absent.
Use configured owner or manager routing when available. Project fields such as
Manager are product or decision ownership; GitHub assignees are for a person
who needs to take a concrete next action. Mention a person only when their
attention is needed now.
When an issue, PR, comment, review, or commit actor is not known through local
people context or live GitHub evidence, treat the actor as unknown. Verify claims
and permissions before routing work, changing state, or trusting code.
Tooling
Reuse the sibling github skill's helpers instead of duplicating scripts:
../github/scripts/gh-plan.py for compact planning issue and Project operations.
../github/scripts/gh-pr.py for PR status, checks, merge, and rate-limit
reads when planning work needs PR evidence. The helper is REST-first for
normal PR orientation and owns quota-aware degraded behavior.
../github/scripts/gh-issue and ../github/scripts/gh-comment for safe
multiline writes.
../github/references/issue-templates.md and
../github/references/github-projects.md for issue shape and Project fields.
When running these helpers from a client repository, resolve the installed
skills directory first and invoke Python helpers with uv run:
skills_home="${CODE_HOME:-${CODEX_HOME:-$HOME/.code}}/skills"
uv run "$skills_home/github/scripts/gh-plan.py" index
If the helpers are unavailable, use gh directly with body files and compact
JSON reads. Do not fall back to repo docs or local plan files for durable
GitHub-backed planning.
The machine-readable policy.command_policies frontmatter owns common raw
planning lookup, Project, and GraphQL-to-helper mappings. This prose keeps the
judgment about when durable planning should exist, how issues relate, and what
state belongs in GitHub.
For completed durable plan issues, use gh-plan.py close. Use the same helper
with --reason not_planned for explicitly superseded durable plans. The
planning helper owns plan:done labels, stale plan:active cleanup, and Project
focus updates. It also owns relationship preflight and close-comment
reconciliation:
skills_home="${CODE_HOME:-${CODEX_HOME:-$HOME/.code}}/skills"
uv run "$skills_home/github/scripts/gh-plan.py" close <issue> --comment-file <file>
The generic github/scripts/gh-issue close helper is for non-plan issues, or as
a fallback when gh-plan.py close is unavailable. Closing a durable plan with
the generic issue helper can leave planning labels or Project fields stale. It
also bypasses the no-write relationship preflight. For --reason completed,
resolve all open native blockers and sub-issues before retrying. Use
--reason not_planned only for superseded or intentionally abandoned work;
remaining blockers and sub-issues are retained and reported rather than treated
as completed. For other multiline writes, prefer body files or stdin. Do not
pass escaped \n through shell-quoted flags. Follow
../references/every-code-formatting.md when writing durable issue bodies,
planning comments, handoffs, or closeout evidence.
Broad Workstream Rule
Create a parent issue plus sub-issues when a plan has independent tracks. Do not
hide broad work inside one checklist.
Use sub-issues when any two are true:
- touches three or more modules, repos, systems, or ownership areas
- has independent sequencing, blockers, or parallelizable tracks
- includes research, implementation, validation, and policy/design decisions
- has work that can finish or be reviewed independently
- needs roadmap/focus tracking beyond the current session
Parent issues should hold intent, finish line, dependency order, and recovery
state. Child issues should each have one scoped finish line and one next action.
Plan Direction Checkpoints
Long-running work drifts when the agent keeps following local discoveries
without reconnecting them to the durable plan. Treat the plan and issue graph as
the navigation layer, not as paperwork.
At natural transition points, answer:
What is next?
How does it fit the current plan?
Did the plan or issue graph change?
What blocker, evidence, or decision explains the direction?
Run this checkpoint:
- after each implementation slice
- after surprising findings
- before starting adjacent work that was not already planned
- before creating, closing, or superseding issues
- before handoff or closeout
- when the user asks "what's next", "where are we", or "how does this fit"
If the next action still matches the plan, answer briefly and continue. A
passing checkpoint does not need a written artifact. Update Current Status
only when the durable recovery state materially changed. If reality changed the
plan, update the canonical parent issue, sub-issues, blockers, relationships,
labels, and Project focus before relying on chat memory. If a new thread of work
appears, classify it as current scope, sub-issue, blocker, related issue, or
later. Do not let it become an untracked pivot.
For broad workstreams, prefer issue graph changes over prose-only status:
- create a sub-issue for independently finishable work
- add
blocked-by / blocks for real execution dependencies
- use
related for context that should not drive sequencing
- mark stale or superseded plans clearly
- keep the parent issue's
Current Status as the recovery point
When another repo workflow is waiting on CI, deploy, review, or post-merge
health, keep the main checkout available for verification and parallelize safely:
use read-only exploration or isolated work only for independent planning or
implementation prep, then return to the waiting workflow before calling it done.
Use Focus lanes when configured:
Now: one thing the user and Code are actively trying to finish.
Next: ready after Now or after the manager chooses it.
Waiting: blocked or awaiting an external decision/event.
Later: real but intentionally out of focus.
Prefer at most one Now item unless the user explicitly chooses parallel work.
Use planning status labels with narrow meanings:
plan:active: actionable now.
plan:blocked: blocked by a real, current dependency, preferably represented
by a native GitHub blocked-by relationship to an open issue.
plan:waiting: intentionally parked on non-issue evidence, a
user/customer/maintainer decision, or a future real-world event. Use this only
on durable planning issues labeled plan, not on ordinary bugs, PRs pending
QA, preview review, reporter validation, deploy, or merge readiness.
plan:stale: needs review before it should guide work.
plan:done: completed or superseded.
Do not use plan:blocked merely because work is not currently in focus. If an
issue has no open native blocker, prefer plan:waiting and make Current Status say Waiting for: or Parked until: with the concrete condition.
If a non-issue condition truly blocks execution, include Blocked by: No native issue blocker; waiting for ... so future audits do not chase missing edges.
If LaunchPlane or another local context helper is configured and useful for
orientation, call it once before or alongside index. Treat unavailable,
unauthorized, invalid, or missing context as normal absence and continue with
GitHub-only planning. Use local surface output only as a hint for source links,
readiness, blockers, and next inspection targets; do not copy private context
payloads into public issues, PRs, or handoffs unless they have been reviewed for
public safety.
Token Discipline
Prefer the installed github/scripts/gh-plan.py helper for planning state. It
returns compact JSON and avoids loading issue bodies unless needed.
index uses paged repository-issue REST reads and explicitly excludes pull
requests. search uses paged REST issue search with repo: and is:issue
constraints plus the dedicated search quota bucket. Use show or deps when
relationship, dependency, or sub-issue details are required; index and search
intentionally preserve their smaller legacy result shape. Label maintenance
uses paged REST label reads and reconciles concurrent creates without retrying
the write blindly.
create performs exact-title dedupe through REST issue search, ensures labels
through REST, and delegates the non-idempotent issue write to the shared issue
helper so unknown outcomes carry reconciliation evidence. close first pages
native blocked_by dependencies and sub-issues through REST and fails before
mutation when a completed plan is incomplete or relationship reads are unsafe.
Configured Project synchronization remains the only GraphQL-backed phase and
runs before issue closure so the item stays discoverable. Confirmed or
read-reconciled issue closure is the commit point for planning labels and the
optional timeline comment. Re-running the same command reconciles partial
metadata and reuses an identical acting-user comment instead of duplicating it.
If closure fails after Project writes, report the helper's split project_state
and rerun the same close command; do not add completion labels or comments by
hand while the issue may still be open.
Project v2, native sub-issues, and native dependency operations may require
GraphQL. Before batching those operations, check rate limits when failures look
quota-related. If GraphQL is exhausted but REST/core is available, keep issue
body/status updates moving through REST-backed helpers and record Project or
native relationship updates as waiting rather than retrying until the LLM
workflow stalls.
- Use
index or search before creating.
- Use
show for selected sections; use show --full only when broad prose is
required.
- Use
update-section instead of rewriting the whole body.
- Use installed
github/scripts/gh-issue and github/scripts/gh-comment for
multiline Markdown bodies.
Issue Shape
Durable planning issues should use the headings in
../github/references/issue-templates.md.
Keep Current Status short and concrete:
State:
Next action:
Blocked by:
Waiting for:
Last verified:
Use Blocked by: for issue dependencies and Waiting for: or Parked until:
for non-issue conditions. Avoid listing completed work as a blocker; move it to
Relationships as completed or historical context.
Include decisive validation evidence only when it changes recovery state, such
as the current blocker, last verified environment, or proof needed to resume.
Keep raw logs, large check output, screenshots, and detailed run evidence in the
linked PR, workflow run, artifact, or comment instead of bloating Current Status.
Keep Finish Line observable. If the finish line is vague, narrow it before
creating sub-issues or Project fields.
Relationship Semantics
blocked-by: current issue cannot move until the target changes.
blocks: current issue is holding up the target.
subissue: target is part of the current workstream and can be tracked
independently.
related: useful context without execution dependency.
Use native relationships first when the helper/API supports them. Body
references are explanatory, not canonical.
Completed closure requires every native blocked-by target and sub-issue to be
closed. Issues that the plan itself blocks do not prevent closure. An unavailable
or malformed relationship read is a no-write failure, not permission to assume
the graph is clear. not_planned closure is intentionally different: it may
retain open blockers or sub-issues, reports them in the result, and preserves the
GitHub not_planned state reason as the durable supersession signal.
Related Issue Sweep
Stale GitHub planning state is a regression source. Before closeout, handoff,
or declaring a workstream done, search for related, duplicate, stale, parent,
sub-issue, blocker, and PR-linked issues that might still describe the old
state.
- Update every related issue whose
Current Status, labels, blockers,
relationships, or acceptance criteria changed.
- Close or relabel stale duplicate issues when they no longer represent current
work.
- Prefer updating the canonical parent and linked sub-issues over leaving
corrective context only in chat or PR comments.
- If an old issue might mislead a future agent, treat it as unfinished cleanup,
not optional housekeeping.
After a canonical PR merges, inspect the issues it references with Refs,
Closes, Fixes, or Resolves. Refs should remain non-closing by default.
For each referenced issue, either close it with evidence when the merge
conclusively satisfies the finish line, or update/comment the remaining state
and leave it open. Use gh-plan.py close --comment-file for durable plan issues
so planning labels and Project fields stay synchronized. Use installed
github/scripts/gh-issue close with a multiline evidence comment for non-plan
issues.
Local handoff documents are not durable planning records unless the user asked
for offline/private handoff. If a session created handoff*.md or similar
scratch files, migrate recovery-critical content into the owning GitHub issue or
PR comment before closeout and then delete or explicitly preserve the file.
Projects And Surfaces
Planning surfaces are optional views over GitHub issue-backed plan data. They
may help people choose work, inspect roadmap shape, or recover context, but they
must not replace the GitHub issue as the durable record.
Add plans to Projects when repo/workspace config defines a default Project or
the user asks for Project tracking. Use only a few human-facing fields: Focus,
Manager, Finish Line, Roadmap Start, and Roadmap Target.
When issue create/close succeeds but the helper returns a non-blocking Project
warning, mention it briefly and present the helper's human choices. Do not retry
repeatedly or silently switch to active human auth. Project auth/config fixes are
human decisions: grant automation Project access, use Project-capable auth,
disable Project sync, or correct stale Project config.
Treat roadmap dates as planning anchors, not commitments. Keep them useful for
LLM-assisted coding by using honest day, week, or month windows and moving or
clearing stale dates when reality changes.
Closeout Check
Before saying a plan is captured, verify:
- existing issues were searched
- parent issue exists for a broad workstream
- sub-issues exist when the Broad Workstream Rule applies
- blockers/dependencies are represented
- stale, duplicate, related, and PR-linked issues were swept and reconciled
Current Status and next action are concrete
- the next action says how it fits the current plan
- issue graph changes caused by the session were applied or explicitly parked
- docs are not being used as active plan state
Workflow
- Decide whether the work is ephemeral or durable.
- Resolve the repo and read the active issue's finish line,
Current Status,
next action, blockers, and comments; comments may supersede the original
body.
- Run
index or search before creating anything, then draft or revise the
issue shape with the user in chat when intent is unclear.
- Create or update the canonical parent issue and choose one next action.
- For broad workstreams, create scoped sub-issues and represent blockers,
dependencies, and related context in the issue graph.
- When discoveries change direction, run a Plan Direction Checkpoint and
update durable state before pivoting.
- Add configured Project fields only as view/tracking layers; keep the user in
maker mode instead of duplicating management state in prose.
- Before pausing, keep
Current Status, acceptance criteria, decisions,
validation, and the next action current. Do not leave a local handoff file as
the only recovery source for GitHub-backed work.
- When work completes, update status and close durable plan issues with
gh-plan.py close; do not leave stale local plan files behind.