Orchestrate — Multi-Agent Task Distribution
You are the orchestrator's automation layer. The human orchestrator runs /orchestrate to get help analyzing the task board, planning parallel work distribution, spawning agent worktrees, generating agent prompts, monitoring progress, and cleaning up after waves complete.
Context: This project uses git worktrees for agent isolation, GitHub Projects as the coordination board, and scripts/orchestrate.sh for worktree mechanics. Agent-side commands (/sync, /claim, /handoff) already exist. This skill automates the human side.
Task Source: GitHub Projects (the project board with structured fields: Status, Priority, Readiness, Effort, Agent, Workstream, Dependencies). Requires gh CLI and MOLTNET_PROJECT_NUMBER env var (set in env.public).
How to Respond
When the user invokes this skill, determine which action they want based on their message. If unclear, show a brief menu of the 6 actions. Then execute that action.
Action 1: Analyze
Triggers: "what's ready?", "what can we parallelize?", "analyze tasks", "show dependencies", or invoked with no specific request.
Query the GitHub Project board and classify every item into one of three categories.
Gathering Tasks
gh project item-list "${MOLTNET_PROJECT_NUMBER}" --owner "${MOLTNET_PROJECT_OWNER:-getlarge}" --format json
This returns items with their project fields (Status, Priority, Readiness, Effort, Agent, etc.).
Dependency Resolution
For each item with Status "Todo":
- •
Read the Dependencies text field.
- •
If empty or "none" → ready.
- •
If it references issue numbers (e.g.,
#42, #45), check if those issues are closed:bashgh issue view <NUMBER> --repo getlarge/themoltnet --json state -q '.state'
- •All closed → ready
- •Some open but assigned → soon (waiting on active work)
- •Some open and unassigned → blocked
- •
Check for file boundary overlaps: read the issue body's Context Files section. If two ready tasks mention the same directory, flag as a potential conflict.
Output Format
## Task Analysis ### Board Summary - Todo: <N> | In Progress: <N> | Done: <N> ### Ready (can start now) - **<Task Name>** #<N> [<Priority>] [<Effort>] Dependencies: none (or all satisfied) Context: <files from issue body> ### Soon (waiting on active work) - **<Task Name>** #<N> [<Priority>] — waiting on: #<dep issue(s)> ### Blocked (dependencies not started) - **<Task Name>** #<N> [<Priority>] — needs: #<dep issue(s)> ### Potential Conflicts - <Task A> and <Task B> both touch <directory> — consider sequencing
Action 2: Plan
Triggers: "distribute work", "plan tasks", "plan the wave", "what should I spawn?".
Prerequisite: Run the Analyze action first (internally) if you haven't already.
Present a wave-based distribution plan:
Wave Planning Logic
- •Take all ready tasks from the analysis.
- •Remove any with file boundary conflicts (move the conflicting one to wave 2).
- •Sort remaining by priority: high > medium > low.
- •Present as Wave 1.
- •For soon tasks, estimate they'll become ready after Wave 1 completes. Present as Wave 2 candidates.
- •Note any blocked tasks that need manual intervention.
Output Format
## Distribution Plan ### Wave 1 (parallel — start now) | # | Task | Priority | Worktree Name | Branch | |---|------|----------|---------------|--------| | 1 | <name> | high | <repo>-<slug> | agent/<slug> | | 2 | ... | | | | ### Wave 2 (after Wave 1 merges) | # | Task | Unblocked By | |---|------|-------------| | 1 | <name> | <wave 1 task(s)> | ### Needs Attention - <any blocked tasks or conflicts> Ready to spawn? Say "spawn it" or "go ahead".
Action 3: Spawn
Triggers: "spawn it", "go ahead", "create worktrees", "spawn" (after a plan has been presented).
For each task in the approved wave:
- •
Derive a worktree slug from the task name: strip
WS\d+:\s*prefix, lowercase, spaces to hyphens, keep only[a-z0-9-]. Examples:- •"WS4: Auth library" ->
auth-library - •"WS3: Diary service" ->
diary-service - •"WS2: Ory token enrichment webhook" ->
ory-token-enrichment-webhook
- •"WS4: Auth library" ->
- •
Ask the user: "Use Docker sandboxes for isolation? (Requires Docker Desktop 4.58+)" — two modes:
Mode A — Bare worktrees (default):
bash./scripts/orchestrate.sh spawn <slug> main
Mode B — Docker sandbox (stronger isolation):
- •For each task, tell the user: "Run
/sandbox-worktree <slug> mainto create a sandboxed worktree" - •The
/sandbox-worktreeskill handles:- •Creating the worktree via
orchestrate.sh spawn - •Copying
.sandbox-includedirectories - •Creating the Docker sandbox
- •Error handling and fallback
- •Creating the worktree via
- •Do NOT attempt to run Docker sandbox commands yourself — delegate to the skill
- •For each task, tell the user: "Run
- •
Report results. If any spawn fails (worktree already exists), report the error and suggest
teardownfirst. - •
After all spawns, run:
bash./scripts/orchestrate.sh list
And if sandboxes were requested, run:
bashdocker sandbox ls 2>/dev/null
to confirm everything is ready.
- •
CRITICAL - Auth Fix for Docker Sandboxes: If Mode B was used, tell the user they must fix credential persistence BEFORE launching agents:
Correct workflow:
a. Launch ONE sandbox:
docker sandbox run themoltnet-<any-name>b. Inside that sandbox:claude login(authenticate once) c. Exit the sandbox d. Run this batch fix for ALL sandboxes:bashdocker sandbox ls | tail -n +2 | awk '{print $1}' | while read SANDBOX_NAME; do echo "Fixing credentials for: $SANDBOX_NAME" docker sandbox exec $SANDBOX_NAME bash -c ' # CRITICAL: Remove apiKeyHelper that overrides OAuth tokens if [ -f /home/agent/.claude/settings.json ]; then cat /home/agent/.claude/settings.json | jq "del(.apiKeyHelper)" > /tmp/settings.json && \ mv /tmp/settings.json /home/agent/.claude/settings.json echo "✓ Removed apiKeyHelper from settings" fi # Persist credentials to persistent volume sudo mkdir -p /mnt/claude-data sudo chown -R agent:agent /mnt/claude-data if [ -f /home/agent/.claude/.credentials.json ]; then cp /home/agent/.claude/.credentials.json /mnt/claude-data/ cp /home/agent/.claude.json /mnt/claude-data/ 2>/dev/null || true rm /home/agent/.claude/.credentials.json rm /home/agent/.claude.json 2>/dev/null || true ln -s /mnt/claude-data/.credentials.json /home/agent/.claude/.credentials.json ln -s /mnt/claude-data/.claude.json /home/agent/.claude.json 2>/dev/null || true echo "✓ Credentials persisted to volume" else echo "⚠ No credentials found" fi ' 2>/dev/null || echo " → Sandbox stopped or error" donee. Now all sandboxes are authenticated and will stay authenticated across restarts
Why this order? Credentials must exist BEFORE they can be persisted. One
claude logincreates the credential file, then the batch script copies it to all sandboxes' persistent Docker volumes.
Action 4: Launch
Triggers: "launch agents", "generate prompts", "give me the commands" (after spawn).
For each spawned task, generate a self-contained agent prompt and present it as a ready-to-run terminal command.
Prompt Generation
For each task, build a prompt from the project board item and its linked issue:
You are an agent working on MoltNet. Your task: <Task Name>. ## Setup 1. Run /sync to check the coordination state 2. Run /claim <Task Name> to claim your task ## Context Read these files first: <list from Context Files column, one per line with "- " prefix> Also read: - CLAUDE.md (project conventions) - docs/FREEDOM_PLAN.md (relevant workstream section) ## Task <Notes column content> ## Workflow 1. Implement the task following project conventions in CLAUDE.md 2. Write tests (Vitest, AAA pattern) 3. Run: pnpm run validate 4. Fix any lint, typecheck, or test failures 5. Run /handoff to create journal entry and PR
Output Formats
Ask the user which format they prefer, then generate:
Option A — Individual commands (copy-paste one at a time):
# Task: <name> cd <worktree-path> && claude -p '<prompt>'
Option B — tmux script (all agents in one session):
tmux new-session -d -s agents tmux send-keys -t agents:0 'cd <worktree-1> && claude -p "<prompt-1>"' C-m tmux split-window -h -t agents tmux send-keys -t agents:1 'cd <worktree-2> && claude -p "<prompt-2>"' C-m # ... for each task tmux attach -t agents
Option C — Background with logs (fire and forget):
cd <worktree-1> && claude -p '<prompt-1>' > agent-<slug-1>.log 2>&1 & cd <worktree-2> && claude -p '<prompt-2>' > agent-<slug-2>.log 2>&1 & # ... for each task echo "Agents launched. Tail logs with:" echo " tail -f agent-*.log"
Option D — Docker sandboxes (if spawned with sandbox mode):
# Each agent runs inside its sandbox docker sandbox run themoltnet-<slug-1> # (in another terminal) docker sandbox run themoltnet-<slug-2>
Note: Docker sandbox sessions are interactive — each needs its own terminal. Provide the commands as a list for the user to run manually.
Escape single quotes in prompts by replacing ' with '\''.
Action 5: Monitor
Triggers: "status", "check agents", "how are they doing?", "monitor".
Gather and present:
- •
Worktree status:
bash./scripts/orchestrate.sh list
- •
Docker sandbox status (if any exist):
- •Run
/sandbox-managerto get sandbox status (delegates to the sandbox-manager skill)
- •Run
- •
Branch activity (for each agent branch):
bashgit fetch --all --quiet
Then for each worktree that matches
agent/*:bashgit log --oneline -5 <branch>
- •
Open PRs and CI:
bashgh pr list --limit 10 gh run list --limit 10
- •
Stale branch detection:
bashgit branch -r --merged origin/main
Flag any
agent/*orclaude/*remote branches that are fully merged into main — these are leftover from previous waves and can be deleted. - •
Project board state: query the board and summarize Todo vs In Progress vs Done.
Output Format
## Agent Status ### Active Worktrees | Worktree | Branch | Sandbox | Last Commit | Age | |----------|--------|---------|-------------|-----| | ...-auth-library | agent/auth-library | yes/no | <msg> | <time> | ### Open PRs | PR | Title | Status | CI | |----|-------|--------|----| | #N | ... | review/draft | pass/fail/running | ### Stale Branches - <branch> (merged, safe to delete) ### Task Board - Active: <count> tasks in progress - Available: <count> tasks remaining - Completed: <count> tasks done
Action 6: Cleanup
Triggers: "clean up", "next wave", "teardown", "merge and continue".
Guide the orchestrator through the end-of-wave lifecycle:
- •
Check mergeable PRs:
bashgh pr list --json number,title,mergeable,reviewDecision,statusCheckRollup --limit 20
For each PR that has passing CI, present it for merge approval.
- •
Merge approved PRs (only after explicit user confirmation for each):
bashgh pr merge <number> --squash --delete-branch
- •
Teardown merged worktrees and sandboxes:
For each merged task's slug, tell the user to run
/sandbox-managerto clean up both the sandbox and worktree. The sandbox-manager skill handles:- •Removing the Docker sandbox (if it exists)
- •Removing the git worktree
- •Proper error handling
Alternatively, for bare worktrees without sandboxes:
bash./scripts/orchestrate.sh teardown <slug>
- •
Delete stale remote branches:
bashgit fetch --prune origin
Then list any
agent/*orclaude/*remote branches withahead=0relative to main. Present them to the user for batch deletion:bashgh api -X DELETE "repos/<owner>/<repo>/git/refs/heads/<branch>"
- •
Prune dangling worktree references:
bashgit worktree prune
- •
Update local main:
bashgit fetch origin main && git rebase origin/main
- •
Re-analyze: Run the Analyze action to show what's now ready for the next wave.
Output
After cleanup, show:
## Wave Complete ### Merged - PR #N: <title> ### Cleaned Up - Worktree: <slug> (removed) - Sandbox: <slug> (removed) — if applicable ### Branches Deleted - <branch> (was merged) ### Next Wave <output from Analyze action>
Important Notes
- •Never auto-merge PRs. Always list them and wait for explicit user approval per PR.
- •Never auto-spawn without a plan. Always show the plan first and wait for confirmation.
- •Worktree slugs must match what
orchestrate.shexpects: lowercase alphanumeric with hyphens. - •The repo name for worktree paths is derived from the repo root directory name (currently
themoltnet). - •Agent prompts should be self-contained — the agent starts fresh with no prior context.
- •When running shell commands, use absolute or repo-relative paths. The orchestrate script is at
scripts/orchestrate.sh. - •GitHub Projects is required. If
ghis not available orMOLTNET_PROJECT_NUMBERis not set, tell the user to set up the project board first (./scripts/setup-project.sh).