cursorctl
Use the `cursorctl` CLI (Cursor SDK Bridge) to spawn, send, detach, follow up, inspect, and collect Cursor cloud or local agents. Trigger when delegating work to Cursor cloud agents (`bc-…` IDs), runn
SKILL.mdplugins/cursorctl/skills/cursorctl/SKILL.md
GitHubcursorctl
cursorctl is a Go CLI over the Cursor SDK Bridge. Use it for agent-to-agent delegation from Claude Code: start Cursor cloud agents against GitHub repos, detach, inspect runs later, send follow-ups, and collect results. It also supports local Cursor agents against this machine's filesystem.
Do not invent SDK Bridge HTTP/RPC calls. Drive everything through cursorctl in Bash. Keep this hub short; open a reference file only when needed.
Canonical source: nickmisasi/cursor-utils (skills/cursorctl/). This plugin is the Claude Code translation of that skill.
Claude Code runtime
- Run every
cursorctlinvocation with Bash. Do not use Claude Code's Agent/Task tool to spawn Cursor cloud agents — those subagents are Claude processes, not SDK Bridge agents. Cursor cloud IDs start withbc-and exist only throughcursorctl. - Only create or send to agents when the user asked to delegate to Cursor or the task clearly requires a Cursor cloud/local agent. Confirm the
--repoURL (and ref) before the first create/prompt. - Interactive TTY prompts do not work here. If auth is missing, tell the user to run
cursorctl auth add <name> --stdin --defaultthemselves. Never print, log, or pass a raw API key on the argv. - Blocking
agent prompt,agent send(without--detach), andrun waitcan run for many minutes. Prefer--detachplusrun get/run wait/run watch, or set a Bash timeout well above the expected run.--detachis not cancellation. - If
command -v cursorctlfails, stop and tell the user how to install it. Do not emulate the CLI.
Binary and auth
command -v cursorctl
cursorctl version
If it is missing, install from GitHub Releases (linux/darwin amd64/arm64; not Windows) or go install github.com/nickmisasi/cursor-utils/cursorctl@latest. A common local path is ~/.local/bin/cursorctl.
Store a user API key from https://cursor.com/dashboard/api. Do not export CURSOR_API_KEY in shell rc files; Cursor's agent CLI treats that variable as higher-priority than stored login.
cursorctl auth add work --stdin --default
Key resolution: --api-key → env named by --api-key-env → --profile/CURSORCTL_PROFILE → stored default.
The first bridge-backed command downloads the pinned SDK Bridge (v1.0.27), verifies SHA-256, and caches it under ~/.cache/cursorctl/sdk-bridge/. Pre-fetch with cursorctl bridge install.
Use explicit cloud flags when delegating. --repo URL[@ref] selects cloud; without cloud-only flags the CLI builds local options and uses --cwd (default: --workspace).
Start here
cursorctl agent prompt \
--repo https://github.com/acme/widgets@main \
--auto-create-pr \
--skip-reviewer-request \
--quiet \
"Fix the failing tests, verify the fix, and open a PR."
The three delegation patterns
1. One-shot: agent prompt
Create an agent, send one message, consume its run, then close the agent:
cursorctl agent prompt --repo "$REPO_URL@main" --auto-create-pr --quiet \
"Implement the issue, run tests, and open a PR."
Use for one task with no follow-up. Omit --quiet for NDJSON events. In Claude Code, prefer --detach (pattern 2) unless you can wait the full run in one Bash call.
2. Fire-and-forget: agent send --detach
Create a durable cloud agent, then detach as soon as its run ID is known:
agent_id="$(cursorctl agent create --repo "$REPO_URL@main" --auto-create-pr |
jq -r '.agentId')"
cursorctl agent send "$agent_id" --detach "Implement the issue and open a PR."
# {"agentId":"bc-...","runId":"..."} (pretty-printed in default JSON)
Save both IDs. Later use cursorctl run get RUN_ID, run wait RUN_ID, or run watch RUN_ID. Detaching closes only the client stream; it does not cancel the server-side run.
This is the default pattern from Claude Code when the run may outlive a single Bash timeout.
3. Durable conversation: create, send, follow up
agent_id="$(cursorctl agent create --repo "$REPO_URL@main" --auto-create-pr |
jq -r '.agentId')"
cursorctl agent send "$agent_id" --quiet "Implement the issue."
cursorctl agent send "$agent_id" --quiet "Now add regression tests and update the PR."
Use when later messages need the same agent's conversation context.
When to open a reference file
| If the task is... | Read |
|---|---|
| Looking up any command, positional argument, flag, RPC, payload, or response | references/command-reference.md |
| Delegating cloud work, detaching, following up, triaging agents, or collecting results | references/delegation-patterns.md |
Parsing streams, choosing JSON/YAML/TOON, using --json, or handling exit codes |
references/output-and-json-mode.md |
| Debugging auth, bridge installation, truncated streams, runtime routing, or failures | references/troubleshooting.md |
Wire-level SDK Bridge details: sdk-bridge-protocol.md.
Local agents and custom tools
Local agents run on this machine against --cwd; a model is required. Cloud agents clone --repo; their IDs start with bc-.
For local agents, agent create --custom-tool NAME=COMMAND declares a tool. Pass the same executor flag to agent send so cursorctl runs a loopback callback server. The command receives tool-argument JSON on stdin and should return a JSON object on stdout. See the command reference before using --custom-tool-config.
Local custom tools require the agent send/agent prompt process to stay attached; --detach shuts down the loopback executor.
Top traps
- Exit
2is a completed run with terminal statusERROR,CANCELLED, orEXPIRED; exit1is a CLI, bridge, RPC, or stream failure. Exit0meansFINISHEDfor run-returning commands. --jsonis a complete raw RPC request, not an extra options object. It conflicts with positional and per-field flags by default.--quiet,--detach, artifact--file, and custom-tool executor flags are the documented exceptions where applicable.me,models, andreposrequire the Cursor API key insideoptions; cursorctl injects it from--api-key, the env named by--api-key-env,--profile/CURSORCTL_PROFILE, or the stored default profile (cursorctl auth add).--detachis not cancellation.agent prompt --detachskipsCloseAgent. Follow up later withagent send bc-...(it resumes in the same process, then sends). Usecursorctl run cancel RUN_IDto request cancellation.agent send,agent prompt, andrun watchwrite one compact JSON event per line regardless of-o. Use--quietto suppress events and format only the final result with-o.run watch --after-offsetaccepts only an offset previously emitted byrun watch/ObserveRun, not an offset from the initialagent sendstream.- Cloud dashboard hides SDK agents by default; filter Source → SDK, or open
https://cursor.com/agents/bc-….