/fanout
Spawn a wave of JAT agents partitioned by file so they can't conflict, then get harness-notified when the wave is done.
$ npx -y skills add joewinke/jat --agent claude-codeHow it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/fanout
Context preview
What this command does when you run it.
Spawn a wave of JAT agents partitioned by file so they can't conflict, then get harness-notified when the wave is done.
Command definition
fanout.mdargument-hint: <taskId> <taskId> ... (the parallel wave to spawn)
description: Spawn a wave of JAT agents partitioned by file so they can't conflict, then get harness-notified when the wave is done.
/jat:fanout — Spawn a conflict-free wave of JAT agents, tracked to completion
Fan a set of tasks out to **real JAT agents** (full identity, signals, leases, `/work` board presence, token tracking) **and** bridge them to the Claude Code harness so you get re-invoked the moment the wave finishes — instead of babysitting them with manual polls.
> **You are the ORCHESTRATOR.** This skill spawns *other* agents; it does not start > your own task. Run it from a session that is coordinating the work.
When to use
- You have several independent tasks ready (`jt ready`) and want them worked in parallel.
- A larger piece decomposes into file-disjoint chunks (e.g. one new component per agent).
- Anytime you'd otherwise spawn agents and then repeatedly poll `jt show` by hand.
The one rule: partition by file
Two agents editing the same file in one shared checkout = merge hell (and silent clobbers — a sibling's merge can replace your pushed file). So **every agent in a wave must own a disjoint set of files.** The classic safe shape:
- **UI work → one NEW component file per agent.** Tell each agent: *build only your
component, take data via props/stores, DO NOT edit the shared page.* Mounting the components into the shared page/route is a **separate serial step** done by ONE agent afterward (see Step 5).
- **Non-UI work → name the exact files** each agent owns; refuse the wave if any two
footprints overlap.
Steps
1. Define the wave
For each task, decide its **footprint** (the globs it will touch) and model. Derive footprints from the task description, or set them. Example wave:
.7 → ide/src/lib/components/mobile/MobileAnswerSheet.svelte (sonnet)
.9 → ide/src/lib/components/mobile/MobileVerbSheet.svelte (sonnet)
.12 → ide/src/lib/components/mobile/MobileTerminalPeek.svelte (sonnet)
2. Partition guard (MANDATORY)
Verify no two footprints overlap before spawning. If they do, either re-scope a task to a disjoint file or move it to a later serial phase. Check existing leases too:
sqlite3 -noheader ~/.config/jat/file-leases.db "SELECT task_id, agent_name, globs FROM file_leases;"
2.5. Link the wave under an epic (MANDATORY)
A wave of loose sessions is hard to read on `/tasks` — you can't tell which of N running agents belong together. Fix this by making the wave an **epic with the spawned tasks as its children**. The `/tasks` active-sessions view groups every session under its epic header automatically (`getSessionsByEpic` keys off exactly the epic→child dependency edge), and `/epics` then shows the whole wave as one pilotable unit with its dependency graph. You get the grouping for free — you just have to wire the edge.
**Promote your orchestrator task to an epic** (the task this `/jat:fanout` session is running under), or create a fresh epic to hold the wave:
# Promote the orchestrator/fanout task itself:
jt update <orchestratorTaskId> --type epic
# (works on sqlite AND postgres projects — pg routes issue_type through the REST API)
# …or create a dedicated wave epic:
jt create "Wave: <what this batch does>" --type epic --priority 1 # capture its id → EPIC
Use that epic id as `EPIC` in Step 3. The children are wired at spawn time (the spawn API auto-links them when you pass `epicId` — see Step 3), so there's no separate `jt dep add` round-trip in the normal flow.
> **Direction matters:** the edge is **epic depends_on child** (epic is BLOCKED until > the wave finishes; each child stays READY to work). The spawn API and `jt dep add > EPIC CHILD` both write it in this direction. The epic naturally clears once every > child closes — a clean "wave done" signal.
2.6. Put YOURSELF in the picture (MANDATORY — the UX must express your role)
Wiring the children is not enough: **your own orchestrator session must also read as the wave's overseer on `/tasks`**, or the human sees N grouped workers plus one mystery "Independent" session that is secretly running the show. Two wires, both required, right after spawning (or immediately after arming the watchers in Step 4):
# (a) Group your session under the epic header — link YOUR task as a child too.
# (Skip if you promoted your own task to be the epic in Step 2.5.)
# Correct semantics: the wave isn't done until your serial integration/docs
# step closes, so the epic SHOULD wait on you.
jt dep add <EPIC> <yourOrchestratorTaskId>
# (b) Render the conducting/overseer chip — emit a working signal that carries
# the `orchestrating` payload (this is what the /tasks UI keys the cyan
# "conducting ▸N" badge off; the jat-wave-complete ownership claim adds the
# OVERSEER badge, but only this signal expresses WHAT you are conducting).
jat-signal working '{
"taskId": "<yourOrchestratorTaskId>",
"taskTitle": "<your task title>",
"approach": "Overseeing wave epic <EPIC>: jat-wave-complete driving <N> agents; serial integration after.",
"orchestrating": { "epicIds": ["<EPIC>"], "childTaskIds": ["<taskId>", "..."] }
}'If your session was previously in `review` state, emitting `working` here is correct — you have re-entered active work (overseeing + the serial step). Re-emit `review` when the whole wave and your serial step are done.
> `jat-wave-complete` also emits this signal automatically on your behalf when it > claims the wave (it resolves the epic from the task set's dep edges) — but emit it > yourself anyway when you orchestrate without the completer daemon, e.g. hand-rolled > watch loops or critical-path mode before the first completer run.
3. Scope + lease + spawn — per task
For UI/component tasks, write the **component-only scope** into the task description so the spawned agent reads it at `/jat:start` (it scans `.descrip
Read more
argument-hint: <taskId> <taskId> ... (the parallel wave to spawn) description: Spawn a wave of JAT agents partitioned by file so they can't conflict, then get harness-notified when the wave is done.
/jat:fanout — Spawn a conflict-free wave of JAT agents, tracked to completion
Fan a set of tasks out to **real JAT agents** (full identity, signals, leases, `/work` board presence, token tracking) **and** bridge them to the Claude Code harness so you get re-invoked the moment the wave finishes — instead of babysitting them with manual polls.
> **You are the ORCHESTRATOR.** This skill spawns *other* agents; it does not start > your own task. Run it from a session that is coordinating the work.
When to use
- You have several independent tasks ready (`jt ready`) and want them worked in parallel.
- A larger piece decomposes into file-disjoint chunks (e.g. one new component per agent).
- Anytime you'd otherwise spawn agents and then repeatedly poll `jt show` by hand.
The one rule: partition by file
Two agents editing the same file in one shared checkout = merge hell (and silent clobbers — a sibling's merge can replace your pushed file). So **every agent in a wave must own a disjoint set of files.** The classic safe shape:
- **UI work → one NEW component file per agent.** Tell each agent: *build only your
component, take data via props/stores, DO NOT edit the shared page.* Mounting the components into the shared page/route is a **separate serial step** done by ONE agent afterward (see Step 5).
- **Non-UI work → name the exact files** each agent owns; refuse the wave if any two
footprints overlap.
Steps
1. Define the wave
For each task, decide its **footprint** (the globs it will touch) and model. Derive footprints from the task description, or set them. Example wave:
.7 → ide/src/lib/components/mobile/MobileAnswerSheet.svelte (sonnet) .9 → ide/src/lib/components/mobile/MobileVerbSheet.svelte (sonnet) .12 → ide/src/lib/components/mobile/MobileTerminalPeek.svelte (sonnet)
2. Partition guard (MANDATORY)
Verify no two footprints overlap before spawning. If they do, either re-scope a task to a disjoint file or move it to a later serial phase. Check existing leases too:
sqlite3 -noheader ~/.config/jat/file-leases.db "SELECT task_id, agent_name, globs FROM file_leases;"
2.5. Link the wave under an epic (MANDATORY)
A wave of loose sessions is hard to read on `/tasks` — you can't tell which of N running agents belong together. Fix this by making the wave an **epic with the spawned tasks as its children**. The `/tasks` active-sessions view groups every session under its epic header automatically (`getSessionsByEpic` keys off exactly the epic→child dependency edge), and `/epics` then shows the whole wave as one pilotable unit with its dependency graph. You get the grouping for free — you just have to wire the edge.
**Promote your orchestrator task to an epic** (the task this `/jat:fanout` session is running under), or create a fresh epic to hold the wave:
# Promote the orchestrator/fanout task itself: jt update <orchestratorTaskId> --type epic # (works on sqlite AND postgres projects — pg routes issue_type through the REST API) # …or create a dedicated wave epic: jt create "Wave: <what this batch does>" --type epic --priority 1 # capture its id → EPIC
Use that epic id as `EPIC` in Step 3. The children are wired at spawn time (the spawn API auto-links them when you pass `epicId` — see Step 3), so there's no separate `jt dep add` round-trip in the normal flow.
> **Direction matters:** the edge is **epic depends_on child** (epic is BLOCKED until > the wave finishes; each child stays READY to work). The spawn API and `jt dep add > EPIC CHILD` both write it in this direction. The epic naturally clears once every > child closes — a clean "wave done" signal.
2.6. Put YOURSELF in the picture (MANDATORY — the UX must express your role)
Wiring the children is not enough: **your own orchestrator session must also read as the wave's overseer on `/tasks`**, or the human sees N grouped workers plus one mystery "Independent" session that is secretly running the show. Two wires, both required, right after spawning (or immediately after arming the watchers in Step 4):
# (a) Group your session under the epic header — link YOUR task as a child too.
# (Skip if you promoted your own task to be the epic in Step 2.5.)
# Correct semantics: the wave isn't done until your serial integration/docs
# step closes, so the epic SHOULD wait on you.
jt dep add <EPIC> <yourOrchestratorTaskId>
# (b) Render the conducting/overseer chip — emit a working signal that carries
# the `orchestrating` payload (this is what the /tasks UI keys the cyan
# "conducting ▸N" badge off; the jat-wave-complete ownership claim adds the
# OVERSEER badge, but only this signal expresses WHAT you are conducting).
jat-signal working '{
"taskId": "<yourOrchestratorTaskId>",
"taskTitle": "<your task title>",
"approach": "Overseeing wave epic <EPIC>: jat-wave-complete driving <N> agents; serial integration after.",
"orchestrating": { "epicIds": ["<EPIC>"], "childTaskIds": ["<taskId>", "..."] }
}'If your session was previously in `review` state, emitting `working` here is correct — you have re-entered active work (overseeing + the serial step). Re-emit `review` when the whole wave and your serial step are done.
> `jat-wave-complete` also emits this signal automatically on your behalf when it > claims the wave (it resolves the epic from the task set's dep edges) — but emit it > yourself anyway when you orchestrate without the completer daemon, e.g. hand-rolled > watch loops or critical-path mode before the first completer run.
3. Scope + lease + spawn — per task
For UI/component tasks, write the **component-only scope** into the task description so the spawned agent reads it at `/jat:start` (it scans `.descrip
Agents ship, suggest, repeat. You supervise — or they run on their own. JAT is the complete, self-contained environment for agentic development. Task management, agent orchestration, code editor, git integration, terminal access—all unified in a single IDE.
Repo: joewinke/jat
Other commands on jat.
- /adapt
/home/jw/code/jat/.agents/skills/adapt//SKILL.md
Open command - /animate
/home/jw/code/jat/.agents/skills/animate//SKILL.md
Open command - /arrange
/home/jw/code/jat/.agents/skills/arrange//SKILL.md
Open command - /audit
Runs the multi-agent fan-out + adversarial-verify audit pattern that produced `ide/docs/internal/optimization-audit-2026-06.md` — codified as a reusable, parameterizable Workflow (`.claude/workflows/forensic-audit.js`), so it no longer has to be re-derived by hand each time.
Open command - /bolder
/home/jw/code/jat/.agents/skills/bolder//SKILL.md
Open command - /clarify
/home/jw/code/jat/.agents/skills/clarify//SKILL.md
Open command

