dev-agent-spawn

SKILL.md

Agent Spawn

Spawn AI coding agents (Claude Code, Codex) in new Ghostty terminals via AppleScript, wrapped in tmux for output capture. Requires Ghostty 1.3.0+, tmux, and macOS.

Spawn

bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh [OPTIONS]
Flag Description Default
-a, --agent AGENT Agent preset: claude, codex claude
-d, --directory DIR Working directory Current dir
-p, --prompt PROMPT Initial prompt for the agent None
-m, --mode MODE window, tab, split-right, split-down window
-r, --resume ID Resume conversation by ID (claude only) None
-c, --command CMD Full custom command (overrides --agent) Resolved from --agent preset
-n, --name NAME Tmux session name agent-<timestamp>
-w, --worktree Force worktree isolation (claude only) Auto (on in git repos)
--no-worktree Disable worktree isolation
--no-park Disable AeroSpace workspace auto-allocation
--workspace NAME Override auto-allocated workspace Auto (3+)

Monitor

agent-spawn.sh --status              # List all agent sessions with workspace occupancy
agent-spawn.sh --focus NAME          # Switch to agent's AeroSpace workspace
agent-spawn.sh --peek NAME           # Last 50 lines of output
agent-spawn.sh --peek NAME -l 200    # Last 200 lines
agent-spawn.sh --send NAME [TEXT]    # Send text + Enter (or bare Enter)
agent-spawn.sh --kill NAME           # Kill tmux session only
agent-spawn.sh --close NAME          # Kill tmux + close Ghostty window
agent-spawn.sh --close-all           # Close all agent sessions and windows

Modes

Mode When to Use
window Independent task in a separate window
tab Related task, keep in same window
split-right Side-by-side view, monitor while working
split-down Stacked view, log output below

Agent Presets

The --agent flag selects a CLI with the correct unattended/yolo flags. Use -c to override with a fully custom command.

Agent Command
claude (default) claude --dangerously-skip-permissions --model opus
codex codex --dangerously-bypass-approvals-and-sandbox

Feature support by agent

Feature claude codex
Worktree isolation (-w) Yes (auto-detected) No
Resume (-r) Yes No
Prompt (-p) Yes Yes

Examples

# Claude Code (default agent)
bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  -d ~/Projects/my-api \
  -p "fix the tests"

# Codex
bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  --agent codex \
  -d ~/Projects/my-api \
  -p "fix the tests"

# Custom command (full override, no preset applied)
bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  -c "claude --dangerously-skip-permissions --model sonnet" \
  -d ~/Projects/my-api \
  -p "quick review"

Examples

Spawn with prompt

bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  -d ~/Projects/my-api \
  -p "fix the failing tests in pkg/auth"

Named session for monitoring

bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  -n api-review \
  -d ~/Projects/my-api \
  -p "review error handling"

# Check progress
agent-spawn.sh --peek api-review

# Send follow-up prompt
agent-spawn.sh --send api-review "also check the retry logic"

Multiple parallel agents

for dir in pkg/auth pkg/api pkg/storage; do
  bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
    -m tab \
    -n "review-$(basename $dir)" \
    -d ~/Projects/my-api \
    -p "review $dir for error handling issues"
done

# Monitor all
agent-spawn.sh --status
agent-spawn.sh --peek review-auth
agent-spawn.sh --peek review-api

Resume a previous conversation

bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  -r 01abc123-def4-5678-9012-abcdef345678

Session Naming Convention

Always use descriptive -n names for spawned agents. Opaque default names like agent-1710329481 are meaningless in tmux ls output — you cannot tell which session is doing what without peeking into each one.

Keep the full -n name under 20 characters. Tmux truncates long session names in the status bar, making them unreadable. Use short slugs — 1–2 words is ideal.

Format

Use a prefix that encodes the work type, followed by a short slug:

Prefix When Example
task-<id>-<slug> Working a task queue item task-43-naming
pr-<n>-<slug> Reviewing or working a PR pr-87-auth-flow
fix-<slug> Bug fix fix-retry-timeout
feat-<slug> Feature work feat-webhooks
res-<slug> Research / exploration res-rate-limits

Slug rules: 1–2 words, lowercase, hyphenated. Full name (prefix + slug) must be under 20 characters.

Before / After

# BAD — opaque names, impossible to manage at scale
$ tmux ls
agent-1710329481: 1 windows (created Fri Mar 13 09:31:21 2026)
agent-1710329522: 1 windows (created Fri Mar 13 09:32:02 2026)
agent-1710329558: 1 windows (created Fri Mar 13 09:32:38 2026)
agent-1710329601: 1 windows (created Fri Mar 13 09:33:21 2026)

# GOOD — short descriptive names, no truncation in tmux status bar
$ tmux ls
task-43-naming:    1 windows (created Fri Mar 13 09:31:21 2026)
pr-87-auth-flow:   1 windows (created Fri Mar 13 09:32:02 2026)
fix-retry-timeout: 1 windows (created Fri Mar 13 09:32:38 2026)
res-rate-limits:   1 windows (created Fri Mar 13 09:33:21 2026)

Usage

# Task from the queue
bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  -n task-43-naming \
  -d ~/Projects/claude-skills \
  -p "/dev-task-queue claim and work on task #43"

# PR review
bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  -n pr-87-auth-flow \
  -d ~/Projects/my-api \
  -p "review PR #87"

