Polyhydra Skills  /  Agent Workflow

haiku-storm

Fan out a batch of independent, well-specified housekeeping/recon/mechanical work across several parallel lanes at once instead of working through it serially. Lanes dispatch to Codex Luna by default, with Haiku reserved for lanes that need Claude Code's own tool surface (MCP servers, nested Agent calls, a named subagent type). Use on "haiku storm", "storm this", or when there's a pile of low-ambiguity work (close stale issues, clean up merged worktrees, survey a backlog, verify-and-report tasks) that splits cleanly into 3-5 independent lanes. Not for work that needs judgment, touches files another in-flight task is actively editing, or requires a GitHub issue that doesn't exist yet.

Agent Workflow

Drop this in — save the block below as ~/.claude/skills/haiku-storm/SKILL.md, or run:

mkdir -p ~/.claude/skills/haiku-storm
cat > ~/.claude/skills/haiku-storm/SKILL.md <<'EOF'
# (paste the full source block below into this file)
EOF

Full source

SKILL.md — copy everything inside
# Haiku storm

Dispatch several subagents in parallel, each carrying one independent,
self-contained lane of low-ambiguity work, and let them report back
concurrently instead of grinding through the list one item at a time. The
name is legacy — as of 2026-08-19 lanes default to **Codex Luna**, with
**Haiku** kept for the lanes Luna structurally can't do (see "Picking the
model per lane" below). Don't rename mid-flight if the routing default
flips again; check `~/.claude/CLAUDE.md`'s "Coding fan-out" section for
the live default before assuming this doc is current.

This is the "keep the forge well stocked" pattern: while you (the
orchestrator) do the sequential, judgment-heavy work only you can do — merge
conflict resolution, architectural decisions, PR review — the storm clears
everything around it that doesn't need that judgment.

## When to reach for this

Good storm material is **verify-and-act** or **survey** work, not
**design** work:

- Closing GitHub issues that are already resolved on `main`/`dev` but never
  got closed (verify the fix landed, cite the commit, close with a comment)
- Cleaning up merged-but-still-present git worktrees (confirm branch is
  merged and working tree is clean before removing)
- Surveying an open-issue backlog to shortlist the next batch of
  independent, well-scoped candidates (read-only, no mutations)
