dev-agent-spawn
Agent Spawn
Spawn Claude Code sessions 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 |
|---|---|---|
-d, --directory DIR |
Working directory | Current dir |
-p, --prompt PROMPT |
Initial prompt for Claude | None |
-m, --mode MODE |
window, tab, split-right, split-down |
window |
-r, --resume ID |
Resume conversation by ID | None |
-c, --command CMD |
Custom command | claude --dangerously-skip-permissions --model opus (sandbox disabled) |
-n, --name NAME |
Tmux session name | agent-<timestamp> |
-w, --worktree |
Force worktree isolation | 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 |
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/agent-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:
- Find its transcript
.jsonlfile (most recently modified file in~/.claude/projects/) - Pass
--jsonl-pathtocomplete_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/agent-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
- Activate Ghostty (launches if not running)
- Create surface configuration with the target working directory
- Open a new window/tab/split using that configuration
- Send a tmux command that creates a named session and runs claude inside it
- Detect the new AeroSpace window by diffing
aerospace list-windowsbefore/after spawn - 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) |