ethanhq/cc-fleet/workflow

Claude Code and agent skill by ethanhq/cc-fleet

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Orchestrate a MULTI-PHASE, dependent, or resumable run over many provider subagents from a JS script, off the main context (`cc-fleet workflow`). Use for fan-out→barrier→synthesis, per-item pipelines, loop-until-dry, or a run that must survive a kill and `--resume` from its journal. NOT a flat fan-out of independent tasks (that is /cc-fleet:subagent — cheaper, no script); NOT interactive collaboration (that is /cc-fleet:team); NOT trivial single-shot work for the main session.

Install

npx vskill@latest install ethanhq/cc-fleet/workflow

SKILL.md

workflow — multi-phase JS orchestration over provider subagents

Wrong lane? A flat one-shot fan-out of independent tasks → /cc-fleet:subagent; interactive collaboration you message back and forth → /cc-fleet:team; 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.

A workflow is a JavaScript script that fans out provider cc-fleet subagent leaves and runs in a cc-fleet process, OFF the main session's context. You write the script; cc-fleet workflow run executes it. The orchestration plan lives in script variables (CPU, ~0 of your tokens) — you are invoked only when authoring the script, not on every scheduling decision. The API mirrors the native Claude Code Workflow tool — write the script exactly as you would a native workflow; the only addition is the provider option on agent().

When to use it

  • Multi-phase or dynamic orchestration over many provider subagents: fan-out + barrier, per-item pipeline, loop-until-dry, branch-on-result, with a board run-tree.
  • A single flat batch of independent one-shots is not a workflow — that's /cc-fleet:subagent. Don't write a script for it.

The provider ask ladder (ask at most once per task)

  1. The user named a provider or model → use it.
  2. Else run 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)").
  3. Else (several providers, none default) ask the user ONCE which to use — list the enabled providers from 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.)
  4. A mid-task provider failure (insufficient balance / rate limit / auth) → STOP, tell the user what happened, propose the next provider, and WAIT for their confirmation. Never switch providers silently.

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.

In a script, agent()'s opts.provider is optional: omitted, the leaf uses the run's default provider, resolved ONCE at launch and recorded with the run — so --resume stays stable even if the default changes later. A script meant to be shared or reproducible should still pin provider explicitly.

