/to-task
Capture the chat (or a roadmap item) into `.task/task/<slug>.md` — `## Description` plus `## Plan` (Goal/Touches/Logic), and `## Tests` when the testing policy calls for it.
Claude Code
$ npx -y skills add SpaiR/task-pipeline --skill to-task --agent claude-code
Codex
$ npx skills add SpaiR/task-pipeline --skill to-task -a codex -y
Cursor
$ npx skills add SpaiR/task-pipeline --skill to-task -a cursor -y
Gemini CLI
$ npx skills add SpaiR/task-pipeline --skill to-task -a gemini-cli -y
GitHub Copilot
$ npx skills add SpaiR/task-pipeline --skill to-task -a github-copilot -y
OpenCode
$ npx skills add SpaiR/task-pipeline --skill to-task -a opencode -y
Windsurf
$ npx skills add SpaiR/task-pipeline --skill to-task -a windsurf -y
SKILL.md
to-task.SKILL.mdname: to-task
description: 'Capture the chat (or a roadmap item) into `.task/task/<slug>.md` — `## Description` plus `## Plan` (Goal/Touches/Logic), and `## Tests` when the testing policy calls for it.'
argument-hint: '[<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 one single-task capture: a task worth an artifact is a task whose approach is worth writing down, so the Plan is never optional. The slug is the filename; the artifact path is the handle, and a fresh session implements it by reading `## Execution`.
**Input:** `$ARGUMENTS` — optional. Recognized forms:
- (empty) — draft from the chat discussion so far; with no chat to draft from, open an item from a roadmap that has open items.
- `<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" capture`
[docs/contract.md § Helpers](../../docs/contract.md#helpers) owns that block's shape. Read it, then act:
1. `AI_DIR:` is the `.task` directory: `.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. Then continue 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 the file untouched: never rewrite it, re-detect its values or "repair" a missing section ([contract § `.task/CLAUDE.md` format](../../docs/contract.md#taskclaudemd-format)). 4. `ROADMAPS:` / `TASKS:` / `SPECS:` are what already exists. Step 1 branches on the roadmap lines and the slug-collision guards check `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.
Step 1: Entry
No pointer to resolve — the artifact path is the handle, and every run is a fresh capture. Branch on `$ARGUMENTS`:
1. `$ARGUMENTS` names a `ROADMAPS:` slug, with or without `#<N>`, or, when `ROADMAPS:` is not `none`, is shaped `<kebab-slug>#<digits>` whatever the slug → **from-roadmap mode**, Step 1a. (A mistyped slug stops at `roadmap-item.md` step 1, which lists the real ones, rather than being captured as a chat draft.) With `ROADMAPS: none` and no chat discussion to draft from, such an argument is a **stop**, writing nothing: "no roadmaps found under `.task/roadmap/` — create one, or describe the task in chat. → Next: `/task:to-roadmap`". With chat discussion, it is free-form context for rule 2. 2. Otherwise, chat discussion **or** free-form `$ARGUMENTS` to draft from — either alone is enough → **chat-draft mode**, Step 2. 3. Neither, but some `ROADMAPS:` line carries an `unchecked=` list other than `none` or `unreadable` → **from-roadmap mode** on a roadmap with open items: `AskUserQuestion` (convention (c)), "Which roadmap?", one chip per such slug — or take it when there is only one — then Step 1a. 4. Nothing at all → **stop** rather than drafting from nothing: "nothing to capture yet — describe the task in chat, or name it directly. → Next: `/task:to-task <what to capture>`"
Step 1a: From-roadmap mode
1. Follow `${CLAUDE_PLUGIN_ROOT}/skills/_lib/roadmap-item.md` — the one owner of the from-roadmap block, shared with the driver's plan agent: resolve the roadmap, pick `#<N>`, read the ready description, collect the spec slugs, derive `<item-slug>`, and check whose file it is. Its footers take this skill's own command, so a stop reads `→ Next: \`/task:to-task <slug>#3\``.
2. **Slug collision.** `roadmap-item.md` step 5 already separated this item's earlier capture from an unrelated namesake (the namesake gets a disambiguated slug and is never touched). When the file is **this item's own**, run the one sanctioned chip (convention (b)) before writing anything: state the existing file's headings as message text first ("Existing `.task/task/<item-slug>.md` has: Description, Plan (4 steps), Tests (2)."), then pose an `AskUserQuestion`: **Regenerate from the item** *(Recommended — the Description is re-derived from the ready description, so only the old Plan and any hand edits are replaced)* / **Decline — stop without writing**. Only the first chip earns `--force` in Step 7. **Decline** says plainly that nothing was written and closes with `→ Next: implement the existing file in a fresh session: \`implement .task/task/<item-slug>.md\``.
3. Hold what it produces for Step 7's write — the item title, the roadmap slug, `#<N>`, the distinct spec slugs, and the item's ready description, which `plan-driver.md` § Core step 4 turns into the Description (`roadmap-item.md` step 3 owns that mapping). Do not write the file yet: Description, Plan and Tests are assembled and written once, together, in Step 7. Continue to Steps 3–6.
Step 2: Chat-
Read more
name: to-task description: 'Capture the chat (or a roadmap item) into `.task/task/<slug>.md` — `## Description` plus `## Plan` (Goal/Touches/Logic), and `## Tests` when the testing policy calls for it.' argument-hint: '[<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 one single-task capture: a task worth an artifact is a task whose approach is worth writing down, so the Plan is never optional. The slug is the filename; the artifact path is the handle, and a fresh session implements it by reading `## Execution`.
**Input:** `$ARGUMENTS` — optional. Recognized forms:
- (empty) — draft from the chat discussion so far; with no chat to draft from, open an item from a roadmap that has open items.
- `<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" capture`
[docs/contract.md § Helpers](../../docs/contract.md#helpers) owns that block's shape. Read it, then act:
1. `AI_DIR:` is the `.task` directory: `.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. Then continue 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 the file untouched: never rewrite it, re-detect its values or "repair" a missing section ([contract § `.task/CLAUDE.md` format](../../docs/contract.md#taskclaudemd-format)). 4. `ROADMAPS:` / `TASKS:` / `SPECS:` are what already exists. Step 1 branches on the roadmap lines and the slug-collision guards check `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.
Step 1: Entry
No pointer to resolve — the artifact path is the handle, and every run is a fresh capture. Branch on `$ARGUMENTS`:
1. `$ARGUMENTS` names a `ROADMAPS:` slug, with or without `#<N>`, or, when `ROADMAPS:` is not `none`, is shaped `<kebab-slug>#<digits>` whatever the slug → **from-roadmap mode**, Step 1a. (A mistyped slug stops at `roadmap-item.md` step 1, which lists the real ones, rather than being captured as a chat draft.) With `ROADMAPS: none` and no chat discussion to draft from, such an argument is a **stop**, writing nothing: "no roadmaps found under `.task/roadmap/` — create one, or describe the task in chat. → Next: `/task:to-roadmap`". With chat discussion, it is free-form context for rule 2. 2. Otherwise, chat discussion **or** free-form `$ARGUMENTS` to draft from — either alone is enough → **chat-draft mode**, Step 2. 3. Neither, but some `ROADMAPS:` line carries an `unchecked=` list other than `none` or `unreadable` → **from-roadmap mode** on a roadmap with open items: `AskUserQuestion` (convention (c)), "Which roadmap?", one chip per such slug — or take it when there is only one — then Step 1a. 4. Nothing at all → **stop** rather than drafting from nothing: "nothing to capture yet — describe the task in chat, or name it directly. → Next: `/task:to-task <what to capture>`"
Step 1a: From-roadmap mode
1. Follow `${CLAUDE_PLUGIN_ROOT}/skills/_lib/roadmap-item.md` — the one owner of the from-roadmap block, shared with the driver's plan agent: resolve the roadmap, pick `#<N>`, read the ready description, collect the spec slugs, derive `<item-slug>`, and check whose file it is. Its footers take this skill's own command, so a stop reads `→ Next: \`/task:to-task <slug>#3\``.
2. **Slug collision.** `roadmap-item.md` step 5 already separated this item's earlier capture from an unrelated namesake (the namesake gets a disambiguated slug and is never touched). When the file is **this item's own**, run the one sanctioned chip (convention (b)) before writing anything: state the existing file's headings as message text first ("Existing `.task/task/<item-slug>.md` has: Description, Plan (4 steps), Tests (2)."), then pose an `AskUserQuestion`: **Regenerate from the item** *(Recommended — the Description is re-derived from the ready description, so only the old Plan and any hand edits are replaced)* / **Decline — stop without writing**. Only the first chip earns `--force` in Step 7. **Decline** says plainly that nothing was written and closes with `→ Next: implement the existing file in a fresh session: \`implement .task/task/<item-slug>.md\``.
3. Hold what it produces for Step 7's write — the item title, the roadmap slug, `#<N>`, the distinct spec slugs, and the item's ready description, which `plan-driver.md` § Core step 4 turns into the Description (`roadmap-item.md` step 3 owns that mapping). Do not write the file yet: Description, Plan and Tests are assembled and written once, together, in Step 7. Continue to Steps 3–6.
Step 2: Chat-
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.
Other skills on task.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about to-task.
- Which coding agents can use to-task?
- to-task installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

