subagent — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited subagent (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.
Wrong lane? A long-lived collaborator you message back and forth → /cc-fleet:team; a multi-phase pipeline with dependencies or resume → /cc-fleet:workflow; 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-lookingdoctorwhose 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.
cc-fleet subagent runs a provider model headless and returns the result directly on Bash stdout — no tmux pane, no team, no SendMessage. The analog of the native Agent/Task tool, but the model can be a provider id. It reuses the same provider selection as the teammate lane and needs only a claude binary on the host. It's the lightweight synchronous branch.
--timeout caps wall-clock; the return value carries usage / total_cost_usd; it stops when done (nothing to forget to tear down).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.)STOP freezes the affected provider operation and any unapproved provider switch, not independent authorized work. The error table's single rate-limit retry remains allowed; do not retry uncertain writes before establishing their prior result. Main-session handling is allowed only where the workflow already permits it and the user has not required that provider. Changing a provider or the saved default still requires the corresponding explicit authorization.
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.
The reserved native leaf — `claude`. cc-fleet subagent claude … runs the official claude CLI on the user's OWN Claude Code login (their subscription OAuth or whatever they're logged in as) — no providers.toml row, no profile, no key material. A NAMED deliberate choice, never the auto-default (cc-fleet default claude errors; it never auto-resolves). --model takes a literal id (fable / opus / sonnet / a full id) — the slot keywords default/strong/fast are rejected (no roster); omitted = claude's login default, which is typically the most expensive tier, so naming a model is usually wise. Profiles apply unchanged. The leaf spends the lead session's own subscription window — use it for one or two synthesis / judgement nodes, never a wide fan-out.
cc-fleet subagent claude --model opus --prompt "<synthesis over the gathered notes>" --json--json)cc-fleet subagent --prompt "<task>" --json # no provider arg → default provider
cc-fleet subagent deepseek --model strong \
--prompt "Analyze the worst-case complexity of quicksort in src/sort.go; give a triggering input" --jsonThe provider arg is optional — with no provider, cc-fleet uses the default. NO_DEFAULT_PROVIDER / DEFAULT_PROVIDER_DISABLED / DEFAULT_PROVIDER_UNKNOWN in the failure envelope mean there is no usable default — apply the provider ask ladder above.
Session grouping — no flag needed. cc-fleet subagent auto-detects the parent Claude session (fail-closed: an unvalidatable registry shows (no session), never a guess) — the same live session id the Agents Board groups your teammates under. The envelope's lead_session_id is the id subagent-gc --session takes. --lead-session-id <id> overrides detection, but never copy it from ~/.claude/teams/<team>/config.json: the implicit team keeps its startup session id after /clear, /resume, --resume or --continue.
Useful flags (full list: cc-fleet subagent --help):
--label "<short-alias>" (e.g. --label sort-complexity). The Agents Board shows the label instead of the opaque job id — pass one on every launch, like a teammate name. Display-only metadata; capped at 256 bytes.--prompt-file <path> (read from file, piped via stdin, kept out of argv / ps). Use it once a single prompt approaches ~128 KiB (MAX_ARG_STRLEN, the per-argument cap — not the ~2 MB total ARG_MAX). --prompt-file - reads stdin.--timeout 600s (default 300s). For tasks that may exceed the timeout, run the sync call in a backgrounded Bash, or use --background (both below). Note: a provider that's down on auth (401) or quota (429) makes claude retry ~180s before surfacing KEY_INVALID / INSUFFICIENT_BALANCE, so keep --timeout ≥ ~200s (the 300s default is fine) — a shorter timeout reports those as SUBAGENT_TIMEOUT instead. --probe does not catch a bad key (the models endpoint may not 401 it).--max-budget-usd 0.5 (cap spend) and --max-turns (cap the agentic tool loop). On fan-out, strongly consider a budget cap on every call. Size `--max-turns` generously up front — a read-heavy / multi-file / git-inspecting task spends ~1 turn per file read or command, so give it 30–50 (or omit it); a small cap (8/10) starves it and the leaf fails SUBAGENT_MAX_TURNS mid-task.slim is the DEFAULT; read-only research → --profile slim-ro; --profile full ONLY to compare against a full session or diagnose a suspected slim regression. --tools REPLACES the whole tool set, never appends. Write prescriptive prompts ("Run cmd", "Use the Read tool on X"), not "look at" / "check" — weak provider models skip tools on weak imperatives under any profile. Tool whitelists / --skills / --mcp defaults / downgrade behavior: cc-fleet-shared/providers.md.--probe to opt in): the inner claude -p call is itself the authoritative reachability + auth test. On a big fan-out, run one shared cc-fleet doctor / probe up front rather than paying up to 10s × N.--prompt and --prompt-file are mutually exclusive — pass exactly one (else error_code=SUBAGENT_BAD_ARGS, no claude launched).{"ok":true,"result":"<answer text>","provider":"deepseek","model":"deepseek-reasoner",
"duration_ms":12044,"usage":{"input_tokens":812,"output_tokens":1530},
"total_cost_usd":0.0031,"session_id":"…"}→ Take .result as this subagent's output and hand it back / continue orchestrating. model is the model the provider actually billed (routing evidence). Keep .session_id if you intend a multi-turn follow-up (below).
error_code (do not parse prose)error_msg is a canonical string only; never matched on. Dispatch on error_code:
error_code | Meaning | What you do |
|---|---|---|
SUBAGENT_BAD_ARGS | The call itself is invalid (a missing or conflicting prompt flag, a flag value cc-fleet rejects, or a slot keyword on the native claude leaf — error_msg says which) — or, from subagent-status, an invalid or unknown job id (e.g. one already pruned). An unknown flag or an unparsable value (--timeout 5zz) never gets here: it exits 1 with one stderr line and no JSON. | Fix the call and re-issue; never retry it unchanged. An unknown job id on --wait means the record is gone — stop waiting on it. |
NO_DEFAULT_PROVIDER | No provider arg and no default configured. | Apply the provider ask ladder. |
DEFAULT_PROVIDER_DISABLED | The default provider is disabled. | Apply the provider ask ladder; or the user re-enables via cc-fleet edit <provider> --enable. |
DEFAULT_PROVIDER_UNKNOWN | The default names a provider that no longer exists. | Apply the provider ask ladder; the user re-pins with cc-fleet default <p>. |
DEFAULT_PROVIDER_RESERVED | default_provider is hand-set to the reserved claude (explicit-only). | The user runs cc-fleet default --unset or re-pins a real provider; don't retry. |
CONFIG_LOAD_FAILED | providers.toml failed to load/validate. | cc-fleet doctor; surface to the user — don't retry. |
UNKNOWN_PROVIDER / PROVIDER_DISABLED | Provider not configured / disabled. | Tell the user to cc-fleet add / cc-fleet edit <provider> --enable. |
PROVIDER_RESERVED | A providers.toml row is named claude (reserved for the native leaf). | Tell the user to rename or cc-fleet remove claude. The subagent, workflow and teammate lanes refuse that row; only cc-fleet run claude launches it (cc-fleet-shared/providers.md). |
FINGERPRINT_STALE | The claude binary was not found (the code keeps its old name). | Tell the user to install/fix Claude Code or PATH, then retry. cc-fleet doctor confirms. |
KEY_INVALID | Provider 401/403 (on a codex provider: no usable codex login). | Have the user rotate the key; do not retry blindly. A codex provider has no key: the user runs cc-fleet codex login --credential <its secret_ref> (protocol codex-oauth and secret_ref in cc-fleet list --json). |
INSUFFICIENT_BALANCE | Out of balance / quota (429/402 + balance signature). | Retry can't help — propose the next provider (provider ask ladder, step 4) or fall back to native Agent; tell the user they're out of credit. |
RATE_LIMITED | Provider 429. | Wait briefly, retry once, or propose a switch (provider ask ladder, step 4). |
MODEL_NOT_FOUND | Model name rejected (400). | Drop --model, or pass a slot (default/strong/fast; see cc-fleet models <provider> --json), and retry. If the user named that model, tell them it was rejected and confirm the substitute before retrying. If a configured slot itself is rejected, the user fixes it with cc-fleet edit <provider> --default-model/--strong-model/--fast-model <id> (or the TUI); cc-fleet refresh changes nothing a run uses. |
PROVIDER_UNREACHABLE | Transport failure (with --probe, or at runtime when claude reports one). | cc-fleet doctor; if urgent, fall back to native Agent. |
SUBAGENT_TIMEOUT | Exceeded --timeout. | Real long task → raise --timeout (or use --background) and retry; suspected hang → switch provider / fall back (with user confirmation). |
PROVIDER_API_ERROR | Other provider failure (5xx / overloaded). | Retry once or propose a switch. |
CODEX_PROXY_UNAVAILABLE | The codex / openai-* conversion daemon could not start (e.g. its loopback port is held; error_msg names the cause — only did not become ready on port <n> when the daemon exited on start). A missing codex login does not cause this — it fails on the request as KEY_INVALID. | Run cc-fleet codex-proxy status; tell the user to free the port in the provider's base_url or move it (cc-fleet edit <provider> --base-url http://127.0.0.1:<n>/, a codex provider also --models-endpoint http://127.0.0.1:<n>/v1/models), or fix the named cause. |
CODEX_CLOUDFLARE_BLOCKED | The ChatGPT backend's edge blocked this IP/client — not a key problem. | Switch network/IP or retry later; don't rotate credentials. |
SUBAGENT_MAX_TURNS | claude hit the --max-turns cap without finishing (the spent cost is surfaced — not silently $0). | Raise --max-turns (or omit it) and retry — a read-heavy / multi-file task needs ~1 turn per file read or command; a genuinely long task can use --background. |
SUBAGENT_FAILED | claude exited with no parseable result (or budget exhaustion). For a claude native leaf on a logged-out machine, this is the login failure — the error preview names it (no dedicated code). | Inspect; retry or switch provider. A logged-out native leaf → tell the user to log in to Claude Code interactively. |
SUBAGENT_OUTPUT_TOO_LARGE | The child's stdout/stderr exceeded the byte cap; the run was killed. | Have it write its output to a file and return a short answer (or narrow the ask) — a blind retry overflows again. |
SUBAGENT_STOPPED | An operator stopped the job (workflow stop / a leaf stop) — terminal, NOT a failure. | Never auto-retry; surface it. |
# These Bash calls are independent and can fire in parallel; subagent is
# lock-free, so they don't queue behind each other.
cc-fleet subagent glm --prompt "Summarize docs/a.md" --json
cc-fleet subagent glm --prompt "Summarize docs/b.md" --json
cc-fleet subagent deepseek --prompt "Summarize docs/c.md" --json
# Each returns its own {ok, result, total_cost_usd}; aggregate them. No
# team or teammate needed.A flat fan-out only — phases, dependencies, or dynamic orchestration over the results is /cc-fleet:workflow.
A finished subagent CAN wake you: a backgrounded Bash command's exit is delivered to the session as a task notification. Never spawn an agent (or loop yourself) to poll. Two shapes:
cc-fleet subagent … --json with the Bash tool's run_in_background=true, end your turn, and the harness wakes you when it exits — the envelope is the task output. Zero extra mechanism; the process is tied to your session.cc-fleet subagent --prompt "<long task>" --background --json
# → {"ok":true,"job_id":"<uuid>","status":"running","output_file":"…","pid":…}
# arm the notifier (backgrounded Bash — its exit wakes you):
cc-fleet subagent-status <job_id> --wait --timeout 5m --jsonWake-up dispatch on the exit code: 0 done (envelope has .result) · 1 failed OR stopped — check .status first: stopped is an operator stop, never auto-retry; failed, or no .status (an invalid or unknown job id) → dispatch on .error_code · 3 held (a workflow-leaf id an operator parked — surface it, never wait it out) · 124 still pending at --timeout (a heartbeat: re-arm; escalate only if the job is far past its own --timeout) · 130 interrupted. Always pass --timeout, and re-arm any still-pending wait after a session restart.
cc-fleet subagent-gc --json prunes finished job files.
--resumeContinue a prior subagent session (stateful, but not long-lived between turns — each turn is a fresh claude -p --resume):
cc-fleet subagent --resume <session_id> --prompt "<follow-up>" --json<session_id> is the .session_id from the previous turn's envelope. A default-profile (slim) resume is silent; an explicitly passed --profile over --resume warns on stderr — it swaps the system prompt mid-session. Keep the profile constant across a session's turns.
A sync subagent has nothing to tear down; "cleanup" only concerns --background job records on the Agents Board. The rules:
--resume works after gc iff you kept the id, and keeping the record without the id buys you nothing.cc-fleet subagent-gc --session <lead_session_id> --json (immediate, skips pinned) — prefer it over a blanket subagent-gc --older-than 0s so you never wipe another session's records. Default gc only removes finished jobs older than 24h; running jobs are always kept; pinned records are user-owned — never force-remove them.subagent-gc deletes the runs it reaches (--session: that session's finished runs, at once; the default: runs idle past the cutoff) with their journals and saved scripts, so workflow run --resume / restart can no longer replay them — resume or abandon a stopped or failed run before pruning. A stopped or killed run's leftover isolation worktree is first saved to a cc-fleet/wf-salvage-* branch (or kept with a .cc-fleet-keep marker if that fails); gc prints no notice, so check git branch --list 'cc-fleet/wf-*', and git worktree list for a kept directory.SendMessage / polling cc-fleet ps --check for a subagent → unnecessary; the result is on stdout.--prompt (hits MAX_ARG_STRLEN ~128 KiB) → use --prompt-file.--timeout 300s caps it, but tune per task on fan-out, and run genuinely long work via a backgrounded Bash or --background (Long tasks above).subagent-status in a loop (or delegating an agent to watch a job) → arm subagent-status --wait in a backgrounded Bash once; its exit is the notification..error_code → every --json failure carries a code; switch on it (table above; teammate-side codes in cc-fleet-shared/troubleshooting.md).claude native leaves → drains your own subscription window; use a metered provider for breadth, claude only for one or two synthesis nodes.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.