feat(agents): add native Cursor CLI support - #203
Merged
Conversation
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.
…s test Follow-ups on top of the Cursor CLI adapter, found by driving it end to end against a live signed-in cursor-agent rather than a mock binary. Resolve the binary as `cursor-agent` first and fall back to the generic `agent` name. Cursor's installer currently symlinks both, but `agent` alone is ambiguous with any unrelated tool of that name on PATH, and installs predating the alias expose only `cursor-agent`. Driving gnhf with a PATH carrying just `cursor-agent` failed with `spawn agent ENOENT`. Raise PermanentAgentError when the CLI reports it is signed out. That exit was retryable, so an expired session burned the whole consecutive-failure budget before the run gave up; it now aborts on the first iteration. Spawn the linger integration test's script through process.execPath. A bare `.mjs` path is not directly executable on Windows, which failed CI with `spawn EFTYPE`. The product path was never affected: real `.cmd` wrappers and full-path binaries are already handled. Use the shared parseAgentOutput helper instead of a private copy, per the guidance in AGENTS.md, and point the docs at the `cursor-agent` name.
Owner
Author
|
Merged and released in 0.1.44. Thanks for the Cursor CLI adapter. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Adopt the open community contribution #187 (a native Cursor CLI agent, --agent cursor) rather than reimplementing Cursor support ourselves, rebased onto current origin/main, and add the fixes found by validating it against a real signed-in cursor-agent.
Background: a scout validated PR 187 end to end against the live signed-in Cursor CLI (2026.08.11-e8db854) on this machine - the contributor had only demonstrated it with a mock binary. The adapter's wire-protocol handling proved correct against the real CLI (stdin prompt, assistant.message.content[].text, camelCase usage keys, result/success terminal event, real token counts), so the decision was to adopt it, not rewrite it.
Deliberate decisions in this change:
Deliberately NOT in scope, please do not flag these as omissions:
What Changed
--agent cursorwith stream-json parsing, structured output validation, token usage tracking, permission defaults, and graceful process shutdown.cursor-agentbinary with anagentfallback, and treat signed-out sessions as permanent failures.Risk Assessment
✅ Low: The Cursor adapter is well-bounded, preserves contributor history, satisfies the stated resolution and security requirements, and includes behavior-focused coverage for the introduced paths.
Testing
Built the CLI, passed the focused Cursor adapter, lifecycle, factory, configuration, and CLI E2E tests, then verified the end-user flow against the real signed-in Cursor CLI and confirmed signed-out authentication aborts after one invocation. Contributor authorship was also preserved, and generated build output was removed afterward.
Evidence: Live signed-in Cursor CLI end-to-end transcript
Evidence: Signed-out Cursor abort transcript
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 2 issues found → auto-fixed (3) ✅
src/core/agents/cursor.ts:26- The required fallback "tries 'cursor-agent' first and falls back to the generic 'agent'" fails on supported Unix environments without the non-standardwhichutility: both lookups throw, line 37 selectscursor-agent, and an installation exposing onlyagentthen fails with ENOENT. Resolve candidates directly from PATH at this boundary or retryagentwhen spawningcursor-agentfails with ENOENT.src/core/config.ts:195- Cursor supports--api-key, but its reserved-argument list permits both--api-key <secret>and--api-key=<secret>, placing credentials in process argv and persistent config. Reserve both forms and direct users toCURSOR_API_KEY, consistent with the existing Pi protection.🔧 Fix: Block Cursor API keys in agent arguments
1 error still open:
src/core/agents/cursor.ts:26- The required behavior that binary resolution "tries 'cursor-agent' first and falls back to the generic 'agent'" still depends on the non-standard Unixwhichutility. Ifwhichis unavailable, both lookups fail, line 37 selectscursor-agent, and an installation exposing onlyagentfails with ENOENT. Retryagentwhen spawningcursor-agentfails with ENOENT, or resolve candidates directly from PATH without an external utility.🔧 Fix: Resolve Cursor binaries directly from PATH
1 warning still open:
src/core/agents/cursor.ts:40- On Unix, PATH resolution treats any regularcursor-agentfile as runnable without checking execute permission. A non-executablecursor-agentin PATH therefore prevents fallback to an executable genericagent, and spawn fails with EACCES. Check executability withaccessSync(..., X_OK)at this resolution boundary and cover that sequence.🔧 Fix: Skip non-executable Cursor binaries during PATH resolution
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
git log --format='%H%x09%an%x09%s' --reverse 64329d1d65d382e34ed6f78caa9bf4bd5371e0dc..c51660d263251409d394ade70d606739e4ed1d1cverified Evan Ram's original commit remains separately authored.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.tscursor-agent statusandcursor-agent --versionconfirmed the live CLI was signed in and running version 2026.08.11-e8db854.Ran built gnhf against the real signed-incursor-agentwith no genericagenton the isolated PATH; it created and committed the requested file and reported real token usage.Ran built gnhf with--max-iterations 5against a signed-out Cursor fixture; the Cursor process was invoked exactly once before the run aborted.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.