Skill

kage-bunshin

Spawn and manage persistent interactive Claude Code CLI sessions with bidirectional communication via tmux. Provides spawn, send, read, status, list, and kill subcommands for orchestrating parallel peer sessions. Uses built-in --worktree and --tmux flags. Sessions stay alive for multi-turn steering. Triggers on "spawn claude session", "launch separate claude", "peer session", "inter-session communication", "shadow clone", "kage bunshin".

From dh
Install
1
Run in your terminal
$
npx claudepluginhub jamie-bitflight/claude_skills --plugin development-harness
Tool Access

This skill uses the workspace's default tool permissions.

Supporting Assets
View in Repository
references/stream-json-protocol.md
scripts/spawn.py
tests/test_spawn.py
Skill Content

Kage Bunshin — Persistent Peer Claude Sessions

Spawn independent interactive claude CLI sessions in tmux with full bidirectional communication. The orchestrator can send messages, read responses, monitor status, and steer work mid-flight via tmux send-keys and tmux capture-pane.

This is NOT a subagent or teammate — it is an independent CLI process with its own context window, inheriting all MCP servers, skills, plugins, and agents from the project directory.

Session Manager Script

All operations go through ${CLAUDE_SKILL_DIR}/scripts/spawn.py:

spawn.py spawn  --name X [--model MODEL] [--max-budget N] "prompt"
spawn.py send   --name X "message"
spawn.py read   --name X
spawn.py status --name X
spawn.py list
spawn.py kill   --name X

Quick Start

SPAWN="${CLAUDE_SKILL_DIR}/scripts/spawn.py"

# 1. Spawn a session (interactive claude in tmux + worktree)
$SPAWN spawn --name worker-42 --model haiku \
  "Load /dh:work-backlog-item #42. Execute the full work flow."

# 2. Check on it
$SPAWN status --name worker-42

# 3. Read what's on screen
$SPAWN read --name worker-42

# 4. Steer mid-flight
$SPAWN send --name worker-42 \
  "Stop current work. Prioritize the auth module instead."

# 5. Clean up when done
$SPAWN kill --name worker-42

How It Works

flowchart TD
    Start(["spawn called"]) --> Verify["Verify claude and tmux in PATH"]
    Verify --> Check{"Session name<br>already in registry?"}
    Check -->|"Alive"| Fail["Exit 1: kill it first"]
    Check -->|"Dead entry"| Clean["Remove stale entry"]
    Check -->|"Not found"| Launch
    Clean --> Launch["tmux new-session -d wrapping<br>claude --worktree {name} --tmux<br>--dangerously-skip-permissions --model {model}"]
    Launch --> Wait["Wait for claude REPL to initialize<br>(3 seconds)"]
    Wait --> Prompt["Send initial prompt via<br>tmux send-keys"]
    Prompt --> Register["Save to registry.json"]
    Register --> Print["Print JSON record to stdout"]

The claude CLI's built-in --worktree creates a git worktree at .claude/worktrees/{name}. The built-in --tmux creates a tmux session named {repo}_worktree-{name}. The script wraps the launch in tmux new-session -d to provide the TTY that --tmux requires in headless environments.

Subcommand Reference

spawn

Launch a new persistent interactive claude session in tmux.

$SPAWN spawn --name my-session --model haiku "Your initial prompt"
$SPAWN spawn --name my-session --max-budget 5.00 "Your prompt"

Flags:

  • --name — Session name (auto-derived from first 30 chars of prompt if omitted)
  • --model — Model for the spawned session (default: sonnet)
  • --max-budget — Maximum USD spend cap

Output (JSON to stdout):

{
  "name": "worker-42",
  "tmux_session": "claude_skills_worktree-worker-42",
  "model": "haiku",
  "spawned_at": "2026-03-22T01:30:00+00:00",
  "worktree": true
}

Every session gets its own git worktree via the built-in --worktree flag. Configure worktree.symlinkDirectories in project settings to share .venv, node_modules, etc. across worktrees.

send

Send a message to a running session via tmux send-keys.

$SPAWN send --name worker-42 "Check the test results and report back"

Types the message into the session's interactive REPL as if a human typed it. The session processes it as a new conversation turn. Use this to steer, redirect, or provide additional context.

read

Read the current screen content from a session via tmux capture-pane.

$SPAWN read --name worker-42

