Spawn long-lived provider LLM teammates in tmux panes that you message via the native agent-team tools — multi-turn, collaborative, watchable. Use for sustained parallel build/work ("spawn workers", N teammates on N files), or when you need a collaborator you message across turns. NOT a fire-and-forget one-shot or a flat batch of independent prompts — that is /cc-fleet:subagent. NOT a scripted multi-phase run — that is /cc-fleet:workflow.
npx skills add https://github.com/ethanhq/cc-fleet --skill team
Run a third-party provider model as a real Claude Code teammate in a tmux pane: same tool stack and team coordination as a native teammate, LLM backend swapped to the provider. Your main session's own auth stays untouched.
Wrong lane? A fire-and-forget one-shot or flat batch → /cc-fleet:subagent; a scripted multi-phase run → /cc-fleet:workflow; full arbitration in cc-fleet-shared/routing.md.
When this skill cites cc-fleet-shared/<file>.md, OPEN it with the Read tool at ../cc-fleet-shared/<file>.md relative to this SKILL.md — the cited content is load-bearing, not optional background.
> Execution environment — check before running anything. Confirm your shell tool executes on the host where cc-fleet is installed. In sandboxed or remote agent sessions, a tool named Bash may run on an isolated machine with a different filesystem, PATH, processes, and tmux server — command not found, a healthy-looking doctor whose leaves can't reach your files, or a wrong working directory should prompt you to verify whether you are in a sandbox shell, not conclude that cc-fleet is broken. If so, route commands through a host-executing bridge tool (for example, desktop-commander) and pass host paths for any files you reference; do not retry the same Bash call expecting different results. If no host-executing tool is available, stop and explain that cc-fleet must run on its installation host.
Precondition — agent-teams must be ON: check your own tool list for SendMessage / TeamCreate; absent → do NOT spawn (an unmessageable pane bills the provider with no work) — enablement + fallback in cc-fleet-shared/routing.md.
Steps 1, 3, 6 are native tools; steps 2, 5, 6a are cc-fleet via Bash with --json.
1. TeamCreate({team_name: "<team>"})
← native, FIRST — the main session becomes the lead
2. cc-fleet spawn [<provider>] --as <name> --team <team> [--model <slot|id>] --json
← Bash; check ok:true, grab .pane_id / .agent_id
The provider arg is OPTIONAL — omitted, the default provider applies
(see "The provider ask ladder"). Full flag table: cc-fleet-shared/cli-reference.md.
3. SendMessage({to: "<name>", message: "<task>. When done, send your result
back with SendMessage."})
← native; always tell it to report — see "Getting a result back"
4. (optional) repeat 2+3 to fan out more workers in parallel
5. wait for idle notifications — WITH a timeout. A teammate on a failed
provider API (429 / out-of-balance / 401) wedges in a retry loop and never
goes idle, so "just wait" blocks forever. Poll cc-fleet ps --json --check
and dispatch on error_class — see "Watching for stuck teammates".
6. report to the user, then ASK before tearing down. On confirm, BOTH, in order:
a. cc-fleet teardown <team> --json ← Bash FIRST: kills provider panes + reaps procs
b. TeamDelete() ← native SECOND: removes the team/tasks dirs
On a spawn failure (ok:false), dispatch on error_code — table + self-heal flow in cc-fleet-shared/troubleshooting.md.
Teardown order — two hard rules (apply to wedged and probe teams too):
cc-fleet teardown FIRST, TeamDelete() SECOND — teardown reads the team's config.json (the swarm socket lives there), which TeamDelete() deletes; and TeamDelete() alone never touches tmux, so a provider pane/process would be orphaned and keep billing.TeamCreate({team_name: "refactor-api"}) # native
cc-fleet spawn --as worker-1 --team refactor-api --model strong --json # default provider
# → {"ok":true,"agent_id":"worker-1@refactor-api","name":"worker-1","pane_id":"%42", ...}
SendMessage({to: "worker-1", message: "Refactor src/api/handlers.go: split each handler into its own file under src/api/handlers/. Keep tests passing. Report your result via SendMessage when done."})
# … wait with timeout + ps --check …
# report; tear down only after the user confirms:
cc-fleet teardown refactor-api --json # Bash, FIRST
TeamDelete() # native
TeamCreate({team_name: "translate-docs"})
cc-fleet spawn kimi --as zh-1 --team translate-docs --json # leaf: omit --model
cc-fleet spawn kimi --as zh-2 --team translate-docs --json
cc-fleet spawn deepseek --as polish --team translate-docs --model strong --json # synthesis: strong
SendMessage({to: "zh-1", message: "Translate docs/intro.md to zh-CN beside it. SendMessage me when done."})
SendMessage({to: "zh-2", message: "Translate docs/api.md to zh-CN beside it. SendMessage me when done."})
SendMessage({to: "polish", message: "When zh-1 and zh-2 finish, copy-edit their outputs for tone consistency. SendMessage me the result."})
# … notifications per worker; report first, tear down on confirm:
cc-fleet teardown translate-docs --json # FIRST: kills all three panes + procs
TeamDelete()
cc-fleet default --json: if it returns a provider (source "configured" or "auto"), use it and STATE it in your kickoff line (e.g. "using glm (default)").cc-fleet list --json (name + default_model + the one-line note in cc-fleet-shared/providers.md). After they pick, run cc-fleet default <chosen> so you never ask again. (cc-fleet default <p> is user-layer; only run it to FILL a blank default, never with --force.)Model tier within a provider: fan-out / leaf work → omit --model (or --model fast); judge / synthesis / sustained work → --model strong. The provider's roster decides the actual model — see cc-fleet-shared/providers.md.
A teammate reports by calling SendMessage to the lead; the harness delivers it to you. Mode-independent — split pane or swarm pane, the pane is where it *runs*, never how you talk to it. Two provider-specific notes:
SendMessage: *"You appear done — reply with your result via SendMessage."* If the second ask still yields nothing, read the pane directly — don't bother the user: cc-fleet ps --json # → the teammate's tmux_socket + pane_id
tmux -L <tmux_socket> capture-pane -t <pane_id> -p | tail -40
Safe: the provider API key is never in the pane (resolved via apiKeyHelper, never printed). tmux_socket is empty for in-tmux teammates (plain tmux capture-pane) and cc-fleet-swarm-<team> for swarm teammates.
The one runtime difference from a native teammate. A provider teammate's brain *is* the provider API: on 429 / out-of-balance / 401 its claude process retries in a loop and never goes idle, never messages you — either would need the very LLM that's down. The error shows only in its tmux pane, never in your inbox. So you must poll.
cc-fleet ps --json --check. --check scans each pane and adds status (ok | error | unknown) plus error_class + detail on error — only the class, never raw pane text. Note the key: this runtime-wedge detection dispatches on error_class (lower_snake), a DIFFERENT key from the error_code (UPPER_SNAKE) that up-front spawn/subagent failure envelopes carry — don't switch on the wrong one. Dispatch:ok — keep waiting (within your ceiling).unknown — pane couldn't be captured (teammate exited / tmux down). Confirm with cc-fleet ps --json; treat a vanished teammate as failed.error — act now, per error_class:| error_class | Meaning | What you do |
|---|---|---|
| insufficient_balance | Provider out of balance / quota. | Retrying can't help. Tear down; STOP, tell the user, propose the next provider, wait for confirm (provider ask ladder, step 4). |
| auth | Provider rejected the key (401/403). | Tear down. Tell the user to rotate the key — file backend: cc-fleet edit <provider> --api-key-stdin <<<"$NEW_KEY" (or --api-key-file <path>); other backends via the secret manager. Don't re-spawn the same provider. Never the raw key in argv. |
| rate_limit | Provider 429. | Tear down; wait a bit and re-spawn, or propose a switch (confirm first). Never keep a wedged teammate looping. |
| api_error | Generic provider failure (5xx, overloaded, rejected). | Tear down; retry once, or propose a switch (confirm first). |
unknown or not specific enough → capture-pane and read it yourself (same command + key-safety note as above). ps --check is the first probe; the raw pane is a fine fallback.Tear down just the wedged worker (siblings keep running) by pane id: cc-fleet teardown <pane_id> --json, or the whole team with cc-fleet teardown <team> --json (then TeamDelete() if done). Then surface it and propose the fallback — another provider (re-spawn + re-SendMessage after the user confirms) or native Agent({subagent_type: "general-purpose", model: "sonnet", prompt: "<task>"}). Never leave a teammate wedged and keep waiting.
Either way you drive it with native SendMessage and it reports via SendMessage.
cc-fleet-swarm-<team> tmux server and runs the teammate there — silent unless you tmux -L cc-fleet-swarm-<team> attach. (A reusable, SendMessage-able teammate is an interactive process polling its inbox — needs a TTY; the truly-headless path is /cc-fleet:subagent.)Declutter the layout without killing the process:
cc-fleet hide <target> --json # pane → detached "claude-hidden" session; keeps running
cc-fleet show <target> --json # pane → back to its origin window, re-tiled
<target> = pane id %42 · team/member · name@team · bare team (every member with a pane). Origin is recorded at hide time.
SendMessage still work, teardown still cleans it.error_code: "SWARM_UNSUPPORTED" is a terminal no-op, not a tmux failure; attach to view instead.error_code, not prose: SWARM_UNSUPPORTED / TEAM_NOT_FOUND / MEMBER_NOT_FOUND / PANE_NOT_FOUND / NOT_HIDDEN / NO_ORIGIN / TMUX_FAILED / BAD_ARGS (malformed target) / CONFIG_WRITE_FAILED (the pane moved but the config write failed — tmux and config are now DIVERGENT; follow the envelope's suggestion to reconcile, never blindly re-run) / INTERNAL (lock/parse failure). Hiding an already-hidden pane is idempotent ok.Agents Board (human-facing): bare cc-fleet → Tab to a live board of every teammate across all teams (ps --check health, HIDDEN column, h/s hide/show). You use cc-fleet ps --json --check programmatically, not the TUI.
SendMessage — task delivery is always SendMessage. (Reading a pane for a result is fine.)TeamCreate before spawn → NO_LEAD_SESSION / TEAM_NOT_FOUND. Native TeamCreate first.ps --check.rm -rf ~/.claude/teams/... to tear down — skips pane/proc cleanup. cc-fleet teardown FIRST, then TeamDelete().apiKeyHelper; keys never enter env / ps aux / history..error_code — every --json failure carries a code (cc-fleet-shared/troubleshooting.md).Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, edit, or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
Replace with description of the skill and when Claude should use it.
Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies
This skill should be used when the user wants to "create a skill", "add a skill to plugin", "write a new skill", "improve skill description", "organize skill content", or needs guidance on skill structure, progressive disclosure, or skill development best practices for Claude Code plugins.
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
Use when creating new skills, editing existing skills, or verifying skills work before deployment
Take ethanhq/team from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.