Adds decisions and process-lessons from recent reflections. Updates decompose and orchestrate SKILL.md with operational improvements. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7.7 KiB
name, description, user_invocable, allowed-tools
| name | description | user_invocable | allowed-tools |
|---|---|---|---|
| orchestrate | Check agent task state and launch container agents for ready tasks. Designed for use with /loop (e.g., /loop 2m /orchestrate) to auto-dispatch work to container agents. | true | Read, Write, Edit, Bash(date *), Bash(cat *), Bash(hostname *), Bash(docker *), Bash(jq *), Bash(git *) |
/orchestrate Skill
orchestrate
You are the task orchestrator. Check task state, update statuses, and launch container agents for tasks that are ready to run. Each task runs in its own git worktree for isolation.
Pre-gathered context
Current date
!date +%Y-%m-%dT%H:%M:%S
Hostname
!hostname
Task state
!cat .agent-tasks.json 2>/dev/null || echo "NO_TASK_FILE"
Instructions
If the task state file doesn't exist, say "No .agent-tasks.json found. Run /decompose first." and stop.
Step 1: Check running containers
For each task with status: "running", check if the container is still alive:
docker inspect --format '{{.State.Status}}' <container_id> 2>/dev/null
- If container status is
exited: get exit code withdocker inspect --format '{{.State.ExitCode}}'- Exit code 0 → set task status to
completed, recordcompleted_atandexit_code - Exit code non-zero → set task status to
failed, recordexit_codeand capture last 20 lines of logs withdocker logs --tail 20 <container_id>, store inerror
- Exit code 0 → set task status to
- If container not found (removed or wrong host): mark as
failedwith error "Container not found" - If container still running: leave as
running
On task completion (success or failure):
- Do NOT remove the worktree yet — the user may want to review changes on the branch
- For successful tasks, note that
branchcontains the changes
Step 2: Identify ready tasks
A task is ready when:
- Its status is
pending - ALL tasks in its
depends_onlist have statuscompleted
If a dependency has status failed, mark the dependent task as blocked (it cannot proceed).
Step 3: Launch ready tasks
Respect max_concurrent from .agent-tasks.json. Count tasks with status: "running" — if at the limit, skip launching and wait for the next cycle.
For each ready task:
3a. Create a git worktree
Determine the branch point:
- If the task has no dependencies, branch from the current HEAD:
git worktree add .worktrees/<task-id> -b agent/<task-id> - If the task depends on one completed task, branch from that task's branch:
git worktree add .worktrees/<task-id> -b agent/<task-id> agent/<dep-task-id> - If the task depends on multiple completed tasks, create a merge base first:
git branch agent/<task-id>-base git checkout agent/<task-id>-base git merge --no-edit agent/<dep-1> agent/<dep-2> ... git checkout - # back to original branch git worktree add .worktrees/<task-id> -b agent/<task-id> agent/<task-id>-base
Record the branch and worktree path in the task state.
3b. Copy dependency outputs into the worktree
For tasks with dependencies, the dependency's output files (listed in writes) are likely untracked in git — they exist only in the dependency's worktree. Copy them into the new worktree:
# For each completed dependency:
for dep_task_id in <depends_on>; do
# Copy the files that dep_task listed in its "writes" field
for file in <dep_task.writes>; do
cp .worktrees/<dep_task_id>/$file .worktrees/<task-id>/$file
done
done
Also copy any untracked files from the main tree that the task needs (listed in reads):
- Spec files, plan files, etc. that may not be committed
- Check with
git statuswhether files exist in the worktree; copy from main tree if missing
This step is critical — worktrees only contain committed content. Without it, agents cannot read dependency outputs or untracked project files.
3c. Launch the container
Determine the model to use:
- Read the task's
modelfield from.agent-tasks.json - If
modelis set, use that value (e.g.,claude-opus-4-20250514,claude-sonnet-4-20250514) - If
modelis not set or null, default toclaude-sonnet-4-20250514
docker run -d \
-e CLAUDE_CODE_OAUTH_TOKEN="<token>" \
-e ENFORCE_SUBSCRIPTION_PRICING=true \
-v <absolute_worktree_path>:/project \
-w /project \
--entrypoint uid-wrapper.sh \
agent-claude:latest \
claude --print --dangerously-skip-permissions --model <model> "<task prompt>"
Important:
- Use
-d(detached) so the container runs in the background — do NOT use--rmso we can inspect logs after exit - Mount the worktree path (not the main project) as
/project - Capture the container ID from docker run output
- The CLAUDE_CODE_OAUTH_TOKEN must be available in the current environment. If not set, read it from
~/dev/claude/secrets/claude/long_lived_oauth_token(extract the value aftervalue:) - If the task's
readslist references paths outside the project (e.g.,/foundationsfor best practices), mount those as additional read-only volumes - Container agents do NOT have web search capability. Do not include "use web search" in task prompts unless web search support has been explicitly configured for the container.
After launching, update the task in .agent-tasks.json:
- Set
statustorunning - Set
hostto the current hostname - Set
container_idto the docker container ID (full ID, not short) - Set
started_atto current ISO timestamp - Set
branchandworktreeto the values from step 3a
Step 4: Report status
Print a concise status summary:
Agent Tasks — <project name>
─────────────────────────────
completed task-a: Write payload spec ✓ (branch: agent/task-a)
completed task-b: Write entrypoint spec ✓ (branch: agent/task-b)
running task-c: Write harness spec (container abc123..., 3m elapsed)
pending task-d: Implement resolver (waiting on: task-c)
blocked task-e: Integration tests (blocked by failed: task-f)
failed task-f: Build images (exit code 1)
─────────────────────────────
3/6 complete | 1 running | 1 pending | 1 blocked
Concurrency: 1/3 slots used
Step 5: Update task state file
Write the updated .agent-tasks.json with all status changes.
Step 6: Merge completed branches (when all done)
When ALL tasks are resolved (no pending or running remaining):
- Print "All tasks resolved."
- List completed task branches with a summary of what each contains
- Suggest the user review and merge:
git merge agent/<task-id>for each, orgit merge agent/<task-1> agent/<task-2> ...for an octopus merge - Note that worktrees can be cleaned up with:
git worktree remove .worktrees/<task-id> - Suggest cancelling the loop if running via
/loop
Do NOT auto-merge — the user should review and decide.
Automation Notes
- This skill is designed to be called repeatedly via
/loop 2m /orchestrate - Each invocation is stateless — it reads .agent-tasks.json, checks containers, updates, and exits
- Keep output concise when called in a loop — just the status table unless something changed
- On first run, if
CLAUDE_CODE_OAUTH_TOKENis not in the environment, read it once and export it for subsequent runs
Error Recovery
- If a task fails, its dependents are marked
blocked. The user can:- Fix the issue in the worktree and re-run: set status back to
pendingin .agent-tasks.json - Skip the task: manually mark dependents as
pendingand adjust their branch points
- Fix the issue in the worktree and re-run: set status back to
- If a worktree creation fails (e.g., branch already exists):
git branch -D agent/<task-id>and retry - Stale containers (running > 30 minutes with no output): flag in status report but don't kill automatically