Captures the last 200 lines of the tmux pane output. Shows the rendered conversation including prompts, responses, and tool use.

status

Check session health.

$SPAWN status --name worker-42

Reports whether the tmux session is alive, the model, age, and tmux session name.

list

List all registered sessions with live/dead status.

$SPAWN list

Prints a columnar table: NAME, MODEL, STATUS (alive/dead), AGE, TMUX_SESSION.

kill

Terminate a session and clean up.

$SPAWN kill --name worker-42

Kills the tmux session and updates the registry. A TaskCompleted hook automatically reminds the orchestrator to clean up any sessions that outlive their tasks.

Session State

The registry is stored at ~/.dh/projects/{slug}/kage-bunshin/registry.json. The {slug} is derived from the git repo root path by replacing / with - (leading hyphen is intentional). Override the base directory with DH_STATE_HOME environment variable.

Capability Inheritance

A spawned session inherits identical capabilities when launched from the same working directory:

flowchart LR
    CWD["Same working directory"] --> P1[".mcp.json — project MCP servers"]
    CWD --> P2["~/.claude.json — user/local MCP servers"]
    CWD --> P3[".claude/CLAUDE.md — project instructions"]
    CWD --> P4["~/.claude/plugins/cache/ — installed plugins"]
    CWD --> P5[".claude/skills/ — project skills"]

Flags that break inheritance — do not use:

  • --bare — strips auto-discovery of CLAUDE.md, hooks, plugins, MCP
  • --strict-mcp-config — overrides inherited MCP servers
  • --disable-slash-commands — removes skill access

Worktree Settings

Configure these in your project or user settings to share heavy directories across worktrees:

{
  "worktree.symlinkDirectories": [".venv", "node_modules", ".cache"]
}

Parallel Fleet Management

Spawn and control multiple coordinators simultaneously. Each returns immediately.

SPAWN="${CLAUDE_SKILL_DIR}/scripts/spawn.py"
ITEMS=(10 11 12 13 14 15 16 17 18 19)

# Spawn all coordinators
for ITEM in "${ITEMS[@]}"; do
  $SPAWN spawn --name "coord-${ITEM}" --model haiku \
    "Load /dh:work-backlog-item #${ITEM}. Execute the full work flow."
done

# Dashboard
$SPAWN list

# Steer one mid-flight
$SPAWN send --name coord-14 \
  "Deprioritize the UI work. Focus on the API contract first."

# Read what a coordinator is showing
$SPAWN read --name coord-12

# Shut down the fleet
for ITEM in "${ITEMS[@]}"; do
  $SPAWN kill --name "coord-${ITEM}"
done

Model Selection

The --model flag controls the spawned session's orchestrator model. Each sub-agent spawned inside the session uses its own model per its agent frontmatter definition.

Use --model haiku for coordinator sessions that dispatch work to sub-agents — haiku is fast and cheap as an orchestrator. Use --model sonnet for sessions doing technical implementation work.

Milestone Dispatch Patterns

Used by /groom-milestone and /work-milestone to spawn parallel kage-bunshin workers.

Groom Dispatch

SPAWN="${CLAUDE_SKILL_DIR}/scripts/spawn.py"

for ISSUE in "${UNGROOMED_ISSUES[@]}"; do
  $SPAWN spawn --name "groom-${ISSUE}" --model haiku \
    "Load /dh:groom-backlog-item #${ISSUE}. Execute the full grooming flow."
done

$SPAWN list
$SPAWN read --name "groom-42"

Work Dispatch

SPAWN="${CLAUDE_SKILL_DIR}/scripts/spawn.py"

for ISSUE in "${WAVE_ISSUES[@]}"; do
  $SPAWN spawn --name "work-${ISSUE}" --model haiku \
    "Load /dh:work-backlog-item #${ISSUE}. Execute the full work flow."
done

$SPAWN list

# Steer if needed
$SPAWN send --name "work-42" \
  "The auth module has a dependency on #43. Coordinate accordingly."

# Clean up after wave
for ISSUE in "${WAVE_ISSUES[@]}"; do
  $SPAWN kill --name "work-${ISSUE}"
done

Reference

See ./references/stream-json-protocol.md for the stream-json output event type catalog and raw experiment data from earlier protocol exploration.

Stats
Parent Repo Stars28
Parent Repo Forks4
Last CommitMar 23, 2026