Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Cc Delegate

БесплатноНе проверен

Delegates heavy development tasks from a supervisor to an autonomous worker on a cheaper model via MCP, with isolated git worktrees and provider-agnostic suppor

GitHubEmbed

Описание

Delegates heavy development tasks from a supervisor to an autonomous worker on a cheaper model via MCP, with isolated git worktrees and provider-agnostic support.

README

cc-delegate

Delegate a whole dev task from your frontier-model supervisor to a cheaper worker model — isolated in a git worktree, graded against a rubric, reviewed as one clean diff.

License: MIT  Claude Code plugin  Runtime: uv

cc-delegate demo: the supervisor plans the work, hands it to a worker model, then reviews the finished branch

Your supervisor — Claude Code on a frontier model — stays on Anthropic and keeps doing what it's good at: planning and reviewing. A worker on any cheaper, litellm-routable model does the heavy implementation in the background, in its own git worktree. You review one diff at the end instead of watching a stream of half-finished edits, and only the worker's tokens land on the alternate provider.

Why cc-delegate

  • Whole tasks, not per-call routing. One run_dev_task hands off a complete bounded task — implement, test, iterate — behind a single tool call, instead of routing individual completions.
  • Isolated by construction. Every task runs on its own delegate/<task_id> branch in a throwaway worktree. Nothing touches your working tree until you review the diff.
  • "Done" is graded, not claimed. A rubric checks the result against your definition_of_done and test_command, so the worker can't declare victory on its own say-so.
  • Non-blocking. run_dev_task returns a task_id immediately and the worker runs in the background. The supervisor ends its turn and polls on a schedule it sets itself, so you keep its full attention in between.
  • Bounded. A cost cap, a git-history guard, and a stall watchdog keep a runaway worker from overspending, touching shared branches, or hanging past its limits.

What a delegation looks like

Ask the supervisor to take on something large and the packaged skill kicks in:

You: Delegate implementing the token-refresh flow in src/auth/ — tests must pass.

Supervisor: Starting a delegated task… run_dev_taskt_…yqsldx. I'll check back in a couple of minutes.

(a few cheap status polls later)

Supervisor: Done — 4 files changed, tests green, $0.24. Here's the diff.

The worker did that for $0.24; the supervisor spent only the handful of tokens to scope the task and read the diff back. That split is the point — the expensive model plans and reviews, the cheap one types.

When to delegate. Reach for it on large, bounded work: a multi-file feature, a refactor, a test-and-iterate loop. Skip it for one-line fixes and read-only questions — the supervisor answers those directly, faster than it can stand up a worktree.

How this compares

These tools overlap with cc-delegate without being drop-in alternatives; each sits at a different point in the design space. I haven't run them in anger, so the notes below are read from their docs — directional, not a benchmark.

Dimension cc-delegate houtini-lm Roo Code Orchestrator
Unit of work A whole multi-turn task with its own agent loop A single model call, routed per request A subtask inside Roo's orchestrator/mode system
Completion check Rubric graded against your definition_of_done / test_command Caller decides Orchestrator reads the subtask's summary back
Isolation Own git worktree + branch per task Per-call, so there's no persistent state to isolate Separate context per subtask, shared workspace
While it runs Async: returns a task_id, supervisor polls on its own schedule Synchronous: the caller waits on the call Synchronous: the orchestrator waits on the subtask
Setup & overhead Needs uv and a worktree per task Just an MCP call — nothing to provision Install the VS Code extension

In practice. houtini-lm — also a Claude Code MCP server — is the lighter touch when you want to route individual completions and don't need isolation or a task loop; there's nothing to stand up. Roo Code fits if you'd rather work inside a full VS Code extension with its own UI than a Claude Code plugin. Both reach plenty of providers — houtini-lm through local runtimes (LM Studio, Ollama, vLLM) and hosted ones, Roo Code per-mode via LiteLLM — so provider breadth isn't the deciding axis. cc-delegate earns its worktree-and-rubric overhead when the thing you want to hand off is a whole bounded task and get back one reviewed diff.

Install

Installing the plugin is one command, but two things live outside Claude Code's control: a worker API key and uv. Neither is guaranteed just because you have Claude Code. Go in order:

1. Get a worker API key. You'll need a key for whatever provider the worker runs on. Out of the box that's MiniMax — sign up at platform.minimax.io and generate a key — but any litellm-routable provider works; skip ahead to Configuration to point it elsewhere.

2. Install uv if uv --version doesn't already show it. That's the only runtime prerequisite: uv run resolves the server's and worker's inline Python dependencies (and Python itself, if needed) on first use — no pip install, no Node.js, no build step.