- Mechanical fixes with an established pattern to follow (e.g. "stub the
  missing dependency the same way the last five slices did")
- Repairing/retiring dead code flagged by a "good first issue"-style issue

Bad storm material — keep this on yourself or a Sonnet lane instead:

- Anything requiring an architectural call the issue doesn't already answer
- Work that touches a file another in-flight task (yours or a worker's) is
  actively editing — collision risk, not parallelism
- Code-changing work with no GitHub issue yet — issue-first still applies;
  a storm dispatches against existing issues, it doesn't skip creating them
- Merge conflict resolution — that stays with the orchestrator, always

## Picking the model per lane

Default every lane to **Codex Luna**. Move a lane to **Haiku** only when it
actually needs something Codex CLI can't reach:

- An MCP server call (GitKraken, Portainer, Seq, etc.)
- A nested `Agent` call (a lane that itself needs to fan out)
- A specific Claude subagent type (`Explore`, `general-purpose`, etc.)

Everything else — `gh`/`git` commands, file reads/edits, grep sweeps,
verify-then-close checks — is plain Bash/Read/Grep/Glob/Edit work Luna
handles the same as Haiku, at Codex-credit cost instead of Anthropic quota.
Don't run the same lane on both models to compare — pick one per lane and
move on; this isn't a bake-off.

## How to run one

1. **Scope 3-5 independent lanes.** Each lane must be completable without
   knowing what the others are doing, and must not write to a path another
   lane (or your own in-flight work) touches. If two candidate lanes would
   touch the same file, that's one lane, not two.
2. **Write each prompt like a ticket**, not a chat message — the subagent
   can't ask a follow-up and won't go read your READMEs to orient itself.
   Inline every fact it needs directly in the prompt: exact scope, the
   verification step before acting (don't trust a branch name or issue
   title alone — confirm the fix is actually on the target branch), the
   exact `gh`/`git` commands to use, and what to do if the assumption
   doesn't hold (leave it alone and report why, don't guess). A prompt that
   says "go check the project conventions first" is a scoping failure —
   the ticket itself should already contain whatever convention matters.
3. **Dispatch together in one pass**, mixed by lane per the model call above:
   - **Luna lanes** — `~/.claude/skills/delegate/scripts/delegate-codex.sh
     -m luna -s read-only "<ticket prompt>"` for read-only survey lanes, or
     with `-C <repo> -W <branch> --issue-url <issue>` for lanes that mutate
     (close an issue, remove a worktree, edit a file). Each call
     backgrounds and returns a log path — fire them all before checking
     any of them. See the `delegate` skill for the full flag reference.
   - **Haiku lanes** — `Agent` tool calls with `subagent_type:
     "haiku-storm-lane"` (bakes in `model: "haiku"` and a restricted,
     ticket-only tool set: `Bash`, `Read`, `Grep`, `Glob`, `Edit` — no
     `Agent`, no MCP, no skill preload), sent in the same response so they
     run concurrently in the background.

   Don't wait on one lane before sending the next, regardless of which
   model it's on.

   One thing neither dispatch path strips: Claude Code loads the full
   CLAUDE.md hierarchy (global `~/.claude/CLAUDE.md`, project CLAUDE.md)
   into every mutating Haiku subagent regardless of type, and a Luna
   worker gets whatever `AGENTS.md`/prompt context `delegate-codex.sh`
   passes it — there's no documented opt-out for either. The ticket-prompt
   discipline in step 2 is what actually keeps a lane focused despite that
   ambient context, not the dispatch path alone.
4. **Keep working while they run.** Continue your own sequential thread;
   the completion notifications arrive on their own schedule.
5. **Review before trusting.** Each subagent's report is a submission, not
   a verified result — skim what it actually closed/removed/found before
   treating the lane as done. A subagent closing an issue or removing a
   worktree is a real mutation; scope the prompt tightly enough that you're
   comfortable with it running unattended, and read the report when it
   lands.

## Why this works

The value isn't parallelism for its own sake — it's the split between work
that needs judgment and work that only needs verification:

- **Verification is cheap to parallelize; judgment isn't.** "Is this issue
  actually fixed on the target branch" or "is this worktree actually
  clean" are yes/no checks against ground truth. Four agents can each
  answer one independently without stepping on each other. "Should we
  merge this this way" can't be split the same way — it needs one thread
  holding the full context.
- **The orchestrator's time is the scarce resource, not compute.** Running
  a storm alongside your own sequential judgment work (a merge conflict, a
  design call) means the storm's wall-clock is free — it finishes while
  you're doing something only you could do anyway.
- **A lane that refuses to guess is worth more than one that finishes.**
  The pattern only stays trustworthy if lanes are scoped tight enough that
  "I'm not sure, here's why, I left it alone" is always an acceptable
  report — not just "issue closed" or "worktree removed." A storm that
  optimizes for lanes reporting done, instead of lanes reporting
  correctly, will eventually mutate something it shouldn't have.
- **Review-before-trust is not optional.** Every subagent report is a
  submission, not a verified result, regardless of how routine the lane
  looked going in.

## Worked example (generalized)

Four lanes dispatched together while the orchestrator resolved a live merge
conflict of its own, across two related repos (a client app and a service
it depends on):

1. Close issues in the client repo already fixed by merged-but-unlinked
   branches — verify each fix on the default branch before closing, cite
   the commit.
2. Close epic tracking issues in the service repo whose PRs had merged but
   never auto-closed — confirm PR state is `MERGED` and the diff matches
   the issue's scope first.
3. Clean up merged worktrees in the client repo with stray uncommitted
   lockfile diffs — diff first, discard only confirmed no-op churn, leave
   anything with real dependency changes in place and flag it.
4. Read-only survey of both repos' open-issue backlogs for the next batch
   of independent, unblocked candidates — no mutations, just a report.

All four ran concurrently; the orchestrator's own merge-conflict work
finished in parallel with them, and every lane's report was reviewed before
being treated as done. Lane 3 correctly refused to discard a worktree that
turned out to have a real new dependency added, flagging it back instead of
guessing — which is the whole pattern working as intended: the storm
cleared everything that was actually safe to clear, and handed back the one
thing that wasn't.