Skip to content

feat(agents): add Cursor CLI agent support - #187

Open
ioqr wants to merge 1 commit into
kunchenguid:mainfrom
ioqr:cursor
Open

feat(agents): add Cursor CLI agent support#187
ioqr wants to merge 1 commit into
kunchenguid:mainfrom
ioqr:cursor

Conversation

@ioqr

@ioqr ioqr commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Add --agent cursor integration that invokes Cursor's agent CLI in non-interactive --print stream-json mode, with schema-in-prompt recovery, default --force/--trust/--approve-mcps (unless overridden), reserved-arg rejection, and post-success lingering process shutdown.
  • Wire cursor through agent factory, config/bootstrap overrides, CLI agent lists, and docs (README Agents table, AGENTS.md, skill process scan, bug report template).
  • Cover the path with unit, linger-integration, factory/config, and e2e tests plus mock Cursor agent fixtures.

Risk Assessment

✅ Low: Well-bounded Cursor agent integration that mirrors existing Claude/Pi spawn, schema-prompt, and linger-shutdown patterns, with parsing aligned to Cursor's last-assistant vs concatenated-result semantics and broad unit/e2e coverage.

Testing

Built the CLI, ran the Cursor-focused unit/integration/e2e suite (all passed), then manually drove a one-iteration --agent cursor run through the mock Cursor binary; help text lists cursor, spawn used -p --output-format stream-json --force --trust --approve-mcps with schema/objective on stdin, committed hello.txt, and the exit summary reported cursor ran / max iterations reached.

Evidence: CLI help and unknown-agent error listing cursor

--agent <agent> ... copilot, pi, cursor, or acp:<target-or-command> Unknown agent: not-a-real-agent. Use "claude", "codex", "rovodev", "opencode", "copilot", "pi", or "cursor", or "acp:<target-or-command>"

=== gnhf --help (agent flag) ===
3:Before I go to bed, I tell my agents: good night, have fun
6:  prompt                   The objective for the coding agent
10:  --agent <agent>          Agent to use (claude, codex, rovodev, opencode,
11:                           copilot, pi, cursor, or acp:<target-or-command>)
14:  --stop-when <condition>  End when the agent reports this condition, after any
19:                           agents on the same repo) (default: false)

=== gnhf --agent bad ===
Unknown agent: not-a-real-agent. Use "claude", "codex", "rovodev", "opencode", "copilot", "pi", or "cursor", or "acp:<target-or-command>" (e.g. acp:gemini).
Evidence: End-user gnhf --agent cursor CLI transcript (TUI + exit summary + workspace)
=== Manual end-user: gnhf --agent cursor (mock agent binary) ===
cwd: /var/folders/qs/67xry7bx4ks0jc6wkgq0tb0w0000gq/T/tmp.bacmDvqyYA
config agentPathOverride.cursor -> mock-cursor-agent

$ gnhf "add a hello.txt via cursor agent" --agent cursor --max-iterations 1 --current-branch --prevent-sleep off

