Hand a bounded coding, research, review, or debugging task to the locally installed
Cursor CLI (cursor-agent) and get the result back —
from Claude Code or Codex CLI.
cursor-agent is a real agent: tools, file editing, shell, running on your Cursor subscription.
This skill drives it headlessly, keeps one Cursor thread per work unit, and never touches your
Claude/Codex session.
Everything here was verified against
cursor-agentv2026.08.04 on 2026-08-07, on macOS. Where a claim is untested, it says so.
- Headless delegation —
cursor-agent -p "…" --output-format json, wrapped so you pass a task and a profile, not a pile of flags. - Session reuse — one work unit maps to one Cursor thread, auto-resumed via
--resumefrom a small JSON registry with atomic locked writes. - Safety profiles — a fixed situation → policy mapping, enforced by real CLI flags
(
--mode plan/--mode ask/--sandbox) rather than by asking the model nicely. - Both hosts — a Claude Code skill (plus a native subagent definition) and a Codex CLI skill, sharing one session registry.
- Cursor CLI, installed and signed in. The wrapper looks for
cursor-agentonPATH, then~/.local/bin/cursor-agent. python3— used only for registry reads and writes. No other runtime dependencies.- Claude Code and/or Codex CLI.
git clone https://github.com/emergency-lee/cursor-cli
cd cursor-cli
./install.sh # installs into ~/.claude and ~/.codex, whichever existManual copy, if you prefer:
# Claude Code
mkdir -p ~/.claude/skills ~/.claude/agents
cp -r claude/skills/cursor-cli ~/.claude/skills/
cp claude/agents/cursor-cli.md ~/.claude/agents/
# Codex CLI
mkdir -p ~/.codex/skills
cp -r codex/skills/cursor-cli ~/.codex/skills/cursor-agent will fail with:
Error: Your macOS login keychain is locked.
Unlocking the keychain does not fix it, and neither does logging in again. The message is misleading.
The real OS error is errSecInteractionNotAllowed: your session is not a member of the macOS Aqua
security session, so it cannot read the login keychain at all. Opening the padlock on the Mac itself
does not propagate to an SSH session — they are separate security sessions.
Set both of these:
export CURSOR_API_KEY=... # from cursor.com/dashboard/api
export AGENT_CLI_CREDENTIAL_STORE=file # skips the keychain check — undocumentedOne alone will not work. The keychain check runs before the API key is read, so a key by itself
never gets reached, which is also why even cursor-agent --help fails. From the CLI's own bundle:
shouldCheckKeychain = platform === "darwin" && likelySshSession && !isCI && store === "default"Your session already satisfies the first three, so flipping store is the only way out.
AGENT_CLI_CREDENTIAL_STORE appears in no documentation we could find; it came from reading the
shipped JavaScript.
# Claude Code host
~/.claude/skills/cursor-cli/scripts/cursor_run.sh \
--unit frontend --profile implement --cwd /path/to/repo \
-- "Implement the change, then report changed files and results."
# read-only review, prompt via stdin
~/.claude/skills/cursor-cli/scripts/cursor_run.sh --unit review --profile consult --cwd "$PWD" <<'EOF'
Review this diff. Return only findings with file evidence, ranked by confidence. Do not modify files.
EOFCalling the same --unit again resumes its Cursor thread; --new rotates it. The registry at
~/.claude/cursor-sessions.json holds only session_id / model / profile / host / updated_at / status — never secrets, never prompt bodies.
| Profile | Situation | Flags |
|---|---|---|
consult (default) |
local diagnose / review / explain | --mode plan --trust |
research |
needs current external info | --mode plan --trust |
implement |
user-authorized edits | --force --trust |
sandboxed |
untrusted / high-risk | --mode ask --sandbox enabled --trust |
Read-only is the default, and it is enforced by the CLI, not by prompt text. --mode plan refuses
edits; --mode ask refuses edits and shell. The policy preamble is still injected on top, because
-p advertises access to all tools and headless AskQuestion has a reported approval-forgery bug.
Belt and braces.
The help text is Force allow commands unless explicitly denied, and --yolo is an alias for
Run Everything. It does not merely permit file edits — it permits every command that is not on a
deny list, and this wrapper ships no deny list.
Deploys, outbound messages and destructive operations are held back by the policy preamble (soft) and by you reading the diff. The CLI will not stop them. Earlier versions of this README said otherwise; that was wrong.
Without it, a directory Cursor has not seen before refuses even to be read
(Workspace Trust Required). The wrapper always passes it. It skips a prompt; it does not grant
privileges.
cursor-agent models lists them — 193 as of 2026-08-07 — named <base>-<effort>[-fast]. Claude,
GPT, Grok, Gemini, Kimi and GLM families are all present, and effort is baked into the name
(-low … -max) or set explicitly:
--model 'claude-opus-5[context=1m,effort=high,fast=false]'The -fast variants are not a reliable basis for choosing. Across 20 matched pairs the difference
oscillated within ±2s and the sign was inconsistent — measured under parallel load, so treat it as
noise rather than a ranking.
Avoid probing models speculatively. Some are metered or paid, and sweeping the whole catalogue to see what answers is an expensive way to learn very little.
| Capability | Available | Notes |
|---|---|---|
| Image understanding (vision) | ✅ | put the file path in the prompt; that is all |
| Image generation | ✅ most models | GenerateImage yields 1536×1024 PNGs. Confirmed on grok-4.5, claude-opus-5, composer-2.5, gpt-5.6-sol, gpt-5.6-terra. Only gpt-5.3-codex came up empty |
| Audio / video / music | ❌ | no such models, no such flags |
None of this shows up in cursor-agent models, which lists text LLMs only. The catalogue is not a
capability spec.
When you ask for generation, say no SVG and no drawing shapes in code. Otherwise you get a rectangle rendered with PIL, described as an image.
Then check the filesystem. gpt-5.6-terra-high once reported "I generated the image:
assets/generated-illustration.png" having written nothing whatsoever. Adding one sentence —
"then run ls -la to confirm it exists and show the output; if it is missing, say so" — made the
same model produce a real 2.2 MB PNG. The first failure was a weak instruction, not a missing
capability, so ask for verification before concluding that anything is unsupported.
It may be a gate a human has to clear in a console. Two we hit:
ActionRequiredError: Review Data Policy— raised byclaude-fable-5-*, a NO-ZDR family. Accepting the data policy in the dashboard opened every tier at once.Workspace Trust Required— solved by--trust.
Likely relatives: MCP server approval (--approve-mcps), usage limits, plan-tier model restrictions.
The wording tells you which you are looking at. ActionRequired, must acknowledge / accept / approve, Review, Trust mean a gate — stop retrying, find out what needs approving where, and say
so. not supported or unknown model means a genuine capability gap.
- Headless
-phas intermittent hang reports (2026-02). On a long silence the wrapper surfaces the error instead of blocking forever. - Headless
AskQuestionhas been reported to fabricate approvals the user never gave. Read the diff for anything run underimplement. - Probing many models at once spawns processes quickly. Kill the parent —
xargs, or the driving script — or the children keep respawning. Note that macOSxargshas no-r. - macOS ships bash 3.2, where empty array expansion (
"${arr[@]}") is an unbound error underset -u. Do not assume bash 4.4+ syntax when editing the wrapper.
MIT — see LICENSE.