Coordinator Mode

Description

Coordinator mode transforms Claude Code from a single agent into a multi-agent orchestrator. When activated, the coordinator receives a completely different system prompt that defines a research → synthesis → implementation → verification workflow. Workers are spawned as async sub-agents, execute independently, and report back via XML task notifications. The coordinator synthesizes findings and crafts precise implementation specs rather than delegating understanding.

Implementation: src/coordinator/coordinatorMode.ts (369 lines)

Activation

export function isCoordinatorMode(): boolean {
  return feature('COORDINATOR_MODE') && isEnvTruthy(process.env.CLAUDE_CODE_COORDINATOR_MODE)
}

Requires both the COORDINATOR_MODE build-time feature flag AND CLAUDE_CODE_COORDINATOR_MODE=1 environment variable. On session resume, matchSessionMode() automatically restores the mode to match the stored session.

Coordinator system prompt

The coordinator gets a completely replaced system prompt (not appended — replaced). Priority in buildEffectiveSystemPrompt(): override > coordinator > agent > custom > default.

Structured workflow

The prompt defines four phases: 1. Research — workers run in parallel, investigate independently 2. Synthesis — coordinator reads findings, understands the problem 3. Implementation — workers make changes per coordinator's precise spec 4. Verification — workers prove code works (not just rubber-stamp)

Worker communication rules

Workers can't see the conversation. Every prompt must be self-contained with: - File paths, line numbers, exact changes needed - Purpose statement for depth calibration - Whether to continue an existing worker or spawn fresh

Anti-pattern: "Based on your findings, fix the bug" — the coordinator must own synthesis.

Available tools

The coordinator has a restricted tool set: - Agent — spawn new workers - SendMessage — continue existing workers (send follow-up to agent ID) - TaskStop — kill a running worker

Worker management

Spawning

When the coordinator calls Agent(), the system forces async execution regardless of run_in_background. Workers always run in the background, returning immediately with an agentId.

Task notifications

Workers report completion via XML notifications injected as user messages:

<task-notification>
  <task-id>{agentId}</task-id>
  <status>completed|failed|killed</status>
  <summary>Agent "Find bug" completed</summary>
  <result>{agent's final text}</result>
  <usage><total_tokens>N</total_tokens>...</usage>
</task-notification>

Notifications are enqueued via enqueuePendingNotification() in the message queue.

Worker tool access

Workers receive the full tool set minus coordinator-internal tools:

Excluded from workers (INTERNAL_WORKER_TOOLS): - TeamCreate, TeamDelete — workers can't create teams - SendMessage — workers can't message other workers - SyntheticOutput — coordinator-only

In simple mode (CLAUDE_CODE_SIMPLE), workers get only Bash, Read, Edit.

Scratchpad directory

Cross-worker durable storage, feature-gated behind tengu_scratch GrowthBook gate:

$TMPDIR/claude-{uid}/{sessionId}/scratchpad/

Workers can read/write without permission prompts. Used for sharing findings, intermediate state, and coordination artifacts. Path injected into the coordinator's user context.

User context injection

getCoordinatorUserContext() injects additional context into the coordinator's messages: - Full list of tools available to workers - MCP servers workers can access - Scratchpad directory path (if enabled)

Lazy-loaded in QueryEngine to avoid circular dependencies.

System prompt priority

src/utils/systemPrompt.ts (lines 41-123): 1. Override (if set, replaces all) 2. Coordinator prompt (if coordinator mode + no mainThreadAgent) 3. Agent prompt (if mainThreadAgent) 4. Custom prompt (if specified) 5. Default prompt (standard Claude Code) 6. Append prompt (always added at end, except with override)

Mutual exclusivity

Coordinator mode and fork subagent mode are mutually exclusive — only one orchestration model per session. isForkSubagentEnabled() returns false when coordinator mode is active.

Communication flow

User Request
  → Coordinator (custom system prompt)
    → Agent({ prompt: "self-contained spec" })  [forces async]
      → Worker executes independently
      → <task-notification> enqueued
    → Coordinator receives notification
    → Synthesizes findings
    → SendMessage({ to: agentId, message: "implementation spec" })
    → Worker continues
    → Loop until done
  → Coordinator responds to user

What depends on it

Design trade-offs

Decision Trade-off
Complete prompt replacement (not augmentation) Clean separation, but coordinator loses default Claude Code guidance
Always-async workers True parallelism, but coordinator can't do simple inline delegation
Workers can't see conversation Self-contained prompts prevent context pollution, but coordinator must repeat context
XML task notifications Human-readable, structured, but verbose
Scratchpad for cross-worker sharing Durable knowledge sharing, but requires explicit file coordination
Mutual exclusivity with fork mode Simplifies reasoning about orchestration, but can't combine patterns

Key claims

Relations

Sources

Source code at src/coordinator/coordinatorMode.ts, src/utils/systemPrompt.ts, src/tools/AgentTool/AgentTool.tsx