Room 42, home

Workflows that Compound

Turn repeatable multi-step tasks into pipelines by chaining custom slash commands, plan mode, structured hand-offs, and fan-out subagents inside Claude Code.

Codingintermediate7 min readUpdated 12 Jun 2026

In short

  1. 01A compounding pipeline chains plan, worker, synthesize, and verify steps so the same task runs faster and cleaner every time.
  2. 02Pass typed JSON between steps inside Claude Code custom slash commands so each hand-off is inspectable and reliable.
  3. 03Fan out independent workers in parallel, then collapse their results into one synthesis and a single PASS or FAIL verdict.
  4. 04Script anything you can enumerate in plain shell and let Claude handle only the steps that need judgment, with a capped retry loop.
Contents · 12 sections
  1. 1What does a compounding pipeline look like?
  2. 2Step 1: extract a structured plan with plan mode
  3. 3Step 2: worker commands that emit typed results
  4. 4Step 3: fan-out then synthesize
  5. 5Step 4: verify against the plan
  6. 6How do I pass structured output between steps?
  7. 7When should I script a step versus let Claude drive it?
  8. 8When should I use subagents?
  9. 9What are skills in a pipeline?
  10. 10Effort and cost checkpoints
  11. 11Prompt templates as pipeline currency
  12. 12Checklist before shipping a pipeline

A one-shot prompt solves one problem. A pipeline solves the same problem every time, faster, and with each run making the next run cheaper. This guide is about building those pipelines inside Claude Code: the plan-act-verify loop, passing structured data between steps, fan-out with subagents, and deciding when to script the glue deterministically versus let Claude drive.

You will not call the API in code here; Claude writes that code. You will chain work in the CLI itself, through custom commands, skills, and plan mode, so the pipeline lives in your project and every teammate can run it.

What does a compounding pipeline look like?

Every useful pipeline follows the same skeleton:

The loop from verifier back to planner is where compounding happens. A failed run produces a richer context for the retry: the original plan, the worker outputs, and the verifier diagnosis all feed the next attempt. Correctness rises faster than cost.

Step 1: extract a structured plan with plan mode

Never hand a raw user string straight to a worker step. Use plan modeShift+Tab in Claude Code toggles plan mode: Claude proposes a plan and waits for approval before taking any action to turn the request into a structured spec your later steps can rely on.

Press Shift+Tab before typing your prompt. Claude will lay out the goal, subtasks, and success criteria as a numbered list and wait for your go-ahead. You review, edit, or approve, and only then does work begin.

For a pipeline you run repeatedly, encode that planning step as a custom slash command so no one has to remember the incantation.

<!-- .claude/commands/plan.md -->
You are the planner for this pipeline. Given the user's request, produce a
structured work plan with these fields and nothing else:
 
- **goal**: one sentence describing the end state
- **subtasks**: numbered list, each with an id, instruction, and any
  dependencies noted in parentheses
- **success_criteria**: one sentence the verifier will use to judge the output
 
Do not begin any work. Emit the plan, then stop and wait for approval.

Run it with:

claude /plan "audit every component for missing aria labels"

Claude returns the plan. You approve it (or edit a subtask inline), then move to the next command.

Tip: if your planner tends to over-split, add a constraint to the command file: "Produce at most five subtasks. Merge anything that can share a single context window."

Step 2: worker commands that emit typed results

Each worker receives one subtask and emits a structured result. Write a command file per worker type, or a single parameterised worker command.

<!-- .claude/commands/worker.md -->
You are a focused worker completing exactly one subtask. Do not speculate
beyond the task scope.
 
You will receive:
- **subtask_id** in $ARGUMENTS (first token)
- **instruction** in $ARGUMENTS (remainder)
 
When finished, emit a fenced JSON block with this shape and nothing else:
 
```json
{
  "subtask_id": "<id>",
  "output": "<your finding or change summary>",
  "confidence": 0.0
}

Confidence is a number from 0 to 1 reflecting how certain you are the output is complete and correct.


Run a worker for one subtask:

```bash
claude /worker "aria-scan Scan src/components/ for missing aria-label props"

Claude reads only the files relevant to that subtask, emits the JSON block, and stops. You collect these blocks for the synthesizer.

FieldPurpose
subtask_idTies the result back to the plan
outputThe finding, change, or artifact
confidenceLets the synthesizer weigh contradictions

Step 3: fan-out then synthesize

Fan-out means running independent workers at the same time. In Claude Code you can open multiple terminal panes and fire each worker command in parallel, or use claude --dangerously-skip-permissions in CI with & to background jobs.Common gotchaA backgrounded worker that crashes or hits a rate limit does not stop the run: wait ignores the failed job's exit code even under set -e, so the synthesizer proceeds on a half-empty result file.Capture each job's PID, wait on it individually, and check $? per worker before merging.

