Skip to content
Development
Skill

/to-plan

Capture the chat into `.task/task/<slug>.md` with `## Description` plus `## Plan` (Goal/Touches/Logic) — the deepest one-task capture.

From plugin
task
78 skills8 agents
Install
$ npx -y skills add SpaiR/task-pipeline --skill to-plan --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/to-plan

Context preview

The summary Claude sees to decide when to auto-load this skill.

Capture the chat into `.task/task/<slug>.md` with `## Description` plus `## Plan` (Goal/Touches/Logic) — the deepest one-task capture.

SKILL.md

to-plan.SKILL.md
name: to-plan
description: 'Capture the chat into `.task/task/<slug>.md` with `## Description` plus `## Plan` (Goal/Touches/Logic) — the deepest one-task capture.'
argument-hint: '[<slug> | <roadmap-slug>[#N] | context]'
disable-model-invocation: true
user-invocable: true
allowed-tools: 'Bash(bash *skills/_lib/preflight.sh* *) Bash(bash *skills/_lib/write-task.sh* *) Bash(bash *skills/_lib/roadmap-items.sh* *) Bash(bash *skills/_lib/detect-project.sh* *) Bash(bash *skills/validate/validate.sh* *)'

Distil the chat discussion so far (or a roadmap item) into `.task/task/<slug>.md` — `## Description` **and** `## Plan` (Goal/Touches/Logic steps), plus `## Tests` when the testing policy calls for it, and the `## Execution` pointer. The deepest of the three capture skills (`to-task` / `to-plan` / `to-roadmap`): use it when you know enough about the approach to hand straight to implementation, or run it again on a `to-task`-only file to add the Plan in place. The slug is the filename; the artifact path is the handle.

**Input:** `$ARGUMENTS` — optional. Recognized forms:

  • (empty) — draft from the chat discussion so far, or continue a task this conversation is clearly about (see Step 1).
  • `<slug>` or a path to an existing `.task/task/<slug>.md` — target that file directly.
  • `<roadmap-slug>` or `<roadmap-slug>#<N>` — open from that roadmap item instead of the chat.
  • anything else — free-form context to fold into the draft alongside the chat discussion.

**Format contract:** [docs/contract.md](../../docs/contract.md) is the single source of truth for the output structure — read it if anything below is ambiguous.

Step 0: Setup gate

The entry state, gathered before this skill reached you — no tool call of your own:

!`bash "${CLAUDE_PLUGIN_ROOT}/skills/_lib/preflight.sh" plan`

[docs/contract.md § Helpers](../../docs/contract.md#helpers) owns that block's shape. Read it, then act:

1. `AI_DIR:` is the pipeline root: `.task/task/<slug>.md` below means `$AI_DIR/task/<slug>.md`, **never a cwd-relative path** ([contract § Setup-gate categories](../../docs/contract.md#setup-gate-categories)). 2. **`CONFIG: absent` → inline setup.** Read `${CLAUDE_PLUGIN_ROOT}/skills/_lib/setup.md` and follow it — it owns the sub-steps and the `.task/CLAUDE.md` template, and there is no separate setup command. No confirmation chip. Then continue to Step 1 with the original `$ARGUMENTS` unchanged. (A relative `AI_DIR: .task` means no git repository and no `.task/` yet; setup establishes `<ROOT>/.task`.) 3. **`CONFIG: present` → leave it alone.** It is user-owned; only `task.root` and the `.git/info/exclude` line are restored when missing. 4. `ROADMAPS:` / `TASKS:` / `SPECS:` are what already exists. Step 1 resolves its target against `TASKS:` and `ROADMAPS:`, and Step 2a's collision check reads `TASKS:` — neither lists a directory of its own.

If that block arrived unexpanded — the command line itself rather than its output — the preprocessing did not fire: run that command yourself and continue exactly as above.

There is no full-scan validate call here — the file this run writes is validated after the write (Step 7), and pre-existing artifacts are checked on demand with `validate.sh all`, never as an entry gate.

Step 1: Resolve the target and capture mode

The artifact path is the handle — there is no pointer to resolve, and the target is re-resolved every run. Take the **first** case that matches:

1. `$ARGUMENTS` holds an explicit path (contains `/`, or ends in `.md`), or a slug that Step 0's `TASKS:` list carries → that file is the target. A slug absent from `TASKS:` does **not** match here; it falls to case 2. 2. `$ARGUMENTS` holds a `ROADMAPS:` slug, with or without `#<N>` → the target is `.task/task/<item-slug>.md`, derived in Step 2a. (Matching both an existing task file and a roadmap is case 1: the concrete file is the more specific target.) 3. No positional reference, but this chat is clearly continuing a task it already captured, or the user names one by title or slug → that file is the target. More than one plausible match → ask via `AskUserQuestion` (convention (c)) rather than guessing. 4. Nothing matches → no target; go to Step 2 as a fresh capture.

A path target is reduced to its `<slug>` — basename without `.md` — before Step 7: `write-task.sh` takes `--slug` and resolves `$AI_DIR/task/<slug>.md` itself.

For cases 1 and 3, branch on whether the target file exists:

  • **Does not exist** → **fresh capture.** From case 2, continue at Step 2a; otherwise Step 2b.
  • **Exists, no `## Plan`** → **promote mode** — the flag-free way to deepen a `to-task` capture. Skip Step 2; the header and `## Description` are already there and stay untouched.
  • **Exists, `## Plan` present** → **revise mode.** Skip Step 2; the new Plan replaces the old one, and `## Tests` moves only if this chat's edit touches it.

Both modes read the existing `## Description` as context and go straight to Steps 3–6.

**Case 2 always continues at Step 2a**, existing file or not: the slug is only derived there, and `roadmap-item.md` step 5 is what decides whether a file already carrying it is *this item's* earlier capture (promote / revise, per the branch above) or an unrelated namesake (disambiguate and write fresh, never overwrite). This is the one way into Step 2 that promote / revise take, and they take **only** its slug and header metadata — never its Description draft; see Step 2a.

Case 4 has three sub-cases, in order: some `ROADMAPS:` line carries an `unchecked=` list other than `none` **and** there is nothing in the chat or `$ARGUMENTS` to draft from → `AskUserQuestion` (convention (c)), "How do you want to start this task?" — **Draft from this chat** / **Open from a roadmap**, the latter chipping the roadmap slugs and proceeding as Step 2a. There **is** chat discussion or free-form `$ARGUMENTS` (either alone is enough) → Step 2b. Neither → **stop**, rather than drafting from nothing: "nothing to capture yet — descri

Read more
Ships withtask

Docs & guides → spair.github.io/task-pipeline A plan file is only as good as the argument that produced it. That second line is where projects quietly go wrong: the model agrees and starts building before the plan was ever argued.

Get the whole plugin

Other skills on task.

grill
Skill

grill

Interrogate a plan or decision one question at a time before capture, keeping a decision-plus-rationale ledger, then route to the right capture skill.

@spair@spairView Skill