3. Set DELEGATE_API_KEY as a persistent environment variable, then restart Claude Code. This is the step most likely to trip you up: .mcp.json's ${DELEGATE_API_KEY} only reads the OS-level environment of the process that launched Claude Code — there's no .env auto-loading and no interactive prompt. Setting it after Claude Code is already running does nothing until you restart from a shell that has the variable.

# Windows (PowerShell) — persists across terminals; restart Claude Code afterward
[Environment]::SetEnvironmentVariable("DELEGATE_API_KEY", "your-key-here", "User")
# macOS/Linux — add to ~/.zshrc or ~/.bashrc, then open a new shell
export DELEGATE_API_KEY="your-key-here"

4. Install the plugin.

/plugin marketplace add EtienneLescot/cc-delegate
/plugin install cc-delegate@cc-delegate-marketplace

Or locally during development: claude --plugin-dir .

5. Verify. Run /mcp — the checkpoint that surfaces a missing uv/key before you're mid-task. A SessionStart hook additionally probes uv --version at the start of every session as an earlier best-effort check (exec-form, so it behaves the same on Windows/macOS/Linux); treat it as a bonus signal, not the primary one.

Configuration

The facade (preferred). The plugin configures itself through its own MCP tools, driven conversationally from Claude Code — no restart needed, changes apply to the next task:

  • "Show me the provider status"provider_status lists your model profiles, the default, and per-profile auth state (key reachable? OAuth token cache present?).
  • "Add a deepseek profile"set_model_profile("deepseek", "litellm:deepseek/deepseek-chat", "DEEPSEEK_API_KEY"); set_default_profile / remove_model_profile manage the menu.
  • "Add a fallback to deepseek if MiniMax fails"set_model_profile("mm", "litellm:minimax/MiniMax-M3", "MINIMAX_API_KEY", fallback_models=["litellm:deepseek/deepseek-chat"]) — tried in order via litellm's own fallback mechanism if the primary model's call fails.
  • "Store my key for the deepseek profile"store_api_key("deepseek") asks for the key through a native Claude Code dialog (MCP elicitation, Claude Code ≥ 2.1.199): the secret goes straight back to the server without ever entering the model's conversation.
  • Per task: "delegate this on the deepseek profile"run_dev_task(..., profile="deepseek"). The supervisor's skill forbids it from picking a non-default profile on its own.

Profiles live in ~/.cc-delegate/config.json, facade-stored keys in ~/.cc-delegate/credentials.json. Any litellm-routable model works — see litellm's provider list.

Subscription providers (OAuth). For a profile on an OAuth provider — GitHub Copilot (set_model_profile("copilot", "litellm:github_copilot/gpt-5"), no API key) or ChatGPT (set_model_profile("chatgpt", "litellm:chatgpt/gpt-5.3-codex")) — run setup_provider_auth("<profile>"). It returns a verification URL and a user code; visit the URL, enter the code, authorize, and auth_poll(flow_id) flips to authorized. litellm caches the tokens, so later runs need no interaction and the key never touches the config. The device flow is exercised for GitHub Copilot; the ChatGPT adapter is wired the same way but hasn't yet been run end-to-end against a live subscription.

On terms of service (this varies by provider): OpenAI supports third-party tools using a ChatGPT subscription this way — its Codex for Open Source program lists such tools explicitly — and GitHub Copilot's device flow is widely used by third-party editors. Anthropic prohibits subscription use outside Claude Code itself, and Google does the same for Gemini CLI, so cc-delegate implements OAuth for neither.

Legacy env path (still supported). See .env.example for the full list: DELEGATE_API_KEY, DELEGATE_MODEL, DELEGATE_API_KEY_ENV_VAR, and the guardrails (DELEGATE_RECURSION_LIMIT, DELEGATE_RUBRIC_MAX_ITERATIONS, DELEGATE_TIMEOUT_MS, DELEGATE_STALL_TIMEOUT_S, DELEGATE_MAX_BUDGET_USD, DELEGATE_ASK_TIMEOUT_S). This path applies when no profile is defined; env changes require restarting Claude Code (the restart trap in Install step 3 only concerns this path).

Architecture

