feat(cli): add experimental cursor-sdk harness#64
Draft
josemontesdeoca wants to merge 4 commits into
Draft
Conversation
4a4e5d2 to
2f9a1d5
Compare
Wire Cursor as a third first-party SDK harness alongside codex-sdk and claude-sdk. The harness wraps @cursor/sdk@^1.0.12 in local mode (cwd plus settingSources: ["project", "user"]), forwards the canonical OpenProse prompt, streams assistant text to stdout, surfaces failed tool_call and status ERROR/EXPIRED events to stderr, and converges on the same 0/1/143 exit-code semantics as the existing SDK harnesses. Authentication uses CURSOR_API_KEY; CURSOR_MODEL overrides the local model id (default composer-2). Skill discovery is intentionally a no-op for cursor-sdk here; the "cursor" SkillAgent and skill-path wiring land in a separate change.
Give the cursor-sdk harness first-class participation in skill
discovery. Add "cursor" as a SkillAgent value, replace the prior
no-op so skillAgentsForHarness("cursor-sdk") now returns ["cursor"],
and refactor project skill resolution to walk every supported
subdirectory at every ancestor — cursor checks both .cursor/skills
and .agents/skills per ancestor, and walks ~/.cursor, ~/.agents,
~/.claude, and ~/.codex as user/provider-user scope.
The auto-installer requires no signature change: passing --agent
cursor to skills@1.5.3 already routes to the right install path. In
practice skills@1.5.3 installs to ~/.agents/skills/open-prose for
cursor (the cross-client interop path), which the new ordering picks
up natively — the harness sees the skill regardless of which path
the installer chose.
Tests cover the harness-to-agent mapping, .cursor/skills + .agents/skills
project discovery at every ancestor, all four user-scope candidates,
~/.codex as a provider-user candidate that's exclusive to cursor (not
claude-code), and the install command's --agent cursor flag.
…ness gap Tag cursor-sdk as an experimental harness. Cursor positions composer-2 as a coding-tuned model rather than a general-purpose instruction- follower; in practice the harness grounds correctly in OpenProse SKILL.md vocabulary but resists strict return-token compliance and runs plan-only on multi-stage execution programs. Read-and-explain programs (lint, inspector, status, diagnose) remain reliable. Surface the limitation in three places: - Runtime stderr warning in cursor-sdk.ts on every run, suppressible via PROSE_SUPPRESS_EXPERIMENTAL_WARNINGS=1. - README provider table tags the row "experimental"; Harness Details carries a Known-limits note plus a CURSOR_MODEL passthrough hint for stricter instruction-following. - POST_RELEASE_PLAYTEST scenarios scoped to read-and-explain programs. Deliberately do NOT add cursor-sdk to the smoke matrix or the CI workflow: composer-2 does not pass the smoke harness's instruction- compliance assertion, and a permanently-red CI signal would mask legitimate failures on codex-sdk and claude-sdk. The smoke script gains a comment block explaining the omission so future maintainers do not "fix" it. package.json description acknowledges experimental Cursor support.
The cursor-sdk README additions had four overlapping problems: the experimental framing was repeated across the table row, Harness Details bullet, Caveat paragraph, and a separate env-var paragraph; the CURSOR_MODEL=claude-4.6-sonnet-thinking hint conflated harness contract with model fitness and put speculative recommendations in shipped docs; the per-run stderr warning was noise any serious user would silence on second run; and the explicit exit-code / SIGINT contract was missing. Changes: - Collapse the cursor-sdk Harness Details bullet to a single paragraph plus a tight Known-limits note. Add an explicit statement that exit codes (0/1/143) and SIGINT/SIGTERM semantics match the other SDK harnesses, and that Cloud / PR automation / models.list are not exposed. - Trim the Provider Selection table Notes cell to one line. - Remove the redundant standalone Cursor env-var paragraph; the facts now live in one place. - Drop the CURSOR_MODEL=claude-4.6-sonnet-thinking name-drop and the model-passthrough probe scenario from POST_RELEASE_PLAYTEST. Speculative recommendations don't belong in user-facing docs. - Remove the runtime stderr warning in cursor-sdk.ts and the PROSE_SUPPRESS_EXPERIMENTAL_WARNINGS env var. The README and the experimental tag are sufficient signal; a per-run nag adds noise without changing behavior. Tests no longer need the suppression env entry.
2f9a1d5 to
17a60e5
Compare
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.
Adds
cursor-sdkas a third first-party SDK harness intools/cli, wrapping@cursor/sdkin local mode behind the existingHarnesscontract. Theharness ships explicitly as experimental: the default
composer-2modelis tuned for code edits and tool use rather than general instruction-following,
so multi-stage Prose programs may run plan-only. Production runs should still
prefer
codex-sdkorclaude-sdk.The change layers cleanly on the existing harness shape — no edits to
canonicalPrompt(),runForwardedProseCommand(), or the two existing SDKharnesses — and stays within the bounds of the public
Harnessinterface.What ships
New harness
tools/cli/src/harnesses/cursor-sdk.ts:await import("@cursor/sdk")with an injectable factory (mirrorsthe Codex pattern; tests never touch the real SDK).
CURSOR_API_KEYfor auth;CURSOR_MODELselects the local model(default
composer-2).local: { cwd, settingSources: ["project", "user"] }so Cursor auto-loads the OpenProse skill.
0/1/143) and SIGINT/SIGTERM semantics matchcodex-sdkandclaude-sdk— abort cancels the active run and disposesthe agent in
finally.Registry / typing (
tools/cli/src/harnesses/{types,index}.ts):"cursor-sdk"added toHarnessNameandHARNESS_NAMES.types.tssocursor-sdk.tsis theonly file importing from
@cursor/sdk.createHarness("cursor-sdk")andHarnessSelectionOptions.cursorSdkwired through the factory.
Skill discovery (
tools/cli/src/skills/open-prose.ts):"cursor"SkillAgentvalue.projectSkillDirectoryrefactored intoprojectSkillDirectoriesso anagent can advertise multiple project skill roots; Cursor checks
.cursor/skills/first and.agents/skills/second for cross-clientinterop.
~/.cursor/skills/,~/.agents/skills/,~/.claude/skills/, and~/.codex/skills/per Cursor's documentedfallback chain.
skillAgentsForHarness("cursor-sdk") → ["cursor"]; auto-installer runswith
--agent cursorvia the existingskills@1.5.3flow.Docs and metadata:
tools/cli/README.mdadds the provider table row, an example invocation,a single Harness Details paragraph with a tight Known-limits note, and
CURSOR_API_KEY/CURSOR_MODELreferences.tools/cli/POST_RELEASE_PLAYTEST.mdadds Cursor playtest scenarios(read-and-explain Prose programs, missing-key path).
tools/cli/package.jsonpins@cursor/sdk: ^1.0.12, refreshes thedescription, and adds the
cursorkeyword.Tests (
tools/cli/tests/{harnesses/harnesses,skills/open-prose}.test.ts):HARNESS_NAMES,resolveHarnessName, andcreateHarnesscoverage for
cursor-sdk.apiKey,model.id,local.cwd,settingSources),CURSOR_MODELoverride, missing-key throws before thefactory runs, assistant-text → stdout, tool-call/status error → stderr,
run.wait()error mapping, abort mid-stream returns143, dispose onstream throw.
skillAgentsForHarnessmapping,.cursor/skillsfirstdiscovery, four user-scope candidates, ancestor walk across both project
subdirs, install command targets
--agent cursor.