claude /worker "aria-scan Scan src/components/ for missing aria-label props" \
  > results/aria-scan.json &
 
claude /worker "focus-order Verify keyboard tab order in forms" \
  > results/focus-order.json &
 
claude /worker "color-contrast Check contrast ratios in tailwind classes" \
  > results/color-contrast.json &
 
wait

After fan-out, pass all result files to the synthesizer:

<!-- .claude/commands/synthesize.md -->
You are the synthesizer. You receive multiple worker result JSON blocks.
Collapse them into one coherent summary:
 
1. List every finding, grouped by subtask.
2. Where two workers contradict each other, cite their confidence scores and
   resolve in favour of the higher-confidence result.
3. Produce a final recommendations list ordered by severity.
4. End with a one-line verdict: PASS or FAIL and why.
 
The plan's success_criteria is provided in $ARGUMENTS.
claude /synthesize "zero missing aria labels and all contrast ratios >= 4.5" \
  < <(cat results/*.json)

Step 4: verify against the plan

The verifier checks the synthesis against the original success_criteria and returns a structured verdict. Write it as a command:

<!-- .claude/commands/verify.md -->
You are the verifier. You receive the plan's success_criteria in $ARGUMENTS
and the synthesized output on stdin.
 
Emit only a fenced JSON block:
 
```json
{
  "passed": true,
  "diagnosis": "All criteria met." 
}

If passed is false, diagnosis must name the specific criterion that failed and what evidence in the synthesis led to that conclusion.


```bash
claude /verify "zero missing aria labels and all contrast ratios >= 4.5" \
  < synthesis.md

If passed is false, append the diagnosis to your next /plan call:

claude /plan "audit every component for missing aria labels -- previous attempt
failed: color-contrast worker reported 3 components untested"

Cap retries at two or three in your shell script. A pipeline that retries indefinitely has a bad planner prompt, not a transient error.

How do I pass structured output between steps?

The contract between steps is what makes the pipeline reliable. Each command produces a known shape; the next command expects that shape.

StepReceivesEmits
/planRaw user stringPlan (goal, subtasks, success_criteria)
/workerOne subtask id + instructionResult JSON (subtask_id, output, confidence)
/synthesizePlan criteria + all Result JSONsProse summary + PASS/FAIL line
/verifyCriteria + synthesisVerdict JSON (passed, diagnosis)

Because each hand-off is text you can inspect in the terminal, debugging is straightforward. If something looks wrong, open the intermediate file and read it. No debugger required.Common gotchaThe trap is assuming Claude emits clean JSON when a downstream jq reads it.Claude often wraps the block in a json fence or adds a sentence before it, so `jq -r '.passed'` parses nothing and your loop treats a pass as a fail. Strip the fences first (pipe through `sed '/^/d'or extract the braces with a tiny script) before piping any worker or verifier output intojq`.

When should I script a step versus let Claude drive it?

This is the most consequential design decision in pipeline work. Get it wrong and you end up with either a brittle hand-coded state machine or Claude burning effort on decisions that need no judgment.

SituationUse
Fixed number of steps with known shapeShell script
Subtask count and type vary by input/plan command
Branching on a boolean flagif in shell
Deciding which of N strategies fitsClaude-driven planning
Retrying after a known error classfor loop in shell
Diagnosing an unexpected failure/verify command
Parsing a well-defined JSON responsejq in shell
Extracting fields from free-form textClaude-driven extraction

The practical rule: script anything you can enumerate. Let Claude handle anything that requires reading content to decide. A mixed pipeline is not a compromise, it is the goal. Shell steps are fast, free, and predictable. Claude steps are where judgment lives.

Example: deterministic retry wrapper

#!/usr/bin/env bash
set -euo pipefail
 
CRITERIA="zero missing aria labels and all contrast ratios >= 4.5"
MAX_RETRIES=3
DIAGNOSIS=""
 
for attempt in $(seq 1 $MAX_RETRIES); do
  PROMPT="audit every component for missing aria labels"
  if [[ -n "$DIAGNOSIS" ]]; then
    PROMPT="$PROMPT -- previous attempt failed: $DIAGNOSIS"
  fi
 
  claude /plan "$PROMPT" > plan.md
 
  # fan-out workers (adjust ids from plan.md as needed)
  claude /worker "aria-scan Scan src/components/" > results/aria-scan.json &
  claude /worker "focus-order Verify keyboard tab order" > results/focus-order.json &
  claude /worker "color-contrast Check contrast ratios" > results/color-contrast.json &
  wait
 
  claude /synthesize "$CRITERIA" < <(cat results/*.json) > synthesis.md
  VERDICT=$(claude /verify "$CRITERIA" < synthesis.md)
 
  PASSED=$(echo "$VERDICT" | jq -r '.passed')
  DIAGNOSIS=$(echo "$VERDICT" | jq -r '.diagnosis')
 
  if [[ "$PASSED" == "true" ]]; then
    echo "Pipeline passed on attempt $attempt."
    cat synthesis.md
    exit 0
  fi
 
  echo "Attempt $attempt failed: $DIAGNOSIS"
done
 
echo "Pipeline failed after $MAX_RETRIES attempts: $DIAGNOSIS" >&2
exit 1

The retry logic is deterministic shell. Only the diagnosis that drives the next planning call is Claude-generated.

When should I use subagents?

Everything above assumes workers are focused, single-step Claude invocations. When a worker needs to execute code, run tests, browse the web, or operate the file system across many files, you reach for subagentsClaude Code spawned with its own context window and tool set, running autonomously until a stopping condition.

In Claude Code, subagents are ordinary claude processes with their own context. The orchestrator never sees the raw execution noise, only the typed result the subagent emits at the end.

Reach for subagents when:

  • A worker needs more than one tool call to finish its task.
  • You want the worker's context capped separately from the orchestrator's.
  • You need the worker's execution to be auditable independently (each subagent session has its own transcript).

What are skills in a pipeline?

A skillA markdown file in .claude/skills/ that teaches Claude a repeatable capability, loadable on demand is a markdown file that encodes a repeatable capability. Where a command runs a specific task, a skill teaches Claude how to perform a class of tasks. The commands and skills guide covers which of each are worth building.

<!-- .claude/skills/structured-audit.md -->
# Structured audit
 
When asked to audit code, always:
1. Scope the audit to the directory or file pattern named in the request.
2. Emit findings as a JSON array: [{ "file", "line", "severity", "description" }].
3. After the array, write a one-line summary: N findings, highest severity X.
4. Do not fix anything unless explicitly told to fix.

Load the skill in your command file with @skills/structured-audit at the top, or reference it in your CLAUDE.md so it is always active.

Skills compose. A pipeline can load an audit skill for the worker stage and a synthesis skill for the collapse stage, keeping each command file short and focused.

Effort and cost checkpoints

Before running a full fan-out pipeline, use /cost to see the current session spend and /effort (or the effort slider in the UI) to set how deep Claude searches within each command.

StageRecommended effort
PlanningHigh: a good plan saves retries
Workers (well-scoped subtasks)Low to medium
SynthesisMedium
VerificationLow: the criteria are explicit

Higher effort means more tool calls and a larger context scan per step. On a ten-subtask pipeline, the difference between low and high effort on workers can be 3x the token spend with marginal accuracy gain. Tune workers first.

Prompt templates as pipeline currency

Prompt templatesA reusable string with named placeholders filled at runtime, versioned separately from orchestration logic are what let a pipeline scale. Keep them as command files in .claude/commands/ rather than composing strings inline. Versioning templates separately from shell glue means you can tune behaviour through prompt iteration without touching the orchestration logic, and you can A/B test a planner command against a production baseline by swapping one file.

# test a new planner against the current one
cp .claude/commands/plan.md .claude/commands/plan-v2.md
# edit plan-v2.md, then compare outputs
claude /plan-v2 "audit every component" > plan-v2.md
diff plan.md plan-v2.md
Try this prompt
Set up a three-stage pipeline in .claude/commands/ for a code-quality audit: a /plan command that scopes the audit, a /worker command that scans one directory and emits findings as JSON, and a /verify command that checks the findings list against a severity threshold. Show the shell script that fans out workers and retries once on failure.

Checklist before shipping a pipeline

  • Every Claude-to-Claude hand-off passes a typed JSON block, not raw prose.
  • Worker commands are scoped: each touches one directory or one concern.
  • Fan-out runs concurrently with & and wait, not sequentially.
  • The /verify command receives the exact success_criteria string from the plan.
  • Retry count is capped and the cap is enforced in shell, not by Claude.
  • Effort is tuned per stage: high for planning, low-to-medium for well-scoped workers.
  • Each command file is under 60 lines. Long commands are a sign the stage is doing too much.

The guides on Multi-Agent Architectures and Claude Code Workflows cover the broader ecosystem these pipelines live in. The pattern here is the building block: one typed spec, parallel workers, one synthesis, one verdict, and a clean retry path, all wired together in plain shell and .claude/commands/.