tm
Task Master - plan, start, review, and close
Files1
View on GitHubSKILL.mdskills/tm/SKILL.md
GitHub<!-- floor:cold-verify-completion -->
Task Master Orchestrator
$ARGUMENTS
Thin orchestrator. Delegates to subagents for implementation and review loops.
Planning Mode (
/tm use stripe as kyc provider): When args don't match an existing tag, explores the codebase, writes a PRD, creates a tag, generates tasks, runs complexity analysis, and expands. Stops after planning - run/tm <tag>to start work.Marathon Mode (
/tm <tag>): When only a tag is given (no task-id), automatically progress through all ready tasks. When Agent Teams are available, each task gets its own teammate with shared task list. When teams unavailable, falls back to parallel subagents. PRs auto-merge when CI green, no conflicts, required approvals met, and 0 changes requested.
TM Work-Source Adapter
This command supplies the marathon skill's adapter as:
- enumerate —
task-master tags use "<tag>" && task-master list --json; usejqontasks.jsonfor reliable status filtering (task-master nextcan suggest subtask IDs of done parents). - mark in-progress —
task-master set-status --project ~/dev/github.com/<org>/<repo> --id=<id> --status=in-progress(run sequentially inline — never as a parallel background job; concurrent TM writes race the global tag). Every TM write passes--project <container root>:set-statushas no--tag, the shell cwd persists across calls, and a write run from<repo>-main/or a worktree prints its banner but writes nothing. Re-readtasks.jsonafter each write to confirm. - close on merge —
task-master tags use "<tag>" --project ~/dev/github.com/<org>/<repo> && task-master set-status --project ~/dev/github.com/<org>/<repo> --id=<id> --status=done(same rule: sequentially inline, never in parallel -tags useswitches the shared active tag, so an interleaved write lands on the wrong tag). - branch / worktree — branch
<tag>--<task-id>--<slug>; worktreeworktree/<tag>/<task-id>--<slug>.
Phase 0: Detect Capabilities
# Agent Teams
echo $CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
Set $TEAMS_AVAILABLE (true if result is "1").
Project-Specific Configuration
Read the repo's CLAUDE.md for a ## Marathon Configuration section. This provides project-specific overrides for marathon behavior. Extract these values (with defaults if section is missing):
| Setting | Default | Description |
|---|---|---|
$BASE_BRANCH |
main |
Branch to create worktrees from and merge PRs into |
$REQUIRED_APPROVALS |
1 | Minimum approvals for auto-merge |
$MARKDOWN_APPROVALS |
1 | Approvals for markdown-only PRs |
$RETRO_LOG |
(none) | Path to retrospective log file |
| Bot reviewer rules | (none) | Per-bot thread resolution patterns |
| CI patterns | (none) | Known flaky checks, pre-existing failures |
If no Marathon Configuration section exists, prompt the user to set one up before starting marathon mode:
No Marathon Configuration found in this project's CLAUDE.md.
For best results, add a ## Marathon Configuration section to your project's CLAUDE.md.
Run `/tm-marathon-config-example` to see the template, then copy and customize it.
Proceeding with defaults: base branch=main, 1 approval, no bot reviewer rules.
Defaults apply for non-marathon use (single task mode, planning mode) without prompting. The template below uses $BASE_BRANCH where previous versions hardcoded develop.
Phase 1: Detect Context and Mode
Parse arguments to determine mode:
- No arguments → Report mode
- One argument that matches an existing TM tag → Marathon mode (
$MARATHON_MODE = true) - Two arguments (tag + task-id) → Single task mode
- Arguments that don't match any existing tag → Planning mode (
$PLANNING_MODE = true)
Tag match check (use tasks.json directly - CLI output has formatting that breaks grep):
cd ~/dev/github.com/<org>/<repo>
FIRST_ARG="<first-argument>"
jq -e --arg tag "$FIRST_ARG" '.[$tag]' .taskmaster/tasks/tasks.json >/dev/null 2>&1 && echo "TAG_EXISTS" || echo "NEW_IDEA"
If NEW_IDEA, search for existing PRD in the repo:
cd ~/dev/github.com/<org>/<repo>/<repo>-main
# Search common PRD locations and filename patterns
fd -t f "$FIRST_ARG" --extension md . | head -5
# Also check conventional path
ls .taskmaster/prd/$FIRST_ARG.md 2>/dev/null
- File found →
$PLANNING_MODE = true,$PRD_EXISTS = true,$PRD_FILE = <path> - No match →
$PLANNING_MODE = true,$PRD_EXISTS = false
Early routes:
- If
$PLANNING_MODE: Jump to Planning Mode - If
$MARATHON_MODEAND$TEAMS_AVAILABLE: Jump to Marathon Mode: Agent Teams
Check context in order:
- Current directory - pwd matches TM worktree pattern?
- Conversation context - Recent "📍 Current Work" footer with worktree path?
- Arguments - Explicit tag/task-id provided?
Detect Worktree Pattern
pwd | grep -q '/worktree/[^/]*/[^/]*--' && echo "IN_WORKTREE" || echo "NOT_IN_WORKTREE"
If IN_WORKTREE: Extract tag and task-id from path, proceed with PR check. If NOT_IN_WORKTREE but conversation shows active work: cd to the worktree.
Decision tree:
Is current directory a TM worktree?
(Pattern: worktree/<tag>/<task-id>--<slug>)
│
├─ YES → Check PR state
│ ├─ PR merged → CLEANUP mode
│ ├─ PR open → REVIEW mode
│ └─ No PR → IMPLEMENT mode
│
└─ NO → START mode
├─ Args match existing tag → Marathon or single task
├─ Args don't match any tag → PLANNING mode
└─ No args → Report ready tasks
CRITICAL: Never auto-start new tasks. Conversation context can continue existing work, but starting a NEW task requires explicit $ARGUMENTS.
Check PR State
gh pr view --json number,state,mergedAt 2>/dev/null
| Condition | Action |
|---|---|
mergedAt is set |
CLEANUP mode |
| PR exists, open | REVIEW mode |
| No PR | IMPLEMENT mode |
Planning Mode
If $PRD_EXISTS: Fast path - PRD already written, go straight to task generation.
If not: Slow path - explore codebase and write the PRD first.
Fast Path (PRD exists)
Step 1: Read PRD and Estimate Task Count
TAG_NAME="$FIRST_ARG"
# $PRD_FILE set during Phase 1 detection
Read the PRD. Estimate how many top-level tasks it should produce, optimizing for maximum concurrency - prefer many independent tasks over fewer sequential ones. Consider:
- Each distinct module/component/endpoint = separate task
- Shared infrastructure (types, config, migrations) = early task others depend on
- Tests that can run independently = separate tasks
- Documentation = separate task (parallelizes with everything)
Step 2: Parse PRD as New Tag
cd ~/dev/github.com/<org>/<repo>
task-master tags add "$TAG_NAME"
task-master tags use "$TAG_NAME"
task-master parse-prd --input="$PRD_FILE" --num-tasks=<estimated-count>
Step 3: Complexity Analysis
task-master analyze-complexity --research
Step 4: Expand into Subtasks
task-master tags use "$TAG_NAME" && task-master list --json
Expand tasks with complexity >= 5 that are not already done:
# NEVER expand done tasks — creates phantom subtasks that are busywork to close.
# If a parent is merged, create new peer tasks instead.
for TASK_ID in <high-complexity-pending-task-ids>; do
task-master expand --id=$TASK_ID --research
done
Step 5: Validate Dependency Graph
Review the generated dependency tree and optimize for concurrency:
- Challenge sequential dependencies - are they genuinely blocking or just ordered by convention?
- Identify tasks that could run in parallel but are chained
- Apply fixes:
task-master update-task --id=<task-id> --prompt="Remove dependency on task <X>, these are independent" - Report the optimized plan (see Report and Stop)
Slow Path (New idea, no PRD)
Input: $ARGUMENTS - natural language description (e.g., "use stripe as another kyc provider")
Step 1: Explore the Codebase
Use Glob, Grep, Read - or spawn an Explore agent for deeper investigation. Focus on:
- Existing patterns the feature should follow
- Files and modules that would be touched
- Integration points and dependencies
Step 2: Write the PRD
TAG_NAME="<derived-tag-name>" # lowercase, hyphens, max 40 chars
mkdir -p ~/dev/github.com/<org>/<repo>/.taskmaster/prd
PRD structure:
# <Feature Title>
## Problem Statement
## Technical Context
## Solution
## Scope
## Success Criteria
## Complexity Estimate
Step 3-5: Same as Fast Path
Create tag, parse PRD, complexity analysis, expand, validate dependencies.
Report and Stop
## Planned: <tag-name>
PRD: .taskmaster/prd/<tag-name>.md
| Task | Title | Points | Subtasks | Deps |
|------|-------|--------|----------|------|
**Total**: <N> points across <M> tasks
**Critical path**: <task-ids> (<P> points sequential)
**Parallel capacity**: <K> tasks can run concurrently in first wave
Next: `/clear` then `/tm <tag-name>`
Do NOT start implementation. Planning mode produces the plan only.
Start Mode (Not in worktree)
No Arguments → Report Only
task-master list --all-tags --ready --json
Report ready tasks and terminate. Do NOT launch subagent.
With Arguments → Setup then Implement
Step 1: Setup
cd ~/dev/github.com/<org>/<repo>/<repo>-main
git checkout $BASE_BRANCH && git pull origin $BASE_BRANCH
git branch <tag>--<task-id>--<slug>
mkdir -p ../worktree/<tag>
git worktree add ../worktree/<tag>/<task-id>--<slug> <tag>--<task-id>--<slug>
cd ~/dev/github.com/<org>/<repo>
task-master tags use "<tag>" && task-master set-status --id="<task-id>" --status=in-progress
cd ~/dev/github.com/<org>/<repo>/worktree/<tag>/<task-id>--<slug>
Step 2: Get task details
task-master show <task-id> --json
Step 3: Implement - See Implement Mode below.
Worktree Modes
Derive context from path:
TAG=$(basename $(dirname "$(pwd)"))
TASK_DIR=$(basename "$(pwd)")
TASK_ID="${TASK_DIR%%--*}"
Mode: Cleanup
cd to repo root first (subagent will delete the worktree).
Agent(
subagent_type: "general-purpose",
model: "sonnet",
prompt: "PR merged for <tag>.<task-id>. From ~/dev/github.com/<org>/<repo>: mark task done, remove worktree, delete branch."
)
Post-Cleanup (Marathon, no teams): Check for next ready tasks:
task-master tags use "<tag>" && task-master list --ready --json
- No ready → Report tag complete, terminate
- 1 ready → Start that task
- Multiple independent → Spawn parallel agents
Mode: Review (PR open)
Use the pr-review-merge skill to drive PR #<number> to merge-ready (6 criteria, thread
rules, background CI watcher). When all criteria are met, output <promise>PR_READY</promise>.
Mode: Implement or Create PR
Agent(
subagent_type: "general-purpose",
model: "sonnet",
prompt: "Implement <tag>.<task-id>: <task-title> in <worktree-path>. Requirements: <task-description-and-subtasks>. TDD, push, create PR, use the pr-review-merge skill for the review loop. Report: ready, waiting, or blocked."
)
Marathon Mode: Entry Gate (non-removable)
Before starting ANY marathon run - Agent Teams or Subagent Fallback, before the first task is decomposed - invoke the acceptance-contract start gate. The run identifier is the TM tag.
The contract scripts live in the plugin package (${CLAUDE_PLUGIN_ROOT}/scripts/contract/), while the contract artifacts (contract, kill test, completion record) live in the target repository's .claude/contracts/ by default. Every contract script resolves the folder the same way: its --contract-dir flag, then the ACCEPTANCE_CONTRACT_DIR environment variable, then the default, so setting the variable once moves the folder for the whole run. A repo that already keeps its contracts in .taskmaster/contract/ and has no .claude/contracts/ keeps using .taskmaster/contract/. When the agent cannot write under .claude/ without a permission prompt, set ACCEPTANCE_CONTRACT_DIR to a folder it can write to. When CLAUDE_PLUGIN_ROOT is unset (a hand-placed checkout rather than an installed plugin) the guard line before each invocation falls back to the current checkout.
: "${CLAUDE_PLUGIN_ROOT:=.}" # unset outside an installed plugin: fall back to the current checkout
python "${CLAUDE_PLUGIN_ROOT}/scripts/contract/start_gate.py" "<tag>"
The gate fails closed. Exactly two doors open a run; there is no silent third:
- Frozen contract - freeze evidence for
<tag>is recorded (the contract's sha256 frozen before decomposition, with a passing kill test): exit 0, proceed. - Operator-signed skip - no valid freeze, but an
operator_signoffis recorded before the run starts: exit 0 with a loud UNVERIFIED warning. The skip is capped, not free - the run is permanently capped atUNVERIFIEDand can NEVER certifyPASS. - Neither - non-zero exit. Do NOT start the run: freeze a contract
(
${CLAUDE_PLUGIN_ROOT}/scripts/contract/freeze.py) or record a signed skip first.
The exit-side gates are owned by the marathon skill, not this command. Marathon
routes every verifier spawn through ${CLAUDE_PLUGIN_ROOT}/scripts/contract/spawn_verifier.py (the
custody chokepoint) and blocks run-complete on ${CLAUDE_PLUGIN_ROOT}/scripts/contract/complete_gate.py <tag>. Start gate here, exit gates there - each fails closed. The
<!-- floor:cold-verify-completion --> marker in this file's header makes this
invocation un-removable: floor.yml reds any PR that drops the marker or any of
the three gate invocation strings from a file that carried them.
Marathon Mode: Agent Teams
Prerequisite: $MARATHON_MODE AND $TEAMS_AVAILABLE.
First run the Entry Gate above.
Use the marathon skill, supplying the TM Work-Source Adapter above and the Marathon Configuration values from Phase 0. The skill owns DAG/hot-file analysis, team lifecycle, waves, crash recovery, and the retrospective; it drives each PR via pr-review-merge.
Marathon Mode: Subagent Fallback
When $MARATHON_MODE but $TEAMS_AVAILABLE is false, the marathon skill's Subagent
Fallback runs parallel subagents after each cleanup cycle using the TM adapter.
Orchestrator Flow
/tm [args...] → detect capabilities → parse args → route:
│
├─ Args don't match tag → PLANNING (explore → PRD → tasks → expand → stop)
│
├─ Marathon + Teams → AGENT TEAMS (spawn teammates, smart-merge, waves)
│
├─ No PR → IMPLEMENT (subagent)
├─ PR open → REVIEW (subagent)
├─ PR merged → CLEANUP → (marathon? check next ready)
│
└─ No context → report ready tasks