# Peek and send by meaningful name
agent-spawn.sh --peek task-43-naming
agent-spawn.sh --send pr-87-auth-flow "also check error paths"

Task Queue Transcript Linking

When spawning agents to work on task queue items, always include transcript linking in the completion step of the prompt. Without this, --jsonl-path is never passed to complete_task.py and the conversation transcript is lost.

The agent's completion step must:

  1. Find its transcript .jsonl file (most recently modified file in ~/.claude/projects/)
  2. Pass --jsonl-path to complete_task.py

Always include this completion block in task queue prompts:

After implementing, push your branch, create a PR, and complete the task with transcript linked:
JSONL_PATH=$(ls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -1)
python3 ~/.agent-task-queue/scripts/complete_task.py <ID> --jsonl-path "$JSONL_PATH" --notes "PR: <url>"

Full task queue spawn template

bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  -n task-43-naming \
  -d ~/Projects/claude-skills \
  -p 'You are working on task #43 from the agent task queue.

FIRST: Create a git worktree to work in isolation:
git worktree add .claude/worktrees/task-43-naming -b task-43-naming
cd .claude/worktrees/task-43-naming

Then claim the task:
python3 ~/.agent-task-queue/scripts/claim_task.py 43 --session-id $(uuidgen)

THE TASK: <description>

After implementing, push your branch, create a PR, and complete the task with transcript linked:
JSONL_PATH=$(ls -t ~/.claude/projects/*/*.jsonl 2>/dev/null | head -1)
python3 ~/.agent-task-queue/scripts/complete_task.py 43 --jsonl-path "$JSONL_PATH" --notes "PR: <url>"'

Worktree Isolation

When spawning into a git repository, each agent automatically gets an isolated git worktree via Claude Code's /worktree command. This prevents branch conflicts and dirty working tree issues when multiple agents work in the same repo concurrently.

Behavior:

  • Auto (default): Detects if the target directory is a git repo. If yes, enables worktree isolation.
  • -w, --worktree: Force worktree isolation on (even if auto-detect fails).
  • --no-worktree: Disable worktree isolation (agent works directly on the repo).

The script prepends /worktree to the agent's prompt, so Claude Code creates a temporary worktree branch before starting work. Each agent gets its own branch and working directory — no coordination needed.

# Auto-enabled in git repos (default)
bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  -d ~/Projects/my-api \
  -p "fix the failing tests"

# Explicitly disable worktree for a quick read-only task
bash ~/.claude/skills/dev-agent-spawn/scripts/agent-spawn.sh \
  --no-worktree \
  -d ~/Projects/my-api \
  -p "explain the auth flow"

AeroSpace Workspace Integration

When AeroSpace is installed, spawned agents are automatically moved to dedicated workspaces to keep your main workspace clean.

Allocation Rules

  • Workspaces 1–3 are reserved for the user/orchestrator
  • Agent workspaces start at workspace 4 and go up (4, 5, 6, ...)
  • Max 3 agents per workspace (AeroSpace tiles them as a readable 3-way split)
  • When workspace 4 is full, the next agent goes to workspace 5, etc.
  • Dead sessions (tmux exited) don't count toward occupancy

Override or Disable

# Force agent to workspace 9
agent-spawn.sh --workspace 9 -n task-99-hotfix -d ~/Projects/app -p "urgent fix"

# Keep agent in the current workspace (old behavior)
agent-spawn.sh --no-park -n res-quick -d ~/Projects/app -p "quick lookup"

Navigation

# Switch to an agent's workspace
agent-spawn.sh --focus task-43-naming

# See workspace occupancy for all agents
agent-spawn.sh --status

Status Output

NAME                  WORKSPACE     TMUX        WINDOW
----                  ---------     ----        ------
task-43-naming        3 (2/3)       attached    window-aea3a4600
task-65-aero          3 (2/3)       attached    window-789908c00
pr-158-mise           4 (1/3)       attached    window-8e7de2700
res-quick             -             attached    window-44aabb100

Graceful Degradation

If AeroSpace is not installed, workspace allocation is silently skipped. All other features (tmux, peek, send, close) work unchanged.

How It Works

  1. Activate Ghostty (launches if not running)
  2. Create surface configuration with the target working directory
  3. Open a new window/tab/split using that configuration
  4. Send a tmux command that creates a named session and runs claude inside it
  5. Detect the new AeroSpace window by diffing aerospace list-windows before/after spawn
  6. Move the window to the allocated workspace via aerospace move-node-to-workspace

The input text + send key enter pattern is used instead of the command surface config property. The command property replaces the login shell, skipping .zshrc/.zprofile and losing PATH setup.

Tmux wrapping enables --peek (capture-pane), --send (send-keys), and --kill (kill-session) without Ghostty API limitations.

Troubleshooting

Problem Fix
"execution error" from osascript Grant Automation permission: System Settings > Privacy & Security > Automation > allow your terminal to control Ghostty
Ghostty not found Install Ghostty 1.3.0+ from https://ghostty.org
Claude not found in new terminal Ensure claude is on PATH in your shell profile (.zshrc)
Split opens but no command runs Increase delay — edit delay 0.3 in script if shell init is slow
--peek shows empty Session may not have started yet — wait a moment and retry
Agent not moving to workspace Ensure AeroSpace is installed and running (aerospace --version)
Weekly Installs
12
First Seen
4 days ago
Installed on
claude-code12
mcpjam3
kilo3
junie3
windsurf3
zencoder3