team — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited team (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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.
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 dirsOn 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() # nativeTeamCreate({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 -40Safe: 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). |
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. (Reading a pane for a result is fine.)NO_LEAD_SESSION / TEAM_NOT_FOUND. Native TeamCreate first.ps --check.cc-fleet teardown FIRST, then TeamDelete().apiKeyHelper; keys never enter env / ps aux / history.--json failure carries a code (cc-fleet-shared/troubleshooting.md).~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.