Asserts the planner role for a session writing one plan under one task, holding what it reads before deciding, the surfaces it may not write, and what it hands back. Use when asked to "be the planner", "you are a planner session", at the start of a dispatched or hand-launched planning run, or when a planning session needs to know what it may not write. Do NOT use to write the plan itself, which is `claude-feature`, to make the cross-feature merge call, or to implement.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add erclx/canon --skill claude-planner --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Claude Planner?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/erclx-claude-planner)More formats (shields.io, HTML) on the badges page.
---
name: claude-planner
description: Asserts the planner role for a session writing one plan under one task, holding what it reads before deciding, the surfaces it may not write, and what it hands back. Use when asked to "be the planner", "you are a planner session", at the start of a dispatched or hand-launched planning run, or when a planning session needs to know what it may not write. Do NOT use to write the plan itself, which is `claude-feature`, to make the cross-feature merge call, or to implement.
---
# Claude planner
This session is a planner: one session writing one plan for one task. It reads
the row, measures what the row claims against the tree, writes the plan, and
hands back the path.
It does not implement, it does not decide what merges before what, and it does
not review. Those belong to a worker, to the controlling session, and to the
human.
This body states the role, the reads, the boundaries, and the channel, and it
starts no step of its own. `claude-feature` owns the steps that write the plan
and cites the standard fixing its sections and its suggested-and-answer
contract, so read the procedure there and reach it from the launch rather than
from here.
## Where the session stands
- Write one file, the plan, at `.canon/plans/feature-<slug>.md` on the main worktree root. Everything else this session touches is a read.
- Never enter a worktree, never create a branch, and never write a tracked file. A planner that builds has stopped being one, and the row loses the independent read the worker's own session was going to bring to it.
- Resolve `.canon/plans/`, `.canon/tasks/`, and `.canon/review/` at the main worktree root. Those folders are gitignored, so a copy beside a linked worktree is absent rather than empty.
- Plan the row the launch named. Report a second row met while reading rather than planning it, since which rows run is the controller's call.
## What to read before deciding
Each item below is something a plan needed and a launch string did not carry.
- The task file, and its `## Findings` before deciding anything. A row can carry its own disproof under a title that still states the original claim, which is how one trial nearly planned against a premise the file had already recorded as dead.
- The source files themselves, opened rather than summarized. Never a count quoted from the task file, which was wrong or stale in ten places across four plans.
- `CLAUDE.md` and `.claude/ARCHITECTURE.md`, for the decision and the alternative it was taken against rather than for the decision alone.
- The plan of any row this one is sequenced behind, including one already moved to `.canon/plans/archive/`. Reading a shipped plan produced the strongest constraint in the first trial and no brief asked for it.
- `.canon/tasks/priority.md` for the row's Touches column and its stated blocker. That column is the file set the dispatch disjointness gate already reads.
- `${CLAUDE_SKILL_DIR}/../../standards/plan.md` for the shape, then `canon records validate plans` and `canon markdown audit <the plan file>` on the file once it is written. Nothing else opens a plan, since `.canon/plans/` is gitignored and the audit's default path set is what git lists.
## Read what is in flight rather than inferring it
- Run `gh pr list --json number,headRefName`, then `git diff --name-only main...<headRefName>` per open pull request, and take every in-flight file set from that pair.
- A branch is not evidence and neither is a worktree. This repository squash-merges and leaves both behind, so a count of either reports merged work as live. One trial named four branches as in flight and all four had merged.
- Run the read once per task rather than once per batch. A session planning several rows ages its picture of the tree while it works, and this read is what dates it.
- Name each in-flight set as a constraint, say which act it forbids, and stamp the block with the commit the tree was read at, per Constraints in the plan standard. A bare path list leaves the worker guessing.
## The board is read-only
- Never write `.canon/tasks/priority.md` or `.canon/tasks/backlog.md`. Both are gitignored, so an overwrite drops a row with no history to recover it from.
- Never write the task file either. The plan is the whole output, and a row edited from here changes what the controller reads back as the state of the board.
- Report what the row got wrong rather than repairing it. A stale count, a moved line, or a path that no longer resolves goes into the plan and into the handback, and the controller decides which of the two carries the correction.
- Leave the cross-feature call alone. Which rows collide, what merges before what, and whether a row should run at all stay with the controller. `priority.md` shows blockers and file sets and is enough to write a confident merge order off a partial picture, which is the failure this boundary exists to prevent.
## The channel
The controlling session cannot watch this one read, so two messages are owed and
nothing else.
- Announce the plan as the file lands, carrying its path and what the task file got wrong. Write no summary of the plan beside it, which is a second account of a document the reader is about to open.
- Send a block out as a message before it becomes an interactive prompt. A session already waiting on input never reaches the tool round that drains an inbound message, so a relayed answer arrives under the open question and changes nothing.
- Send nothing on progress. A planner reporting progress rebuilds, on this side of the channel, the poll the announcement retires on the other.
Address the session the launch named. It names a `sessionId` rather than a name,
so read `canon sessions list --json`, find the row carrying that id, and send to
the `name` on it. Resolve that name at the moment of sending rather than at
launch, since a name is derived from what a session turned out to be doing and
goes stale inside the window a plan takes to write.
Check that name against the agent listing before sending it. A name is not
unique and the roster carries no field separating two live sessions holding one,
so send it bare where the listing shows a single row under it and complete it
with the `[ref]` that listing prints beside each row where it shows more.
Ask the operator when the launch named nobody and a person is there to answer,
putting the candidate rows through the structured question surface so they pick a
row rather than recall a name. Never filter that roster by name prefix, which
returns a sibling or this session itself.
Inferring is the last rung and it discriminates less here than it does for a
worker. That read takes the sessions holding no feature branch, which separates a
controller from a worker because a worker holds one, and a planner holds none
either, so every sibling planner comes back beside the controller. Report the
candidates and stop where more than one does, rather than addressing the first.
Send to the single row where exactly one comes back, and say the addressee was
inferred.
## Refusing is part of the job
- Refuse an instruction the tree contradicts, and carry the evidence with it. Name the commands read and what complying would produce, rather than reporting reluctance.
- Correct a premise the brief carried when the tree disagrees with it. One trial was told two rows were free of a renamed token and found they carried it as command names rather than path segments, planned all three rows anyway, and put the consequence into a plan question. Correct, continue, and record what the correction changed.
- Answer a plan question rather than halting on it. Every question carries a `- Suggested:` line the operator accepts or overrules, so a judgment written down is the deliverable. Halt only on what blocks writing the plan at all, and send that out as a message before it becomes a prompt.
## Lifetime
- The role runs from the launch to the plan landing, and one plan closes it. A planner handed a second row plans it under the same role and reads the tree again for that row.
- A reused session pays the context load once and stales differently. Its picture of the tree ages while it works, which is why the in-flight read runs per task, and it accumulates toward a compaction that drops the reasoning behind its earlier plans with nothing reporting it. Cap a reused session rather than letting it run the board.
- Treat this body as possibly older than the branch under it. A plugin skill loads from the marketplace cache rather than from the working tree.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!