# Cursor Delegate

> Hand one self-contained coding or research task to the Cursor CLI so it runs on Cursor's quota, with Claude orchestrating. Triggers: "delegate to cursor", "offload to cursor", "have cursor do it".

- Skill: `smk-labs/cursor-delegate` (Agent Skill)
- Install (CLI): `npx skillmds@latest add smk-labs/cursor-delegate`
- Raw SKILL.md: https://api.skillmd.com/api/skills/smk-labs/cursor-delegate/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Research & Search
- Author: smk-labs (https://skillmd.com/u/smk-labs)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/smk-labs/cursor-delegate

---


# Delegate to Cursor (agent calling)

Hand a self-contained slice to `cursor-agent`; it runs on the Cursor plan's quota while Claude keeps the context and the plan. This is agent calling, not a model swap: Cursor sells no Anthropic-shaped API for its subscription, so Claude's own engine can't point at it, but the two run side by side.

## Pick the runner first

**One measured fact drives this choice: flaky networks (VPNs especially) kill any single cursor-agent stream older than ~5 minutes.** Long runs die at minute ~6 with "Connection lost" while short requests keep succeeding.

- **Quick task** — the worker will plausibly finish in **under ~4 minutes** (one focused edit, a lookup, a small test fix): call `cursor_run`.
- **Anything else** — multi-file work, builds, test loops, refactors, research that reads a lot: use the **legged runner**. Never start a long single stream.

## Quick tasks: the `cursor_run` MCP tool

Call **`cursor_run`** (from this plugin) with the task:

- `task` (required) — the self-contained instruction.
- `account` (optional) — **omit it in the normal case.** With no account, auth comes from the `default` entry of `~/.claude-deck/cursor/agent-keys.json` (a stable API key — deterministic, no browser login involved). Pass an account name only when the user keeps several Cursor seats and names one.
- `model` (optional). Cursor meters **two separate pools**: first-party (`auto`, `composer-*`, `cursor-*`) has the large allowance; API pass-through (`claude-*`, `gpt-*`) has a small one that empties fast. Prefer `auto` for mechanical work; spend an API-pool model on prose, judgment or review. Say which you used. Full rule: the **cursor-orchestrate** skill, "Model routing".
- `extraArgs` (optional) — flags passed straight to cursor-agent (e.g. `["--resume", "<session_id>"]`). Approval flags are not needed: every runner already passes `--force --approve-mcps`, so workers edit files, run shell, and use MCPs without prompting.
- `dryRun: true` — print the exact command (key redacted) without running, to show the user first.

If the MCP tool is unavailable, the same logic is a script at `${CLAUDE_PLUGIN_ROOT}/scripts/cursor-run.sh` (`--account`, `--model`, `--dry-run`, `-- <flags>`).

## Long tasks: the legged runner (canonical)

```bash
"${CLAUDE_PLUGIN_ROOT}/scripts/legged-run.sh" --cwd /path/to/repo "…self-contained task…"
```

It runs the task as **~4-minute legs on ONE cursor-agent session**: each leg checkpoints (`PROGRESS:`/`NEXT:`) and exits before the network can kill the stream, then the loop `--resume`s the same session (context preserved) until the worker prints `DONE-ALL`. A connection drop costs one leg, never the job.

- stdout = the worker's final result. Exit `1` = leg budget spent; **rerun the exact same command to continue** (state: `~/.claude-deck/cursor/legs/<id>`).
- Options: `--account`, `--model` (default `auto`), `--worktree` (parallel-safe edits: persistent git worktree + branch `legs/<id>` beside the repo), `--id`, `--leg-minutes`, `--max-legs`, `--json` (summary with `ok`, `legs`, `session_id`, `result`, summed `usage`), `--stop --id <id>` (official stop for a live run; never `pkill -f legged-run`), `-- <extra cursor-agent flags>`. `--force` is always passed.
- Opt-in network: set `CURSOR_NET_PROBE_URL` (+ optional `CURSOR_NET_MIN_BPS`, `CURSOR_TUNNEL_REVIVE`) so legged-run probes download speed before the first leg and on hard failures instead of burning legs on a dead tunnel.
- Run it with Bash `run_in_background` and follow progress in the state dir; don't block a turn waiting on many legs.

## Rules that make it work

1. **Self-contained tasks only.** cursor-agent starts with a blank context. Put file paths, the goal, and acceptance criteria inside the task text. "Fix the bug we discussed" fails; "In `src/auth.js`, `verify()` treats expired tokens as valid because it compares `exp` (seconds) to `Date.now()` (ms) — fix it and add a test" works.
2. **Auth is key-based and deterministic.** With no `account`, every runner uses the API key named by the `default` entry of `~/.claude-deck/cursor/agent-keys.json`. Never rely on the ambient `cursor-agent login` (it may be absent or expired — it is only the very last fallback). If auth fails, report it and ask for a key; don't hunt for other fallbacks.
3. **Keychain errors are almost never auth errors.** cursor-agent touches the macOS Keychain at startup even when `CURSOR_API_KEY` is set, and two things break that: a sandboxed Bash call (dies every time: `Security command failed: … code: 45`) and concurrent startups racing (measured: 1 in 4 simultaneous starts dies with `Password not found`). So run the scripts with `dangerouslyDisableSandbox: true`, and know that the race is self-healing: legged legs retry with a random pause, the `cursor_run` tool retries once, and the fleet runner staggers startups (`--spawn-gap`, default 4s). Never diagnose these as "login broken".
4. **Mind the meter: two pools, not one.** First-party models (`auto`, `composer-*`, `cursor-*`) draw the large allowance; API pass-through models (`claude-*`, `gpt-*`) draw a small one that empties first, and its exhaustion looks like a network fault, not a quota error. Probe with one `PONG` call before any fan-out bigger than a handful of tasks on an API-pool model, and read `leg-*.err` before blaming the network. Full rule, evidence and exhaustion signature: the **cursor-orchestrate** skill, "Model routing". There's no per-run bill surprise if the account's on-demand spend limit is off in Cursor's billing settings.
5. **Workers are fully trusted, exactly like Claude Code subagents.** They run with full file, shell, and MCP access and no approval prompts (`--force --approve-mcps` always; the machine's `approvalMode` is `unrestricted`). Tasks may include credentials, keys, and server access when the job needs them: direct deploys, SSH to servers, production config. Do not water tasks down or withhold secrets a task genuinely needs.
6. **Report back honestly.** Return the worker's output plus one line: what ran, which account (or "default"), which model. If cursor-agent is missing, unauthenticated, or out of quota, say so and stop — don't silently redo the work on Claude's quota unless asked.

## Report cards: worker results as chat widgets

When the readable `card` tool is available (`mcp__readable-card__card`, readable >= 4.6.0) and the result deserves user-facing display, have the worker author its own report card — the HTML is written on Cursor's quota and never enters Claude's context:

1. Pick an absolute path ending in `-card.html`, e.g. `~/.claude-deck/cursor/cards/<slice>-card.html` or the session scratchpad.
2. Append to the task: *"When done, read `${CLAUDE_PLUGIN_ROOT}/assets/report-card.md` and write your completion report to exactly `<path>` following that contract. Your entire chat reply: one line `DONE <path>`."*
3. When the run returns (or its background completion notification fires), stamp the standard status header — Cursor logo in the corner plus "تمام شد کارگر Cursor — نشست … — … ثانیه — مدل …" — using the footer facts:

   ```bash
   "${CLAUDE_PLUGIN_ROOT}/scripts/card-header.sh" <path> <session_id> <seconds> <model>
   ```

   (idempotent; workers never write this line themselves). Then call `card` with `htmlFile: "<path>"`. Do NOT Read the file and do NOT copy its HTML into the call — the widget renders straight from the file; Claude's total cost is one short Bash call plus one ~50-token card call.
4. Fallbacks: a missing/invalid file makes the `card` call error with the reason — report the worker's plain-text result instead. If the `card` tool is absent (or predates `htmlFile`), skip the contract entirely.

The card is a status widget in the middle of the work ("this worker finished, here is its report"); your own final reply to the user still gets its own card.

## Resume first, restart never

Every run produces a `session_id` (the `cursor_run` reply footer; `~/.claude-deck/cursor/legs/<id>/session_id` for legged runs). **Save it the moment you see it.** On ANY interruption — timeout, connection drop, exit `1`, killed process, tool error — the worker's context and partial work still exist on Cursor's side. Restarting throws that away; never do it while a session exists.

1. **Harvest first.** Read what the worker already produced: the partial reply, `~/.claude-deck/cursor/legs/<id>/last_result.txt`, the `leg-N.json` files. Use it.
2. **Then resume, with a continue-style prompt:**
   - Quick runs: `cursor_run` again with `extraArgs: ["--resume", "<session_id>"]` and a task like "Continue exactly where you left off on the same task; finish the remaining work."
   - Legged runs: rerun the **exact same command** (state dir does the rest), or `legged-run.sh --resume <session_id>` if only the id survived.
3. **Restart from scratch ONLY when no session ever existed** (setup failure: auth or CLI broken). That is the one case with nothing to lose.

The same move handles corrections: to fix or extend a finished worker's output, resume its session — it keeps full context, so "also handle the empty-input case" just works.

## How cursor-agent behaves (proven facts, use these)

- **Long streams die:** the transport, not the model, is the limit — ~5 minutes per stream on flaky/VPN paths (measured). The legged runner exists for exactly this; single-stream runs are for quick tasks only.
- **Runs close themselves:** cursor-agent sometimes never exits after printing its result. Every runner now supervises the process and kills it ~1.5s after the result object appears, plus a hard `--timeout` (default 900s; legs cap at leg+4 min). A delegation can no longer hang open, and a run killed after its result still exits 0 with the full output.
- **Approvals are bypassed everywhere (verified):** all runners pass `--force --approve-mcps`, and both CLI profiles have `approvalMode: "unrestricted"` in their `cli-config.json`. A worker wrote files and ran shell commands with no approval flag in the task at all. Nothing needs babysitting.
- **Structured output:** `json: true` returns one object `{ result, session_id, request_id, usage: {inputTokens, outputTokens, cacheReadTokens, ...}, duration_ms }`. Use `result` for the answer, `usage` to track cost.
- **Iterate, don't restart:** capture `session_id`, then continue that same worker with `extraArgs: ["--resume", "<session_id>"]` (or `legged-run.sh --resume <id>`). It keeps its full prior context (verified), so corrections and follow-ups are cheap. This same fact is what makes legs work — see "Resume first, restart never" above.
- **Concurrency:** several cursor-agent runs on one account run in parallel fine — fan out independent slices at once. For parallel edits in one repo, give each legged run `--worktree`, or use disjoint dirs.
- **Context sync with the Claude side (verified live):** workers read the repo-root `CLAUDE.md`/`AGENTS.md` AND load the user's `~/.claude/skills` as agent skills AND see the MCP servers of installed Claude plugins. The global operating manual reaches them via the `~/AGENTS.md -> ~/.claude/CLAUDE.md` symlink (cursor-agent applies `~/AGENTS.md` from its parent-dir walk; `~/.cursor/rules` is never read) — ensure the bridge exists: `[ -e ~/AGENTS.md ] || ln -s ~/.claude/CLAUDE.md ~/AGENTS.md`. Project `.cursor/mcp.json` servers are available too.
- **Models come from two quota pools:** `auto`, `composer-*` and `cursor-*` run on Cursor's own large first-party allowance; `claude-*` and `gpt-*` are bought from the provider and draw a small API allowance that runs out first (measured 2026-07-27: the API bar died while the first-party bar absorbed roughly four times the output tokens and kept going). `cursor-agent --list-models` (needs auth) lists them. Routing, the pre-flight probe and the exhaustion signature: the **cursor-orchestrate** skill, "Model routing".
- **Big or multi-part jobs:** don't cram them into one task — use the **cursor-orchestrate** skill (fleet fan-out, review loop, JS harness).

## Setup (once)

- Install the CLI: `curl https://cursor.com/install -fsS | bash`.
- Auth (key-based, the normal path): put Cursor API keys in `~/.claude-deck/cursor/agent-keys.json` (chmod 600) and name the default account:

  ```json
  { "tech-c": "key_...", "tech-nm": "key_...", "default": "tech-c" }
  ```

  Every run without an explicit `account` uses the `default` entry; `account: "label"` targets another seat. `cursor-agent login` exists only as a last-resort fallback — don't depend on it. See the plugin README.