�[?1049h�[?25l�[H                                                                            �[1m⋆·�[0m 
                            �[2mg n h f�[0m  �[2m·�[0m  �[2mc u r s o r�[0m                     �[2m·�[0m      
                                                                               
                                                                               
            �[1m┏━╸┏━┓┏━┓╺┳┓   ┏┓╻╻┏━╸╻ ╻╺┳╸   ╻ ╻┏━┓╻ ╻┏━╸   ┏━╸╻ ╻┏┓╻�[0m       �[1m°�[0m    
            �[1m┃╺┓┃ ┃┃ ┃ ┃┃   ┃┗┫┃┃╺┓┣━┫ ┃    ┣━┫┣━┫┃┏┛┣╸    ┣╸ ┃ ┃┃┗┫�[0m    �[2m⋆�[0m       
            �[1m┗━┛┗━┛┗━┛╺┻┛   ╹ ╹╹┗━┛╹ ╹ ╹    ╹ ╹╹ ╹┗┛ ┗━╸   ╹  ┗━┛╹ ╹�[0m            
                                                                               
                       �[2madd a hello.txt via cursor agent�[0m                        
                                                                               
                                                                              �[1m⋆�[0m
                                                                               
                                                                               
                   �[1m00:00:00�[0m  �[2m·�[0m  0 in  �[2m·�[0m  0 out  �[2m·�[0m  0 commits                   
      �[2m·�[0m                                                                        
                                                                               
                                  �[2mworking...�[0m                                   
  �[1m·�[0m                                                                            
                                                                          �[1m°�[0m    
                                                                         �[1m°�[0m     
                                                                               
                                      🌓                                       
                     �[2m[ctrl+c to stop, gnhf again to resume]�[0m                     
                                                                                �[?25h�[?1049l
╭────────────────────────────────────────────────────────────╮
│ × gnhf stopped                                             │
│   cursor ran for 0s before: max iterations reached (1)     │
╰────────────────────────────────────────────────────────────╯

  iterations      1 total       1 good       0 failed
  tokens          12 in         8 out        
  branch diff     1 commit      +1           -0
  files           1 added       0 updated    0 deleted

  notes           /private/var/folders/qs/67xry7bx4ks0jc6wkgq0tb0w0000gq/T/tmp.bacmDvqyYA/.gnhf/runs/add-a-hello-txt-via-c095ba/notes.md
  debug log       /private/var/folders/qs/67xry7bx4ks0jc6wkgq0tb0w0000gq/T/tmp.bacmDvqyYA/.gnhf/runs/add-a-hello-txt-via-c095ba/gnhf.log

  next steps      git log --oneline ac306af6d89b..HEAD
                  git diff --stat ac306af6d89b..HEAD
                  gh pr create

  too much        git push no-mistakes:
  to review?      https://github.com/kunchenguid/no-mistakes

=== Exit code: 0 ===

=== Working tree after run ===
total 16
drwx------@   6 ab  staff   192 Aug  4 02:36 .
drwx------@ 230 ab  staff  7360 Aug  4 02:36 ..
drwxr-xr-x@  12 ab  staff   384 Aug  4 02:36 .git
drwxr-xr-x@   3 ab  staff    96 Aug  4 02:36 .gnhf
-rw-r--r--@   1 ab  staff    10 Aug  4 02:36 README.md
-rw-r--r--@   1 ab  staff    23 Aug  4 02:36 hello.txt

--- hello.txt ---
hello from cursor mock

--- git log ---
231c59d gnhf 1: cursor mock wrote hello.txt
ac306af init

--- mock cursor spawn event ---
{"timestamp":"2026-08-04T08:36:26.123Z","pid":96293,"event":"spawn","argv":["-p","--output-format","stream-json","--force","--trust","--approve-mcps"],"cwd":"/private/var/folders/qs/67xry7bx4ks0jc6wkgq0tb0w0000gq/T/tmp.bacmDvqyYA","hasSchemaContract":true,"stdinHasObjective":true,"stdinLen":2904}
{"timestamp":"2026-08-04T08:36:26.126Z","pid":96293,"event":"done","wrote":"hello.txt"}

--- gnhf.debug log (selected) ---
log: .gnhf/runs/add-a-hello-txt-via-c095ba/gnhf.log
{"timestamp":"2026-08-04T08:36:26.057Z","pid":96238,"event":"agent:run:start","iteration":1,"agent":"cursor","logPath":"/private/var/folders/qs/67xry7bx4ks0jc6wkgq0tb0w0000gq/T/tmp.bacmDvqyYA/.gnhf/runs/add-a-hello-txt-via-c095ba/iteration-1.jsonl"}
{"timestamp":"2026-08-04T08:36:26.132Z","pid":96238,"event":"agent:run:end","iteration":1,"elapsedMs":75,"success":true,"inputTokens":12,"outputTokens":8,"cacheReadTokens":0,"cacheCreationTokens":0,"estimated":false}
{"timestamp":"2026-08-04T08:36:26.241Z","pid":96238,"event":"run:complete","signal":null,"status":"aborted","iterations":1,"successCount":1,"failCount":0,"totalInputTokens":12,"totalOutputTokens":8,"commitCount":1,"worktreePath":null}
Evidence: Readable exit summary proving cursor iteration succeeded

× gnhf stopped cursor ran for 0s before: max iterations reached (1) iterations 1 total / 1 good / 0 failed branch diff 1 commit +1 hello.txt -> hello from cursor mock commit: gnhf 1: cursor mock wrote hello.txt spawn argv: -p --output-format stream-json --force --trust --approve-mcps

$ gnhf "add a hello.txt via cursor agent" --agent cursor --max-iterations 1 --current-branch --prevent-sleep off

╭────────────────────────────────────────────────────────────╮
│ × gnhf stopped                                             │
│   cursor ran for 0s before: max iterations reached (1)     │
╰────────────────────────────────────────────────────────────╯

  iterations      1 total       1 good       0 failed
  tokens          12 in         8 out
  branch diff     1 commit      +1           -0
  files           1 added       0 updated    0 deleted

Working tree after run:
  hello.txt -> "hello from cursor mock"
  git log:
    231c59d gnhf 1: cursor mock wrote hello.txt
    ac306af init

Mock Cursor spawn argv:
  ["-p", "--output-format", "stream-json", "--force", "--trust", "--approve-mcps"]
  hasSchemaContract: true
  stdinHasObjective: true
Evidence: Mock Cursor spawn/done JSONL (defaults + schema contract)

{"event":"spawn","argv":["-p","--output-format","stream-json","--force","--trust","--approve-mcps"],"hasSchemaContract":true,"stdinHasObjective":true} {"event":"done","wrote":"hello.txt"}

{"timestamp":"2026-08-04T08:36:26.123Z","pid":96293,"event":"spawn","argv":["-p","--output-format","stream-json","--force","--trust","--approve-mcps"],"cwd":"/private/var/folders/qs/67xry7bx4ks0jc6wkgq0tb0w0000gq/T/tmp.bacmDvqyYA","hasSchemaContract":true,"stdinHasObjective":true,"stdinLen":2904}
{"timestamp":"2026-08-04T08:36:26.126Z","pid":96293,"event":"done","wrote":"hello.txt"}
Evidence: Committed hello.txt content from mock cursor agent

hello from cursor mock

hello from cursor mock
Evidence: Intent demonstration summary
user_intent: Wire --agent cursor to Cursor agent binary with stream-json, schema prompt, force/trust/approve-mcps defaults

demonstration:
- CLI accepted --agent cursor
- Spawning mock agent with expected argv
- Iteration committed hello.txt
- Exit summary reported cursor ran / max iterations reached

spawn_argv:
{
  "timestamp": "2026-08-04T08:36:26.123Z",
  "pid": 96293,
  "event": "spawn",
  "argv": [
    "-p",
    "--output-format",
    "stream-json",
    "--force",
    "--trust",
    "--approve-mcps"
  ],
  "cwd": "/private/var/folders/qs/67xry7bx4ks0jc6wkgq0tb0w0000gq/T/tmp.bacmDvqyYA",
  "hasSchemaContract": true,
  "stdinHasObjective": true,
  "stdinLen": 2904
}

hello.txt:
hello from cursor mock

git_log:
231c59d gnhf 1: cursor mock wrote hello.txt
ac306af init

Pipeline

Updates from git push no-mistakes

⏭️ **intent** - skipped

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • pnpm run build
  • pnpm exec vitest run src/core/agents/cursor.test.ts src/core/agents/cursor.linger.integration.test.ts src/core/agents/factory.test.ts src/core/config.test.ts e2e/e2e-cursor.test.ts
  • node dist/cli.mjs --help (confirms cursor in --agent list)
  • node dist/cli.mjs --agent not-a-real-agent &#34;x&#34; (error lists cursor)
  • Manual: node dist/cli.mjs &#34;add a hello.txt via cursor agent&#34; --agent cursor --max-iterations 1 --current-branch --prevent-sleep off with agentPathOverride.cursor pointing at e2e/fixtures/mock-cursor-agent
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@ioqr
ioqr force-pushed the cursor branch 3 times, most recently from df68827 to 3ff29ad Compare August 4, 2026 08:31
Wire `--agent cursor` to the Cursor `agent` binary with stream-json output, schema prompt recovery, force/trust/approve-mcps defaults, and post-success process shutdown for non-interactive runs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant