Loading...
Loading...
Use when acting as a project manager that delegates tasks to other Claude Code sessions - launch workers, assign them work, monitor progress, review their tool calls, and collect results
npx skill4agent add obra/claude-session-driver driving-claude-code-sessions--dangerously-skip-permissions../../scripts/SCRIPTS="<this-skill's-base-directory>/plugin/scripts"RESULT=$("$SCRIPTS/launch-worker.sh" my-worker /path/to/project)
SESSION_ID=$(echo "$RESULT" | jq -r '.session_id')
TMUX_NAME=$(echo "$RESULT" | jq -r '.tmux_name')my-workerclaude--dangerously-skip-permissionssession_startsession_idtmux_nameevents_fileclaude# Use a specific model
RESULT=$("$SCRIPTS/launch-worker.sh" my-worker /path/to/project --model sonnet)converse.shRESPONSE=$("$SCRIPTS/converse.sh" my-worker "$SESSION_ID" "Refactor the auth module to use JWT tokens" 300)
echo "$RESPONSE"--after-lineR1=$("$SCRIPTS/converse.sh" my-worker "$SESSION_ID" "Write tests for the auth module" 300)
R2=$("$SCRIPTS/converse.sh" my-worker "$SESSION_ID" "Now add edge case tests for expired tokens" 300)send-prompt.sh"$SCRIPTS/send-prompt.sh" my-worker "Refactor the auth module to use JWT tokens""$SCRIPTS/wait-for-event.sh" "$SESSION_ID" stop 300stop{"ts":"2025-01-15T10:30:00Z","event":"stop"}# All events
"$SCRIPTS/read-events.sh" "$SESSION_ID"
# Last 3 events
"$SCRIPTS/read-events.sh" "$SESSION_ID" --last 3
# Only stop events
"$SCRIPTS/read-events.sh" "$SESSION_ID" --type stop
# Follow in real-time (blocks -- run in background Bash job for monitoring)
"$SCRIPTS/read-events.sh" "$SESSION_ID" --follow &
MONITOR_PID=$!
# ... do other work ... then stop monitoring:
kill $MONITOR_PID 2>/dev/null| Event | Meaning | Extra fields |
|---|---|---|
| Worker session initialized | |
| A prompt was submitted to the worker | |
| Worker is about to call a tool | |
| Worker finished processing, waiting for input | |
| Worker session terminated |
/--/Users/jesse/myproject-Users-jesse-myproject~/.claude/projects/<encoded-path>/<session-id>.jsonlENCODED_PATH=$(echo "/path/to/project" | sed 's|/|-|g')
LOG_FILE=~/.claude/projects/${ENCODED_PATH}/${SESSION_ID}.jsonl
grep '"type":"assistant"' "$LOG_FILE" | tail -1 | jq -r '.message.content[] | select(.type=="text") | .text'"$SCRIPTS/stop-worker.sh" my-worker "$SESSION_ID"/exitsession_end/tmp/claude-workers/The worker is running in tmux session 'my-worker'. You can:
- Watch live: tmux attach -t my-worker
- Take over: just start typing in the attached session
- Return to me: detach with Ctrl-B d| Script | Usage | Description |
|---|---|---|
| | Send prompt, wait, return response |
| | Start a worker session |
| | Send a prompt to a worker |
| | Block until event or timeout |
| | Read event stream |
| | Gracefully stop and clean up |
| | Respond to a pending tool approval |
| | Format last turn as markdown |
RESULT=$("$SCRIPTS/launch-worker.sh" task-worker ~/myproject)
SESSION_ID=$(echo "$RESULT" | jq -r '.session_id')
"$SCRIPTS/send-prompt.sh" task-worker "Run the test suite and fix any failures"
"$SCRIPTS/wait-for-event.sh" "$SESSION_ID" stop 600
# Read what happened, then clean up
"$SCRIPTS/read-events.sh" "$SESSION_ID"
"$SCRIPTS/stop-worker.sh" task-worker "$SESSION_ID"# Launch workers for different tasks
R1=$("$SCRIPTS/launch-worker.sh" worker-api ~/myproject)
S1=$(echo "$R1" | jq -r '.session_id')
R2=$("$SCRIPTS/launch-worker.sh" worker-ui ~/myproject)
S2=$(echo "$R2" | jq -r '.session_id')
# Send each their task
"$SCRIPTS/send-prompt.sh" worker-api "Add pagination to the /users endpoint"
"$SCRIPTS/send-prompt.sh" worker-ui "Add a loading spinner to the user list page"
# Wait for both (sequentially -- first one to finish unblocks its wait)
"$SCRIPTS/wait-for-event.sh" "$S1" stop 600
"$SCRIPTS/wait-for-event.sh" "$S2" stop 600
# Clean up
"$SCRIPTS/stop-worker.sh" worker-api "$S1"
"$SCRIPTS/stop-worker.sh" worker-ui "$S2"# Worker 1: Generate an API spec
R1=$("$SCRIPTS/launch-worker.sh" worker-spec ~/myproject)
S1=$(echo "$R1" | jq -r '.session_id')
"$SCRIPTS/send-prompt.sh" worker-spec "Generate an OpenAPI spec for the users endpoint and save it to /tmp/api-spec.yaml"
"$SCRIPTS/wait-for-event.sh" "$S1" stop 300
# Worker 2: Implement from the spec that Worker 1 produced
R2=$("$SCRIPTS/launch-worker.sh" worker-impl ~/myproject)
S2=$(echo "$R2" | jq -r '.session_id')
"$SCRIPTS/send-prompt.sh" worker-impl "Implement the API endpoint defined in /tmp/api-spec.yaml"
"$SCRIPTS/wait-for-event.sh" "$S2" stop 600
# Clean up both
"$SCRIPTS/stop-worker.sh" worker-spec "$S1"
"$SCRIPTS/stop-worker.sh" worker-impl "$S2"converse.sh--after-lineRESULT=$("$SCRIPTS/launch-worker.sh" supervised ~/myproject)
SESSION_ID=$(echo "$RESULT" | jq -r '.session_id')
R1=$("$SCRIPTS/converse.sh" supervised "$SESSION_ID" "Write tests for the auth module" 300)
R2=$("$SCRIPTS/converse.sh" supervised "$SESSION_ID" "Now add edge case tests for expired tokens" 300)
"$SCRIPTS/stop-worker.sh" supervised "$SESSION_ID"converse.shread-turn.sh# After a converse.sh call, review what the worker actually did
"$SCRIPTS/read-turn.sh" "$SESSION_ID"
# Show complete tool results (default truncates to 5 lines)
"$SCRIPTS/read-turn.sh" "$SESSION_ID" --fullsend-prompt.shif ! tmux has-session -t my-worker 2>/dev/null; then
echo "Worker is gone -- need to relaunch"
fi/tmp/claude-workers/<session-id>.events.jsonlwait-for-event.shwait-for-event.shstop-worker.shsend-prompt.shtmux send-keys -lecho "Your detailed instructions here..." > /tmp/worker-instructions.txt
"$SCRIPTS/send-prompt.sh" my-worker "Read /tmp/worker-instructions.txt and follow those instructions"pre_tool_use# Watch for pending tool approvals
PENDING_FILE="/tmp/claude-workers/${SESSION_ID}.tool-pending"
# Check if a tool call is waiting for approval
if [ -f "$PENDING_FILE" ]; then
cat "$PENDING_FILE" # Shows tool_name and tool_input
# Approve it
"$SCRIPTS/approve-tool.sh" "$SESSION_ID" allow
# Or deny it
"$SCRIPTS/approve-tool.sh" "$SESSION_ID" deny
fiCLAUDE_SESSION_DRIVER_APPROVAL_TIMEOUTRESULT=$(CLAUDE_SESSION_DRIVER_APPROVAL_TIMEOUT=60 "$SCRIPTS/launch-worker.sh" my-worker ~/project)stop-worker.shtmux kill-session -t my-worker 2>/dev/null
rm -f /tmp/claude-workers/<session-id>.events.jsonl
rm -f /tmp/claude-workers/<session-id>.metatseventlaunch-worker.sh