flowchart LR
  Supervisor["Claude Code supervisor<br/>(Anthropic API)"]
  MCP["cc-delegate MCP server<br/>Python (uv run server/main.py), stdio<br/>run_dev_task (async), get_task_status,<br/>get_task_progress, answer_worker, steer_task,<br/>cancel_task, fetch_task_result, cleanup_task"]
  Worktree["Disposable git worktree<br/>branch delegate/&lt;task_id&gt;"]
  Worker["uv run worker/worker.py<br/>deepagents loop<br/>+ implementer / tester / reviewer subagents<br/>+ rubric grader"]
  Provider["Provider<br/>(litellm-routed,<br/>e.g. MiniMax M3)"]
  Review["Supervisor review<br/>of patch / diff"]

  Supervisor -->|"run_dev_task /<br/>get_task_status / get_task_progress /<br/>steer_task / fetch_task_result / cleanup_task"| MCP
  MCP -->|"createWorktree()"| Worktree
  MCP -->|"uv run worker.py"| Worker
  Worker -->|"litellm completion"| Provider
  Provider -->|"model response"| Worker
  Worker -->|"PROGRESS: {step, node, ...}<br/>QUESTION: {id, message}<br/>(live, flushed per step)<br/>RESULT_JSON: {status, summary,<br/>turns, cost_usd, total_tokens,<br/>rubric_status, error}"| MCP
  MCP -->|"status + progress<br/>(get_task_status, on poll)"| Supervisor
  Worktree -->|"git diff --cached"| MCP
  MCP -->|"patch + diff"| Review

The MCP server (server/main.py, official mcp Python SDK, run via uv run) exposes the delegation tools to the supervisor over stdio:

Tool What it does
run_dev_task Start a delegated task (preflights your test_command first) and return a task_id immediately — the worker runs in the background.
get_task_status Cheap liveness: running / needs_input / done. Poll it as often as you like.
get_task_progress Verbose audit: files written so far, recent activity, cost. Call occasionally.
answer_worker Reply to a worker blocked on a question.
steer_task Redirect a running worker at any moment — delivered at its next tool call.
cancel_task Kill a stalled/runaway worker's whole process tree, salvaging its work.
fetch_task_result Final summary, patch, files changed, cost — including salvaged work from failed runs.
cleanup_task Tear down a finished task's worktree, branch, and persisted job file.
  • Job persistence — every job is mirrored to <repo>/.cc-delegate/jobs/<task_id>.json on each state change, so status, result, and cleanup queries survive MCP-server restarts: the in-memory registry is rebuilt from disk on demand.
  • The worker (worker/worker.py) is a deepagents agent, run as a subprocess via uv run. It uses LocalShellBackend in virtual_mode=True to scope filesystem and shell access to the worktree, SubAgents for implementer/tester/reviewer roles, and RubricMiddleware to grade completion against your definition_of_done/test_command rather than the model's own "I'm done". Each run reports cost_usd and total_tokens via a litellm callback and prints a flushed PROGRESS: line per step.
  • The packaged skill (skills/delegate-heavy-dev/SKILL.md) teaches the supervisor when and how to delegate.
Why deepagents-as-a-library, not a CLI agent

We started with the worker calling @anthropic-ai/claude-agent-sdk's query() pointed at a third-party endpoint, then tried shelling out to CLI coding agents (OpenCode, dcode) — both hit either an unresolved Claude Code CLI headless-auth bug or a Windows/no-TTY hang in dcode's rich terminal UI. Calling deepagents directly as a library sidesteps both: no CLI, no TTY dependency, and real control over the loop (subagents, rubric-based convergence) instead of a black-box CLI. The full story — three worker engines, two upstream bugs — is in docs/build-journey.md; the reproducible bug reports are in KNOWN_ISSUES.md.

Supervision model — async, scheduled polling

run_dev_task returns a task_id immediately and the worker runs in the background. The supervisor never blocks: a standard MCP server can't push into the model's context, so the worker can't call the supervisor — but the supervisor doesn't need to sit and wait either. It ends its turn (free) and re-checks on a cadence it schedules itself: a background wait re-invokes it ("I'll check in ~2 min"), or it simply checks when you next speak. Between checks, you have its full attention.

Two polling tools, split by cost so frequent checks stay cheap:

  • get_task_status — a tiny payload (running / needs_input / done, plus the pending question if blocked). Poll it freely; it barely touches the context.
  • get_task_progress — a verbose audit (files written, recent shell commands, step, cost, elapsed). Heavier, so the supervisor calls it occasionally, or when you ask "how's it going?".

On needs_input, the supervisor decides: answer from its own context with answer_worker, or relay the question to you when it's genuinely your call. On done, it reviews with fetch_task_result.

For large work, the supervisor decomposes into bounded sub-tasks and runs independent ones (different files) in parallel — each run_dev_task gets its own worktree/branch — while serializing sub-tasks that touch the same files to avoid merge conflicts.

Why not a blocking "watch" call or MCP progress notifications?

Both were tried and removed. A blocking call freezes the supervisor for the whole run, and progress notifications never enter the model's context and aren't rendered by the desktop app — so neither gives the supervisor something it can actually act on. Scheduled polling does.

Status line — always-visible ambient indicator (TUI)

For a passive, glance-able view without asking the supervisor, the status line keeps a one-line summary in Claude Code's status bar, token-free (TUI only — the desktop app does not render custom status lines):

