N coordinated agents on shared task list using Claude Code native teams
Spawn N coordinated agents working on a shared task list using Claude Code's implicit agent team. Claude Code 2.1.178+ removed native TeamCreate/TeamDelete; with CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1, each session has one implicit team and teammates are spawned directly with the Agent/Task tool using distinct name values. This skill still preserves OMC's legacy tmux/CLI worker orchestration where documented (omc team / /omc-teams).
The swarm compatibility alias was removed in #1131.
/oh-my-claudecode:team N:agent-type "task description"
/oh-my-claudecode:team "task description"
/oh-my-claudecode:team ralph "task description"
team-exec stage (e.g., executor, debugger, designer, codex, gemini, antigravity). Optional; defaults to stage-aware routing. Use codex to spawn Codex CLI workers, gemini for Gemini CLI workers (enterprise/API-key tier), or antigravity for Antigravity CLI (agy) workers (Google's successor to the Gemini CLI; requires respective CLIs installed). See Stage Agent Routing below./team 5:executor "fix all TypeScript errors across the project"
/team 3:debugger "fix build errors in src/"
/team 4:designer "implement responsive layouts for all page components"
/team "refactor the auth module with security review"
/team ralph "build a complete REST API for user management"
# With Codex CLI workers (requires: npm install -g @openai/codex)
/team 2:codex "review architecture and suggest improvements"
# With Gemini CLI workers (requires: npm install -g @google/gemini-cli)
/team 2:gemini "redesign the UI components"
# With Antigravity CLI workers (requires: install per https://antigravity.google)
/team 2:antigravity "redesign the UI components"
# Mixed: Codex for backend analysis, Gemini/Antigravity for frontend (delegate per-task with /oh-my-claudecode:ask)
User: "/team 3:executor fix all TypeScript errors"
|
v
[TEAM ORCHESTRATOR (Lead)]
|
+-- Use the session's implicit Claude Code team
| -> no TeamCreate call; lead remains current session
|
+-- Analyze & decompose task into subtasks
| -> explore/architect produces subtask list
|
+-- Create task list entries from the implementation plan
| -> TODO/task entries #1, #2, #3 with dependencies
|
+-- Update task-list entries (pre-assign owners)
| -> task #1 owner=worker-1, etc.
|
+-- Task(name="worker-1") x 3
| -> spawns teammates into the team
|
+-- Monitor loop
| <- teammate messages (auto-delivered by the active team surface)
| -> task-list/TodoWrite review for progress
| -> message teammates through the active team surface to unblock/coordinate
|
+-- Completion
-> request shutdown from each teammate through the active team surface
<- shutdown acknowledgement from teammates
-> state_clear(mode="team", session_id="<current_session_id>")
-> preserve shared/legacy state for explicit --all cleanup
Native Claude Code team model (2.1.178+):
- No per-team ~/.claude/teams/<name>/ directory is created by this skill.
- No TeamCreate/TeamDelete calls are available.
- `team_name` is accepted by native Claude Code only as ignored legacy metadata; do not rely on it for routing.
- Spawn teammates directly via Agent/Task with `name="worker-N"`.
Team is the OMC authority for parallel, staged execution. Use the deterministic conflict policies refuse, adopt_existing, and artifact_only rather than non-deterministic warning handling. If a task mentions Claude Code /goal, Ralph, or artifact-only Ultragoal, keep Team as the primary loop authority unless the leader explicitly hands off. Use /goal only as a documented native Claude Code handoff target or as visible evidence from the lead session; do not claim the /goal evaluator independently runs commands, reads files, or replaces team-verify / team-fix. Artifact-only Ultragoal references should be treated as durable goal ledger/checkpoint/evidence artifacts, not as worker execution by themselves.
Team execution follows a staged pipeline:
team-plan -> team-prd -> team-exec -> team-verify -> team-fix (loop)
Each pipeline stage uses specialized agents -- not just executors. The lead selects agents based on the stage and task characteristics.
| Stage | Required Agents | Optional Agents | Selection Criteria |
|---|---|---|---|
| team-plan | explore (haiku), planner (opus) |
analyst (opus), architect (opus) |
Use analyst for unclear requirements. Use architect for systems with complex boundaries. |
| team-prd | analyst (opus) |
critic (opus) |
Use critic to challenge scope. |
| team-exec | executor (sonnet) |
executor (opus), debugger (sonnet), designer (sonnet), writer (haiku), test-engineer (sonnet) |
Match agent to subtask type. Use executor (model=opus) for complex autonomous work, designer for UI, debugger for compilation issues, writer for docs, test-engineer for test creation. |
| team-verify | verifier (sonnet) |
test-engineer (sonnet), security-reviewer (sonnet), code-reviewer (opus) |
Always run verifier. Add security-reviewer for auth/crypto changes. Add code-reviewer for >20 files or architectural changes. code-reviewer also covers style/formatting checks. |
| team-fix | executor (sonnet) |
debugger (sonnet), executor (opus) |
Use debugger for type/build errors and regression isolation. Use executor (model=opus) for complex multi-file fixes. |
Routing rules:
N:agent-type parameter only overrides the team-exec stage worker type. All other stages use stage-appropriate specialists.opus agents to sonnet, sonnet to haiku where quality permits. team-verify always uses at least sonnet.security-reviewer + code-reviewer (opus) in team-verify.explore scans codebase, planner creates task graph, optionally analyst/architect for complex tasks.analyst extracts requirements, optionally critic.verifier + task-appropriate reviewers (see routing table).team-fix.executor/debugger depending on defect type.team-exec then team-verify.Continue team-exec -> team-verify -> team-fix until:
team-fix is bounded by max attempts. If fix attempts exceed the configured limit, transition to terminal failed (no infinite loop).
When transitioning between stages, important context — decisions made, alternatives rejected, risks identified — lives only in the lead's conversation history. If the lead's context compacts or agents restart, this knowledge is lost.
Each completing stage MUST produce a handoff document before transitioning.
The lead writes handoffs to .omc/handoffs/<stage-name>.md.
## Handoff: <current-stage> → <next-stage>
- **Decided**: [key decisions made in this stage]
- **Rejected**: [alternatives considered and why they were rejected]
- **Risks**: [identified risks for the next stage]
- **Files**: [key files created or modified]
- **Remaining**: [items left for the next stage to handle]
.omc/handoffs/ for session resume. They are not deleted by native Claude Code team cleanup; no TeamDelete call exists in Claude Code 2.1.178+.## Handoff: team-plan → team-exec
- **Decided**: Microservice architecture with 3 services (auth, api, worker). PostgreSQL for persistence. JWT for auth tokens.
- **Rejected**: Monolith (scaling concerns), MongoDB (team expertise is SQL), session cookies (API-first design).
- **Risks**: Worker service needs Redis for job queue — not yet provisioned. Auth service has no rate limiting in initial design.
- **Files**: DESIGN.md, TEST_STRATEGY.md
- **Remaining**: Database migration scripts, CI/CD pipeline config, Redis provisioning.
.omc/handoffs/ to recover stage transition context.skills/cancel/SKILL.md; do not duplicate its flag, scope, or state-cleanup
rules here. Handoff files in .omc/handoffs/ are preserved for resume.complete, failed, and cancelled.On native Windows, do not tell users that /team requires WSL or that tmux is unavailable until the actual tmux-compatible binary has been checked. Native psmux installs a tmux-compatible command (often tmux / tmux.cmd) and is a supported Team multiplexer.
Before blocking or falling back on Windows:
tmux -V (or the platform equivalent such as where tmux followed by tmux -V).tmux -V as tmux available.Resolve the current session identity from the invocation context before touching Team state. In CLI contexts, OMC_SESSION_ID is authoritative; in hook contexts, the payload's session_id is authoritative. When an identity is available, pass it explicitly and consistently:
state_read(mode="team", session_id="<current_session_id>")
state_read without session_id reads legacy/aggregate state and may include other sessions. Never select or resume a Team from an unscoped aggregate response. If no identity is available, use only an explicitly identified legacy state; never infer ownership from session entries in an aggregate response.
Read existing session state before deriving a slug, decomposing work, or writing/initializing state. If active=true and current_phase is non-terminal, resume the recorded stage using the existing handoffs and task-list state for that Team. Preserve team_name, current_phase, fix_loop_count, max_fix_loops, stage_history, and all other existing Team state fields, including worker/task/launch-attempt records. Use the same session_id on every subsequent state_write and state_clear, applying only partial updates under the existing state lock. Do not run the new-team initialization below, derive a replacement slug, create duplicate tasks, spawn duplicate workers, or repeat launch attempts.
If state is malformed, unreadable, or otherwise corrupt, report the diagnostic and preserve the original bytes. Do not replace, clear, initialize, or treat it as a new run.
The following initialization phases apply only to a new run with no active, scoped state.
Use explore or architect (via MCP or agent) to analyze the codebase and break the task into N subtasks:
subject and detailed descriptionUse the session's implicit Claude Code team. Do not call TeamCreate; Claude Code 2.1.178+ removed that tool and automatically gives the session one implicit team when CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 is enabled.
Derive a slug such as fix-ts-errors for OMC state, prompt labels, handoffs, and human-readable reporting only. Native Claude Code may accept team_name as legacy metadata, but it is ignored for routing.
Write OMC state using the state_write MCP tool for proper session-scoped persistence:
Use the same resolved session_id from the Resume Check for this and every later Team state call; if no identity is available, use only the explicitly identified legacy state described above.
state_write(mode="team", session_id="<current_session_id>", active=true, current_phase="team-plan", state={
"team_name": "fix-ts-errors",
"agent_count": 3,
"agent_types": "executor",
"task": "fix all TypeScript errors",
"fix_loop_count": 0,
"max_fix_loops": 3,
"linked_ralph": false,
"stage_history": "team-plan"
})
Note: The MCP
state_writetool transports all values as strings. Consumers must coerceagent_count,fix_loop_count,max_fix_loopsto numbers andlinked_ralphto boolean when reading state.
State schema fields:
| Field | Type | Description |
|---|---|---|
active |
boolean | Whether team mode is active |
current_phase |
string | Current pipeline stage: team-plan, team-prd, team-exec, team-verify, team-fix |
team_name |
string | OMC slug for state, handoffs, and reporting; ignored by native Claude Code routing |
agent_count |
number | Number of worker agents |
agent_types |
string | Comma-separated agent types used in team-exec |
task |
string | Original task description |
fix_loop_count |
number | Current fix iteration count |
max_fix_loops |
number | Maximum fix iterations before failing (default: 3) |
linked_ralph |
boolean | Whether team is linked to a ralph persistence loop |
stage_history |
string | Comma-separated list of stage transitions with timestamps |
Update state on every stage transition:
state_write(mode="team", session_id="<current_session_id>", current_phase="team-exec", state={
"stage_history": "team-plan:2026-02-07T12:00:00Z,team-prd:2026-02-07T12:01:00Z,team-exec:2026-02-07T12:02:00Z"
})
Create task list entries for each subtask using TodoWrite or the active task-list surface. Task-list tools are for tracking only; they do not create native teams.
// Task-list entry for subtask 1
{
"subject": "Fix type errors in src/auth/",
"description": "Fix all TypeScript errors in src/auth/login.ts, src/auth/session.ts, and src/auth/types.ts. Run tsc --noEmit to verify.",
"activeForm": "Fixing auth type errors"
}
Response stores a task file (e.g. 1.json):
{
"id": "1",
"subject": "Fix type errors in src/auth/",
"description": "Fix all TypeScript errors in src/auth/login.ts...",
"activeForm": "Fixing auth type errors",
"owner": "",
"status": "pending",
"blocks": [],
"blockedBy": []
}
For tasks with dependencies, update the active task-list entries after creation:
// Task #3 depends on task #1 (shared types must be fixed first)
{
"taskId": "3",
"addBlockedBy": ["1"]
}
Pre-assign owners from the lead to avoid race conditions (there is no atomic claiming):
// Assign task #1 to worker-1
{
"taskId": "1",
"owner": "worker-1"
}
Spawn N teammates directly using the Agent/Task tool with distinct name values. Each teammate gets the team worker preamble (see below) plus their specific assignment. Do not call TeamCreate, and do not rely on team_name; Claude Code 2.1.178+ ignores it for native routing.
{
"subagent_type": "oh-my-claudecode:executor",
"name": "worker-1",
"prompt": "<worker-preamble + assigned tasks>"
}
Response:
{
"agent_id": "worker-1",
"name": "worker-1"
}
Side effects:
metadata._internal: true) tracking the agent lifecycleIMPORTANT: Spawn all teammates in parallel (they are background agents). Do NOT wait for one to finish before spawning the next.
The lead orchestrator monitors progress through two channels:
Inbound messages -- Teammates message team-lead when they complete tasks or need help. These arrive through the active team/conversation surface.
Task-list polling/review -- Periodically check TodoWrite or the active task-list surface for overall progress:
#1 [completed] Fix type errors in src/auth/ (worker-1)
#3 [in_progress] Fix type errors in src/api/ (worker-2)
#5 [pending] Fix type errors in src/utils/ (worker-3)
Format: #ID [status] subject (owner)
Coordination actions the lead can take:
Monitor for stuck or failed teammates:
in_progress for more than 5 minutes without messages, send a status checkOn every stage transition, update OMC state:
// Entering team-exec after planning
state_write(mode="team", session_id="<current_session_id>", current_phase="team-exec", state={
"stage_history": "team-plan:T1,team-prd:T2,team-exec:T3"
})
// Entering team-verify after execution
state_write(mode="team", session_id="<current_session_id>", current_phase="team-verify")
// Entering team-fix after verify failure
state_write(mode="team", session_id="<current_session_id>", current_phase="team-fix", state={
"fix_loop_count": 1
})
This enables:
state_read(mode="team", session_id="<current_session_id>") reveals the last stage and team name for recoverycurrent_phase to know what cleanup is neededWhen all real tasks (non-internal) are completed or failed:
completed in TodoWrite or the active task-list surfaceshutdown_request to each active teammate through the active team surface:{
"type": "shutdown_request",
"recipient": "worker-1",
"content": "All work complete, shutting down team"
}
shutdown_response(approve: true) and terminatesskills/cancel/SKILL.md for the selected session and any linked Ralph;
native Claude Code 2.1.178+ has no TeamDelete.When spawning teammates, include this preamble in the prompt to establish the work protocol. Adapt it per teammate with their specific task assignments.
You are a TEAM WORKER in OMC team "{team_name}". Your name is "{worker_name}".
You report to the team lead ("team-lead").
You are not the leader and must not perform leader orchestration actions.
== WORK PROTOCOL ==
1. CLAIM: Check TodoWrite or the active task-list surface for tasks assigned to you (owner = "{worker_name}").
Pick the first task with status "pending" that is assigned to you.
Mark it `in_progress` using the active task-list surface:
{"taskId": "ID", "status": "in_progress", "owner": "{worker_name}"}
2. WORK: Execute the task using your tools (Read, Write, Edit, Bash).
Do NOT spawn sub-agents. Do NOT delegate. Work directly.
3. COMPLETE: When done, mark the task completed:
{"taskId": "ID", "status": "completed"}
4. REPORT: Notify the lead through the active team/conversation surface:
{"type": "message", "recipient": "team-lead", "content": "Completed task #ID: <summary of what was done>", "summary": "Task #ID complete"}
5. NEXT: Check TodoWrite or the active task-list surface for more assigned tasks. If you have more pending tasks, go to step 1.
If no more tasks are assigned to you, notify the lead through the active team/conversation surface:
{"type": "message", "recipient": "team-lead", "content": "All assigned tasks complete. Standing by.", "summary": "All tasks done, standing by"}
6. SHUTDOWN: When you receive a shutdown_request, respond with:
{"type": "shutdown_response", "request_id": "<from the request>", "approve": true}
== BLOCKED TASKS ==
If a task has blockedBy dependencies, skip it until those tasks are completed.
Check TodoWrite or the active task-list surface periodically to see if blockers have been resolved.
== ERRORS ==
If you cannot complete a task, report the failure to the lead:
{"type": "message", "recipient": "team-lead", "content": "FAILED task #ID: <reason>", "summary": "Task #ID failed"}
Do NOT mark the task as completed. Leave it in_progress so the lead can reassign.
== RULES ==
- NEVER spawn sub-agents or use the Task tool
- NEVER run tmux pane/session orchestration commands (for example `tmux split-window`, `tmux new-session`)
- NEVER run team spawning/orchestration skills or commands (for example `$team`, `$autopilot`, `$ralph`, `omc team ...`, `omx team ...`)
- ALWAYS use absolute file paths
- ALWAYS report progress to "team-lead" through the active team/conversation surface
- Use direct team/conversation messages with type "message" only -- never "broadcast"
When composing teammate prompts, append a short addendum based on worker type:
claude_worker: Emphasize strict TodoWrite/task-list updates, active team/conversation messages, and no orchestration commands.codex_worker: Emphasize CLI API lifecycle (omc team api ... --json) and explicit failure ACKs with stderr.gemini_worker: Emphasize bounded file ownership and milestone ACKs after each completed sub-step.antigravity_worker: Same expectations as gemini_worker; emphasize bounded file ownership and milestone ACKs after each completed sub-step.This addendum must preserve the core rule: worker = executor only, never leader/orchestrator.
{
"type": "message",
"recipient": "team-lead",
"content": "Completed task #1: Fixed 3 type errors in src/auth/login.ts and 2 in src/auth/session.ts. All files pass tsc --noEmit.",
"summary": "Task #1 complete"
}
{
"type": "message",
"recipient": "worker-2",
"content": "Task #3 is now unblocked. Also pick up task #5 which was originally assigned to worker-1.",
"summary": "New task assignment"
}
{
"type": "broadcast",
"content": "STOP: shared types in src/types/index.ts have changed. Pull latest before continuing.",
"summary": "Shared types changed"
}
CRITICAL for graceful paths: Execute these steps in order. Never clear OMC
Team state before shutdown is confirmed or timed out. The --force and
--force --all invocations are the explicit wait-skipping paths; they still
use the canonical protected, session-scoped clear, honor locks/ownership, and
report failures. --force alone never broadens scope.
Step 1: Verify completion
Verify via TodoWrite or the active task-list surface — all real tasks (non-internal) are completed or failed.
Step 2: Request shutdown from each teammate
Lead sends:
{
"type": "shutdown_request",
"recipient": "worker-1",
"content": "All work complete, shutting down team"
}
Step 3: Wait for responses (BLOCKING)
shutdown_response, then reconcile for 5 more secondsTeammate receives and responds:
{
"type": "shutdown_response",
"request_id": "shutdown-1770428632375@worker-1",
"approve": true
}
After approval, the teammate terminates or stops accepting new work. Claude Code 2.1.178+ does not expose per-team config membership or TeamDelete cleanup; track acknowledgements in OMC state/reporting instead.
Step 4: Complete protected cleanup
After the graceful pass, follow the Team cancellation flow in
skills/cancel/SKILL.md; it clears the selected session and handles linked
Ralph. Claude Code 2.1.178+ has no TeamDelete.
Step 5: Orphan scan for OMC tmux/CLI workers only
For legacy OMC tmux/CLI worker runs (omc team / /omc-teams), check for worker processes that survived cleanup:
node "${CLAUDE_PLUGIN_ROOT}/scripts/cleanup-orphans.mjs" --team-name fix-ts-errors
This scans for OMC worker processes matching the team name and terminates stale orphans (SIGTERM → 5s wait → SIGKILL). Supports --dry-run for inspection.
The graceful clear requires every teammate to confirm (shutdown_response
with approve: true) or time out. The request_id comes from the request;
teammates must return it, never fabricate one.
The team skill supports hybrid execution combining Claude agent teammates with external CLI workers (Codex CLI and Gemini CLI). Both types can make code changes -- they differ in capabilities and cost. These are standalone CLI tools, not MCP servers.
Tasks are tagged with an execution mode during decomposition:
| Execution Mode | Provider | Capabilities |
|---|---|---|
claude_worker |
Claude agent | Full Claude Code tool access (Read/Write/Edit/Bash/Task). Best for tasks needing Claude's reasoning + iterative tool use. |
codex_worker |
Codex CLI (tmux pane) | Full filesystem access in working_directory. Runs autonomously via tmux pane. Best for code review, security analysis, refactoring, architecture. Requires npm install -g @openai/codex. |
gemini_worker |
Gemini CLI (tmux pane) | Full filesystem access in working_directory. Runs autonomously via tmux pane. Best for UI/design work, documentation, large-context tasks. Requires npm install -g @google/gemini-cli (enterprise/API-key tier). |
antigravity_worker |
Antigravity CLI (tmux pane) | Full filesystem access in working_directory. Runs autonomously via tmux pane. Same strengths as gemini_worker; Google's successor to the Gemini CLI. Install per the official instructions (agy binary). |
Tmux CLI workers run in dedicated tmux panes with filesystem access. They are autonomous executors, not just analysts:
working_directory set to the project rootKey difference from Claude teammates:
The v2 runtime waits up to 30 seconds for current-attempt task/status evidence. If that is absent, a read-only pane activity probe can grant a busy Cursor/Codex worker one additional 30-second evidence window. An idle, dead, or unverified pane gets only the normal 1-second final recheck. The trigger is never resent, and pane activity alone never counts as successful startup.
The default busy-worker evidence budget is therefore 60 seconds, plus probe and evidence-read overhead (roughly a minute, not a hard 61-second wall-clock limit). Pane creation, readiness, and cleanup add separate time. Startup is serial, so these waits can accumulate per worker. OMC_TEAM_ENGAGED_PANE_RECHECK_MS overrides the additional window in milliseconds; positive values are capped at 120000, while invalid or non-positive values retain the default.
| Task Type | Best Route | Why |
|---|---|---|
| Iterative multi-step work | Claude teammate | Needs tool-mediated iteration + team communication |
| Code review / security audit | CLI worker or specialist agent | Autonomous execution, good at structured analysis |
| Architecture analysis / planning | architect Claude agent | Strong analytical reasoning with codebase access |
| Refactoring (well-scoped) | CLI worker or executor agent | Autonomous execution, good at structured transforms |
| UI/frontend implementation | designer Claude agent | Design expertise, framework idioms |
| Large-scale documentation | writer Claude agent | Writing expertise + large context for consistency |
| Build/test iteration loops | Claude teammate | Needs Bash tool + iterative fix cycles |
| Tasks needing team coordination | Claude teammate | Needs team/conversation status updates |
/team 3:executor "refactor auth module with security review"
Task decomposition:
#1 [codex_worker] Security review of current auth code -> output to .omc/research/auth-security.md
#2 [codex_worker] Refactor auth/login.ts and auth/session.ts (uses #1 findings)
#3 [claude_worker:designer] Redesign auth UI components (login form, session indicator)
#4 [claude_worker] Update auth tests + fix integration issues
#5 [gemini_worker] Final code review of all changes
The lead runs #1 (Codex security analysis), then #2 and #3 in parallel (Codex refactors backend, designer agent redesigns frontend), then #4 (Claude teammate handles test iteration), then #5 (Gemini final review).
For large ambiguous tasks, run analysis before team creation:
Task(subagent_type="oh-my-claudecode:planner", ...) with task description + codebase contextThis is especially useful when the task scope is unclear and benefits from external reasoning before committing to a specific decomposition.
The lead can proactively ingest outbox messages from CLI workers using the outbox reader utilities, enabling event-driven monitoring alongside native team/conversation delivery.
readNewOutboxMessages(teamName, workerName) -- Read new outbox messages for a single worker using a byte-offset cursor. Each call advances the cursor, so subsequent calls only return messages written since the last read. Mirrors the inbox cursor pattern from readNewInboxMessages().
readAllTeamOutboxMessages(teamName) -- Read new outbox messages from ALL workers in a team. Returns an array of { workerName, messages } entries, skipping workers with no new messages. Useful for batch polling in the monitor loop.
resetOutboxCursor(teamName, workerName) -- Reset the outbox cursor for a worker back to byte 0. Useful when re-reading historical messages after a lead restart or for debugging.
getTeamStatus() in the Monitor PhaseThe getTeamStatus(teamName, workingDirectory, heartbeatMaxAgeMs?) function provides a unified snapshot combining:
Example usage in the monitor loop:
const status = getTeamStatus("fix-ts-errors", workingDirectory);
for (const worker of status.workers) {
if (!worker.isAlive) {
// Worker is dead -- reassign its in-progress tasks
}
for (const msg of worker.recentMessages) {
if (msg.type === "task_complete") {
// Mark task complete, unblock dependents
} else if (msg.type === "task_failed") {
// Handle failure, possibly retry or reassign
} else if (msg.type === "error") {
// Log error, check if worker needs intervention
}
}
}
if (status.taskSummary.pending === 0 && status.taskSummary.inProgress === 0) {
// All work done -- proceed to shutdown
}
| Message Type | Action |
|---|---|
task_complete |
Mark task completed, check if blocked tasks are now unblocked, notify dependent workers |
task_failed |
Increment failure sidecar, decide retry vs reassign vs skip |
idle |
Worker has no assigned tasks -- assign pending work or begin shutdown |
error |
Log the error, check consecutiveErrors in heartbeat for quarantine threshold |
shutdown_ack |
Worker acknowledged shutdown -- safe to remove from team |
heartbeat |
Update liveness tracking (redundant with heartbeat files but useful for latency monitoring) |
This approach complements native team/conversation messaging by providing a pull-based mechanism for MCP workers that cannot use Claude Code's team messaging tools.
in_progress for too longblockedBy metadataTask(name="worker-N", subagent_type="...")When the user invokes /team ralph, says "team ralph", or combines both keywords, team mode wraps itself in Ralph's persistence loop. This provides:
Team+Ralph activates when:
/team ralph "task" or /oh-my-claudecode:team ralph "task"team and ralph in the promptMAGIC KEYWORD: RALPH alongside team contextBoth modes write their own state files with cross-references:
// Team state (via state_write)
state_write(mode="team", session_id="<current_session_id>", active=true, current_phase="team-plan", state={
"team_name": "build-rest-api",
"linked_ralph": true,
"task": "build a complete REST API"
})
// Ralph state (via state_write)
state_write(mode="ralph", session_id="<current_session_id>", active=true, iteration=1, max_iterations=10, current_phase="execution", state={
"linked_team": true,
"team_name": "build-rest-api"
})
team-plan -> team-prd -> team-exec -> team-verifyteam-verify passes: Ralph runs architect verification (STANDARD tier minimum)/oh-my-claudecode:cancelteam-verify fails OR architect rejects: team enters team-fix, then loops back to team-exec -> team-verifymax_fix_loops: Ralph increments iteration and retries the full pipelinemax_iterations: terminal failed stateIf the lead crashes mid-run, the team skill should detect existing OMC state and resume:
state_read(mode="team", session_id="<current_session_id>") for the active OMC team slug, phase, and worker labelsThis prevents duplicate worker spawns and allows graceful recovery from lead failures.
| Aspect | Team (Native Claude Code 2.1.178+) | Swarm (Legacy SQLite) |
|---|---|---|
| Storage | OMC state/handoffs plus Claude Code's current task-list surface | SQLite in .omc/state/swarm.db |
| Dependencies | better-sqlite3 not needed |
Requires better-sqlite3 npm package |
| Task claiming | Lead pre-assigns named workers through task-list/TodoWrite state | SQLite IMMEDIATE transaction -- atomic |
| Race conditions | Possible if two agents claim same task (mitigate by pre-assigning) | None (SQLite transactions) |
| Communication | Native implicit-team messages / conversation turns | None (fire-and-forget agents) |
| Task dependencies | Lead-managed dependencies in task-list/TodoWrite state | Not supported |
| Heartbeat | Lead detects via missing messages/status | Manual heartbeat table + polling |
| Shutdown | Graceful request/response protocol plus OMC state clear | Signal-based termination |
| Agent lifecycle | Tracked by named Agent/Task spawns and OMC state | Manual tracking via heartbeat table |
| Progress visibility | Task list/TodoWrite state with named worker ownership | SQL queries on tasks table |
| Conflict prevention | Owner labels (lead-assigned) | Lease-based claiming with timeout |
| Crash recovery | Lead detects via missing messages, reassigns | Auto-release after 5-min lease timeout |
| State cleanup | Clear OMC team state after teammate shutdown | Manual rm of SQLite database |
When to use Team over Swarm: Always prefer /team for new native Claude Code work. It uses Claude Code's implicit agent team, requires no external dependencies, supports inter-agent coordination, and has task dependency management.
Team cancellation is defined only by the flow in
skills/cancel/SKILL.md. It owns the flag matrix, identity/fail-closed rule,
graceful and forced waits, session-scoped protected clears, Team-first linked
Ralph handling, all-session authorization, and unresolved-session gate.
Handoffs survive cancellation; uncaptured Team roots remain protected.
The linked-Ralph dependency is covered by that same canonical flow; do not restate a second session-operation recipe here.
By default, the team runtime uses an event-driven architecture instead of the legacy done.json polling watchdog:
.omc/state/team/{teamName}/events.jsonl.omc/state/team/{teamName}/workers/{name}/status.jsonNative CLI team jobs require the instance-bound v2 runtime. Unset a disabling
OMC_RUNTIME_V2 value (0, false, no, or off) before starting them; there is
no pane-only legacy cleanup fallback. Shutdown requires matching instance and
worker-launch evidence even with --force. Session state_clear does not remove
native runtime trees or substitute for native team shutdown.
When OMC_TEAM_SCALING_ENABLED=1 is set, the team supports mid-session scaling:
Optional settings live in .claude/omc.jsonc (project) or ~/.config/claude-omc/config.jsonc (user). Project values override user values; OMC_TEAM_ROLE_OVERRIDES (env JSON) supersedes both.
{
"team": {
"ops": {
"maxAgents": 20,
"defaultAgentType": "claude",
"monitorIntervalMs": 30000,
"shutdownTimeoutMs": 15000,
},
},
}
/team invocation does not specify one (claude | codex | gemini | antigravity | grok | cursor, default: claude)Note: Native Claude Code teammates do not have a hardcoded model default; each teammate inherits the lead session's configured model unless overridden per role. OMC's legacy CLI workers are separate processes: their provider and model come from OMC's team routing, not native teammate inheritance.
Nesting (Claude Code 2.1.217+): Claude teammates are full, independent Claude Code sessions in the session's implicit team (see Phase 5). Do not assume a teammate can or cannot spawn nested subagents: Claude Code 2.1.217–2.1.218 defaulted
CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTHto 1, while 2.1.219+ defaults to 3, and the current setting controls subagent layers below the main conversation. Plan each teammate as the unit that does the work unless nested delegation is deliberate and supported by the active runtime. OMC CLI workers (claude,codex,gemini,grok,cursor, andantigravityviaops.defaultAgentType) are separate processes, not Claude Code subagents, and are unaffected by Claude's subagent depth setting.Concurrency: The current OMC team CLI caps worker fan-out at 20 (
MAX_WORKER_COUNT); althoughops.maxAgentsexists in the config schema, the current launcher does not consult it. Claude Code'sCLAUDE_CODE_MAX_CONCURRENT_SUBAGENTSalso defaults to 20, but that limit applies to Agent-spawned subagents; Claude Code documents agent-team teammates as following their own limits. Do not treat the two values as a shared cap or assume a full-size OMC team leaves exactly zero headroom for ordinary subagents; size OMC teams conservatively when the lead also needs Agent-spawned work.
Scope: Applies to
/teamonly. Task-based delegation usesdelegationRouting(see separate docs). The two systems coexist by design.
Declare which provider (claude, codex, gemini, antigravity, grok, cursor) and which model tier should back each canonical role. Routing is resolved once at team creation and persisted in TeamConfig.resolved_routing — spawn, scale-up, and restart all read from the snapshot, so a role's worker CLI and model are stable for the lifetime of the team.
// .claude/omc.jsonc
{
"team": {
"roleRouting": {
"orchestrator": { "model": "inherit" },
"planner": { "provider": "claude", "model": "HIGH" },
"analyst": { "provider": "claude", "model": "HIGH" },
"executor": { "provider": "claude", "model": "MEDIUM" },
"debugger": { "provider": "cursor" },
"critic": { "provider": "codex" },
"code-reviewer": { "provider": "gemini" },
"test-engineer": { "provider": "gemini", "model": "MEDIUM" },
},
},
}
| Role | Provider | Model |
|---|---|---|
orchestrator |
claude (pinned) | inherits invoking session |
planner |
claude | HIGH (opus) |
analyst |
claude | HIGH (opus) |
executor |
claude | MEDIUM (sonnet) |
debugger |
cursor | cursor-agent default |
critic |
codex | codex default |
code-reviewer |
gemini | gemini default |
test-engineer |
antigravity | antigravity default |
orchestrator, planner, analyst, architect, executor, debugger, critic, code-reviewer, security-reviewer, test-engineer, designer, writer, code-simplifier, explore, document-specialist.
User-friendly aliases normalize via normalizeDelegationRole() — e.g. reviewer → code-reviewer, quality-reviewer → code-reviewer, harsh-critic → critic, build-fixer → debugger. Accepted alias keys are honored during resolved snapshot creation and later stage routing, not just validation. Unknown roles fail validation at parse time.
TeamRoleAssignmentSpec)"claude" | "codex" | "gemini" | "antigravity" | "grok" | "cursor". Omitted → defaults to claude."HIGH" | "MEDIUM" | "LOW") or an explicit model ID. Tiers resolve through routing.tierModels."critic", "executor"). Only honored when the resolved provider is claude.orchestrator is pinned to claude; only model is user-configurable. Any other key on orchestrator is rejected by the validator.
cursor launches cursor-agent as an interactive worker. Reviewer/verdict roles (critic, code-reviewer, security-reviewer, test-engineer) are supported and receive the same structured verdict-output contract as other non-Claude providers. The leader owns the terminal task transition after consuming the verdict; final approval remains a lead-session responsibility.
OMC_TEAM_ROLE_OVERRIDES='{"critic":{"provider":"codex"},"code-reviewer":{"provider":"gemini"}}'
Precedence: OMC_TEAM_ROLE_OVERRIDES > .claude/omc.jsonc (project) > ~/.config/claude-omc/config.jsonc (user) > built-in defaults. Invalid JSON logs a warning and is ignored — env overrides are best-effort and never abort the run.
Team startup strictly preflights only providers that are effective for its initial workers, including idle-worker assignments and explicit role routes. Role routing selects each worker's initial startup provider; later tasks delivered to an existing pane keep that worker's provider and are not re-routed by task role. A missing, relative, or untrusted binary for a selected provider fails before team state or multiplexer side effects are created. Providers that are merely present in the routing snapshot or declared agent list, including providers for roles never selected for a launch, are not probed. Routing is authoritative: the runtime never silently changes a selected role to Claude when its provider is unavailable. Scale-up and worker recovery independently preflight the provider they are about to launch and fail closed if it is unavailable. Probe provider availability with omc doctor --team-routing.
Resolved routing is immutable per team. It selects each worker's initial startup assignment; later tasks in an existing pane stay on that worker's provider instead of triggering task-role provider re-routing. Editing config mid-team-lifetime does not affect running teams; a new /team invocation picks up the new mapping. Spawn, scale-up, and worker-restart use the same snapshot for the workers they launch, including across worktree detaches (the snapshot travels with TeamConfig).
An empty team.roleRouting preserves pre-patch behavior: every worker is Claude, model tiers follow routing.tierModels, and /team 3:executor ... still spawns three Claude Sonnet executors.
Use /oh-my-claudecode:cancel for Team and linked-Ralph cleanup; its
authoritative flow handles session identity, locks/ownership, graceful versus
forced waits, and legacy runtime cleanup. Native Claude Code 2.1.178+ has no
TeamDelete. For normal completion, invoke it after the shutdown protocol;
uncaptured Team roots and handoffs are preserved.
MCP workers can operate in isolated git worktrees to prevent file conflicts between concurrent workers.
Worktree creation: Before spawning a worker, call createWorkerWorktree(teamName, workerName, repoRoot) to create an isolated worktree at .omc/worktrees/{team}/{worker} with branch omc-team/{teamName}/{workerName}.
Worker isolation: Pass the worktree path as the workingDirectory in the worker's BridgeConfig. The worker operates exclusively in its own worktree.
Merge coordination: After a worker completes its tasks, use checkMergeConflicts() to verify the branch can be cleanly merged, then mergeWorkerBranch() to merge with --no-ff for clear history.
Team cleanup: On team shutdown, call cleanupTeamWorktrees(teamName, repoRoot) to remove all worktrees and their branches.
| Function | Description |
|---|---|
createWorkerWorktree(teamName, workerName, repoRoot, baseBranch?) |
Create isolated worktree |
removeWorkerWorktree(teamName, workerName, repoRoot) |
Remove worktree and branch |
listTeamWorktrees(teamName, repoRoot) |
List all team worktrees |
cleanupTeamWorktrees(teamName, repoRoot) |
Remove all team worktrees |
checkMergeConflicts(workerBranch, baseBranch, repoRoot) |
Non-destructive conflict check |
mergeWorkerBranch(workerBranch, baseBranch, repoRoot) |
Merge worker branch (--no-ff) |
mergeAllWorkerBranches(teamName, repoRoot, baseBranch?) |
Merge all completed workers |
createSession() in tmux-session.ts does NOT handle worktree creation — worktree lifecycle is managed separately via git-worktree.tssanitizeName() to prevent injectionInternal/lifecycle task entries may pollute task-list output -- If Claude Code reports internal lifecycle entries for spawned teammates, filter them when counting real task progress. The subject of an internal task is often the teammate's name.
No atomic claiming -- Unlike SQLite swarm, native task-list/TodoWrite state does not provide transactional claiming. Two teammates could race to claim the same task. Mitigation: The lead should pre-assign owners before spawning teammates. Teammates should only work on tasks assigned to them.
Task IDs are strings when exposed by task-list tools -- IDs may be auto-incrementing strings ("1", "2", "3"), not integers. Always pass string values to taskId fields when using task-list tools.
No TeamDelete cleanup -- Claude Code 2.1.178+ removed TeamDelete; use shutdown messages plus OMC state cleanup.
Messages are auto-delivered -- Teammate messages arrive to the lead as new conversation turns. No polling or inbox-checking is needed for inbound messages. However, if the lead is mid-turn (processing), messages queue and deliver when the turn ends.
Do not put secrets in teammate prompts -- Prompts can be retained in logs, state, or conversation history. Keep credentials and sensitive data out of teammate prompts.
Shutdown acknowledgements are state/reporting events -- After a teammate approves shutdown and terminates, track that acknowledgement in OMC state/reporting. Do not expect a Claude Code team membership config to update.
shutdown_response needs request_id -- The teammate must extract the request_id from the incoming shutdown request JSON and pass it back. The format is shutdown-{timestamp}@{worker-name}. Fabricating this ID will cause the shutdown to fail silently.
Team name must be a valid slug -- Use lowercase letters, numbers, and hyphens. Derive from the task description (e.g., "fix TypeScript errors" becomes "fix-ts-errors").
Broadcast is expensive -- Each broadcast sends a separate message to every teammate. Use message (DM) by default. Only broadcast for truly team-wide critical alerts.
CLI workers are one-shot, not persistent -- Tmux CLI workers have full filesystem access and CAN make code changes. However, they run as autonomous one-shot jobs -- they cannot use Claude Code's native task-list or team messaging surfaces. The lead must manage their lifecycle: write prompt_file, spawn CLI worker, read output_file, mark task complete. They don't participate in team communication like Claude teammates do.
.omc-workspace marker at the parent directory so multiple sessions across sub-repos share one .omc/. Resolution order: OMC_STATE_DIR > .omc-workspace > git > cwd. See docs/REFERENCE.md..omc/handoffs/ are shared by design (see Wave G in the workspace plan).