dev-agent-spawn
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:
- 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/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
- 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) |
More from molechowski/claude-skills
res-price-compare
Polish market product price comparison: 20+ shops, shipping costs, manufacturer vs seller warranty, B2B/statutory warranty analysis, stock status, distribution chain. Export TXT/XLSX/HTML. Use when: looking for a product to buy, price comparison, where to buy cheapest. Triggers: cena, porównaj, gdzie kupić, najtaniej, sklep, price compare, best price, kup, ile kosztuje.
36doc-vault-project
Manage multi-note research projects in Obsidian vault with phased subdirectory structure (concept, research, design, implementation). Scaffold new projects, add component notes, track status, link existing research, promote topics to projects. Use when: creating a project, adding to a project, checking project status, linking research to a project, promoting a research topic to a full project. Triggers: project init, project add, project status, project link, project promote, create project, new project.
35res-deep
Iterative multi-round deep research with structured analysis frameworks. Use for: deep research on a topic, compare X vs Y, landscape analysis, evaluate options for a decision, deep dive into a technology, comprehensive research with cross-referencing. Triggers: deep research, compare, landscape, evaluate, deep dive, comprehensive research, which is better, should we use.
35doc-daily-digest
Process Obsidian daily notes: classify raw URLs and loose ideas, fetch content (X tweets, GitHub repos, web pages), run deep research on ideas, create structured vault notes, replace raw items with wikilinks. Orchestrates doc-obsidian, res-x, and res-deep skills. Use when: processing daily note links, digesting saved URLs into notes, turning ideas into research, daily note cleanup. Triggers: daily digest, process daily, daily links, triage daily, digest daily note.
35res-x
Fetch X/Twitter tweet content by URL and search X posts. Resolves tweet links that WebFetch cannot scrape. Use for: reading saved X/Twitter links, fetching tweet content from URLs, searching X for posts on a topic, batch-processing X links from notes. Triggers: x.com link, twitter.com link, fetch tweet, read tweet, what does this tweet say, X search, twitter search.
34doc-project
Update all project documentation in one pass: CLAUDE.md, AGENTS.md, README.md, SKILLS.md, CHANGELOG.md. Orchestrates doc-claude-md, doc-readme, doc-skills-md, and doc-changelog skills sequentially. Use when: project docs are stale, after major changes, initial project setup, sync all docs. Triggers: update all docs, update project docs, sync documentation, refresh docs, doc-project.
34