⏳ delegate t_…yqsldx · MiniMax-M3 · step 24 · writing src/auth/tokens.js
⚠ delegate t_…yqsldx · asks: which token TTL? · → answer_worker
✓ delegate t_…yqsldx · done · 4 files · $0.24

It stays token-free on both ends: the MCP server (already resident) renders the line in Python and writes it to ~/.cc-delegate/statusline; the status-line script Claude Code runs is a dependency-free reader (no jq, no python, no JSON parsing) that just prints the pre-baked line while it's fresh. The harness runs it locally, so it never consumes API tokens.

Wire it once in ~/.claude/settings.json (refreshInterval is required — status-line event triggers go quiet while the session waits on the background worker, so the timer keeps the line live):

{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/cc-delegate-statusline.sh",
    "refreshInterval": 2
  }
}

Copy statusline/cc-delegate-statusline.sh (or, on Windows without Git Bash, the .ps1 variant) to ~/.claude/ and chmod +x it. A running task refreshes the line on every event; a blocked task keeps its question visible until you answer; a finished task shows a short-lived summary that then fades — no stale state left on screen.

Worker ↔ supervisor communication (and steering)

The worker is not fire-and-forget. Three tools are injected into its agent loop:

  • report_progress(update) — fire-and-forget one-liners at phase transitions; they surface through get_task_progress and the status line.
  • ask_supervisor(question, context) — blocks the worker (zero tokens while waiting) and flips the task to needs_input. The supervisor discovers the question on its next get_task_status poll, answers from its own context or relays it to you, then replies with answer_worker. If no answer arrives within DELEGATE_ASK_TIMEOUT_S (default 600s), the worker proceeds on its best conservative judgment.
  • report_blocker(problem, attempts) — same mechanism, for "I've failed 3 times at the same error": the supervisor can correct course instead of letting the worker thrash until timeout.

Answers travel out-of-band through a file mailbox in <repo>/.cc-delegate/comm/<task_id>/, never through the model conversation.

The other direction — steer_task(task_id, message) lets the supervisor redirect a running worker at any moment, not only in reply to a question: "stop implementing X, do Y instead." It doesn't block the worker or change its status; the message sits in the mailbox until the worker's next tool call picks it up, typically within seconds. (Interrupting an in-flight LangGraph step from outside would need a checkpointer, which this architecture doesn't use.) In testing, a message dropped mid-task showed up in the next shell command's output and the worker changed course on its following turn.

Safety

  • Worktree confinement. The worker's LocalShellBackend runs in virtual_mode=True, scoping filesystem and shell access to the disposable worktree. The supervisor always reviews the diff before deciding whether to merge branch delegate/<task_id>.
  • Git-history guard. SupervisedShellBackend refuses git push / merge / rebase before they run — the worker only ever operates on its own disposable branch, so there's no legitimate reason to touch shared history.
  • Budget cap. run_dev_task(..., max_budget_usd=...) (default from DELEGATE_MAX_BUDGET_USD, $5) stops the worker as soon as accumulated cost crosses the cap, checked after every step against the live cost tracker — so a run can't drift unbounded.
  • Stall watchdog. If the worker goes silent longer than DELEGATE_STALL_TIMEOUT_S (default 300s) — e.g. a hung provider call inside rubric grading — its process tree is killed and the run fails fast instead of hanging until the full 30-minute run timeout. Salvage still runs, so completed work isn't lost. A worker legitimately waiting on answer_worker is exempt.
  • Secret filtering. The worker's shell environment drops anything matching API_KEY/TOKEN/SECRET/PASSWORD/CREDENTIAL; facade-stored keys and OAuth tokens never enter the model's conversation.

For maintainers

No build step. The server is plain Python (server/, stdlib + the mcp SDK declared inline in main.py); the worker is worker/worker.py. Run the test suite with:

uv run python -m unittest discover -s server -p "test_*.py"

Verify the wiring end-to-end:

  • /mcp lists the cc-delegate server and its tools.
  • /status in the supervisor session still shows api.anthropic.com — no worker config ever leaks into the supervisor process.
  • Ask the supervisor to delegate a heavy task; it should call run_dev_task, poll get_task_status, then present the diff via fetch_task_result.

License

MIT for this repository's own code. See NOTICE for a note on third-party terms of use.

from github.com/EtienneLescot/cc-delegate

Установка Cc Delegate

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/EtienneLescot/cc-delegate

FAQ

Cc Delegate MCP бесплатный?

Да, Cc Delegate MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Cc Delegate?

Нет, Cc Delegate работает без API-ключей и переменных окружения.

Cc Delegate — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Cc Delegate в Claude Desktop, Claude Code или Cursor?

Открой Cc Delegate на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Cc Delegate with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development