The script API (mirrors the native Workflow tool)

  • const meta = {name, description, whenToUse?, model?, phases?: [{title, detail?}]} — a top-level pure literal (no calls/vars/spreads; the native export const meta form is also accepted). name + description are required; model is the default for agents that omit it. Read statically before the run → the board shows the named, phase-skeletoned run immediately.
  • agent(prompt, opts) → Promise<string|object> — runs ONE provider subagent leaf. opts.provider is optional (omitted → the run's default provider, above); provider: "claude" runs the official claude CLI on the user's OWN Claude Code login (subscription OAuth) instead of a configured provider — a literal model id (fable/opus/sonnet/a full id, omitted → claude's login default, typically the costliest tier so name one), no roster keywords, no key material. The rest are optional: model, schema, label, phase, timeout (seconds), max_budget_usd, max_turns, isolation: "worktree", profile ("slim" default / "slim-ro" / "full"), tools, skills, mcp. An unknown option key throws (typos fail loudly). On a leaf failure the promise rejects — an un-caught top-level await agent() aborts the run; inside parallel/pipeline a failed element degrades to null. Leaf failures classify like subagent failures — dispatch table in "Leaf failures" below.
  • `schema` (a plain object) goes to the claude child via --json-schema: claude injects a forced StructuredOutput tool and enforces that it is CALLED (the native mechanism — no JSON instruction is added to the prompt); the promise resolves with the parsed structured payload. The three rules:
  • a validation failure — or a result envelope without a structured payload — FAILS the leaf; there is NO automatic retry;
  • the forced StructuredOutput call costs turns — give a schema'd leaf max_turns ≥ 3 (a budget of 1 starves it);
  • needs claude ≥ 2.1.88 (the slim-profile floor); an older claude fails the leaf with a classified usage error.

Client-side validation backstops with a recursive JSON-Schema subset: type (object/array/string/number/integer/boolean/null; integer accepts 5.0), required, nested properties, array items, scalar enum, string pattern (RE2 best-effort — the wire enforces the authoritative ECMA regex) / format (email/uri/uuid/date/date-time), additionalProperties, allOf/anyOf/oneOf, and intra-document $ref (#/… pointers; an external URI is unsupported and fails).

  • `isolation: "worktree"` runs the leaf with cwd = a fresh git worktree, so parallel file-editing leaves don't collide (requires a git repo). When the leaf ends, a clean worktree is removed; one with changes or new commits is first snapshotted to the branch cc-fleet/wf-<job>-a<n> in your repo (list them with git branch --list 'cc-fleet/wf-*'; the engine log — workflow watch — has a kept line naming it), then removed. If the snapshot fails, the directory stays where it is with a .cc-fleet-keep marker — save the work, then delete the directory yourself. If workflow watch shows UNPROTECTED for it, the marker could not be written and nothing shields that directory from cleanup: copy it out by hand before any workflow restart, rm or prune, or a new run in this repo. The worktree starts at HEAD, so uncommitted changes in your checkout are not visible to the leaf, and its edits reach your checkout only when you merge or cherry-pick the cc-fleet/wf-* branches; cc-fleet never deletes them (git branch -D once merged). A whole-run workflow stop or an engine crash can cut a leaf off before its snapshot finishes (a stop --leaf hold saves normally): the next --resume / restart or workflow rm / prune rescues that work to cc-fleet/wf-salvage-<run>-<8 chars> without logging it, and a later run's startup sweep in the same repo rescues it with an isolation worktree salvaged line in that run's events. A resume or restart also clears the old kept lines — after a stop, find the work with git branch --list 'cc-fleet/wf-*', not workflow watch.
  • `profile`: "slim" (the default; write-capable) / "slim-ro" (read-only research) / "full" (ONLY to compare against a full session or diagnose a suspected slim regression). Writes files → slim, read-only → slim-ro. tools, skills (default true) and mcp refine a slim leaf, are rejected with profile: "full", and tools REPLACES the whole set, never appends. Tool whitelists / per-profile mcp defaults / the pre-2.1.88 fail-open downgrade: cc-fleet-shared/providers.md. The run journal folds the effective profile + tools, so a --resume re-runs a leaf whose shape changed.
  • Background = an unawaited promise. There is no run_in_background/wait(): start a leaf with const p = agent(...), keep working, await p later (Promise.all for a batch). Every leaf — awaited or not — is pool-bounded, journaled at completion, and the run only finalizes after all of them settle. A leaf that rejects with nobody ever handling it fails the run (a silently dropped failure is still a failure); fire-and-forget tolerance is an explicit p.catch(() => null).
  • parallel(thunks) → Promise<array> — run each 0-arg thunk concurrently; BARRIER (settles once all finish), null where an element failed: await parallel([() => agent("a", {provider: "glm"}), () => agent("b", {provider: "glm"})]). Concurrent execs stay ~pool size even for a huge list (excess queues).
  • pipeline(items, ...stages) → Promise<array> — push each item through all stages independently with NO inter-stage barrier (item A can be in stage 3 while B is in stage 1). Each stage is (prev, item, index) => … (sync or async; its return value is awaited). A failing stage drops that item to null and skips its remaining stages. DEFAULT to `pipeline` over `parallel` — only use parallel when a stage genuinely needs ALL prior results together.
  • workflow(path, args?) → Promise — run another .js inline on the same engine (shared pool/journal/budget), one level deep only; resolves with the child's top-level return value. A relative path resolves against the run's directory (where workflow run was launched, kept for --resume / restart), not the calling script's directory — use an absolute path when the scripts live elsewhere. The child script is read and checked only when workflow() reaches it, not at launch.
  • budget — two parallel cap surfaces. USD: budget.total (the --budget-usd cap in USD, or null), budget.spent(), budget.remaining() (Infinity when uncapped) — USD floats (an Anthropic list-price estimate). Tokens: budget.tokens_total (the --budget-tokens cap, or null), budget.tokens_spent(), budget.tokens_remaining() — ints (input+output, cache-read excluded). agent() throws when the next leaf does not fit: each call reserves $1.00 (or its larger max_budget_usd) and 50,000 tokens as soon as it is made — before it waits for a slot — until the leaf is charged its real cost, and is refused when spent + held reservations + its own would pass either cap (a leaf replayed from the journal on --resume reserves nothing). A refused call never waits (a lower --max-concurrency does not help): a cap under $1.00 / 50,000 tokens runs no leaf, a fan-out of N leaves needs about N × $1.00 of room (the rest come back null from parallel(), each refusal logged in workflow watch), and a while (budget.remaining() > N) loop scales depth to the cap only with N ≥ one reservation (remaining() does not subtract reservations). (Native's budget.total is a token target; here it is USD — --budget-usd is the cross-provider cap since providers price tokens differently — and tokens are the separate tokens_* surface.) A provider: "claude" leaf spends the lead session's own subscription window, not a metered provider — use it for

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
185
Repository forks
32
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/ethanhq/cc-fleet/workflow/badge)](https://verified-skill.com/skills/ethanhq/cc-fleet/workflow)

Something wrong with this skill or its page? Tell us.