npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@stablekernel/opencode-cursor

v0.4.4

Published

opencode provider plugin backed by the official Cursor SDK (@cursor/sdk) — adds a Cursor provider and lists its models

Readme

@stablekernel/opencode-cursor

npm version CI License: MIT

An opencode plugin that adds Cursor as a native provider. Your Cursor models appear in the model picker; you chat with them the same way you use any other provider.

It uses the official Cursor SDK (@cursor/sdk) to list your account's models live and run chats through Cursor's local agent runtime. For delegated or background workflows it also ships two permission-gated tools (cursor_delegate, cursor_cloud_agent) — see Delegation tools.

⚠️ Security. When you chat with a cursor/* model, Cursor runs its own tools — including shell, write, edit, and delete — directly in your working directory, outside opencode's permission system. Read Security before you use it.

Requirements

  • opencode 1.17+
  • Node.js 22+ on your PATH — opencode runs on Bun; the plugin needs a Node sidecar to host the Cursor SDK (see Runtime).
  • A Cursor account and API key (from the Cursor dashboard).

Install

One line

curl -fsSL https://raw.githubusercontent.com/stablekernel/opencode-cursor/main/install.sh | bash

Registers the plugin in your global opencode.json (~/.config/opencode/opencode.json), checks for Node.js 22+, and offers to set CURSOR_API_KEY. Flags:

  • --project — write ./opencode.json in the current directory instead.
  • --yes / -y — non-interactive.

Review the script first.

Manual

npm install @stablekernel/opencode-cursor

Add to your opencode.json (or opencode.jsonc — both are supported):

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["@stablekernel/opencode-cursor@latest"]
}

The @latest suffix makes opencode re-resolve to the newest release on each startup. Drop it ("@stablekernel/opencode-cursor") or pin a version ("@stablekernel/[email protected]") if you prefer.

The plugin injects the provider block automatically. If you need explicit control:

{
  "provider": {
    "cursor": {
      "npm": "@stablekernel/opencode-cursor",
      "name": "Cursor",
      "options": { "apiKey": "{env:CURSOR_API_KEY}" }
    }
  }
}

Authenticate

opencode auth login   # choose "Cursor", paste your key from the Cursor dashboard

Or set the environment variable:

export CURSOR_API_KEY="key_..."

The key is validated on first use (model discovery / first call), not at login time.

Use

  • opencode models (or the model picker) lists your Cursor models as cursor/<id>.
  • Pick a model and chat — the Cursor local agent runs in your project directory.
  • Run the cursor_refresh_models tool to force a live catalog refresh.

The plugin also registers two delegation tools:

  • cursor_delegate — hand a discrete subtask to a local Cursor agent as a permission-gated tool call (your primary model stays in control).
  • cursor_cloud_agent — launch a Cursor cloud agent on a remote repo that can run for minutes and optionally open a PR.

Security

⚠️ The provider path is unsandboxed and not gated by opencode permissions. When you chat with a cursor/* model, Cursor runs its own tools — including shell, write, edit, and delete — directly in your working directory. opencode's permission rules (e.g. edit: deny, bash: ask) do not apply to them.

Options if you need a permission boundary:

  • Set sandbox: true in provider.cursor.options to run Cursor's tools in Cursor's sandbox.
  • Use cursor_delegate instead of the provider path — it is gated by opencode's permission config.

See SECURITY.md for the full threat model.

Configuration

| Option (provider.cursor.options) | Default | Meaning | | --- | --- | --- | | apiKey | CURSOR_API_KEY | Cursor API key | | cwd | process.cwd() | Directory the local agent operates in | | mode | "agent" | Default conversation mode ("agent" or "plan") | | params | — | Default model params, e.g. { thinking: "high" } | | settingSources | — | Cursor settings layers to load: ["project","user","all",...] — pulls in your Cursor skills, rules, and .cursor/mcp.json | | sandbox | — | Run the agent's tools in Cursor's sandbox | | agents | — | Cursor subagent definitions | | session | "auto" | Session reuse strategy — see Session reuse | | forwardMcp | true | Forward opencode's configured MCP servers to the Cursor agent | | mcpServers | — | Extra MCP servers (Cursor McpServerConfig shape); merged with forwarded ones | | toolDisplay | "blocks" | How Cursor's internal tool activity is shown — see Tool display |

| Environment variable | Default | Meaning | | --- | --- | --- | | CURSOR_API_KEY | — | API key fallback | | OPENCODE_CURSOR_MODEL_CACHE_TTL_MS | 86400000 | Model-list cache lifetime (ms) | | OPENCODE_CURSOR_DEBUG | — | Set to 1 for trace logging on stderr | | OPENCODE_CURSOR_SIDECAR | — | 1 = always use Node sidecar; 0 = never |

Session reuse (session)

opencode re-sends the full conversation transcript on every turn. session: "auto" (the default) fingerprints the conversation and resumes the same Cursor agent when nothing has changed, so you only pay for the new message. It falls back to a fresh agent + full transcript on edits, reverts, or compaction.

| Situation | What happens | | --- | --- | | First turn | Fresh agent, full transcript, pool it | | System prompt differs (title gen, other side calls) | Ephemeral fresh agent; pooled agent untouched | | Clean continuation (one new user message) | Agent.resume — sends only the new message | | Forwarded MCP server set changed | Fresh agent + full transcript, re-pooled | | Message edited/reverted or conversation compacted | Fresh agent + full transcript, re-pooled |

session: true is an alias for "auto". session: false disables reuse (always fresh agent, full transcript every turn).

Fingerprint records persist to ~/.cache/opencode-cursor/session-pool.json, so session reuse survives opencode restarts.

Per-request controls (mode, thinking level)

The plugin auto-generates model variants for each reasoning/effort level a model advertises, plus a fast toggle for models that expose Cursor's fast tier. Selecting a variant in the model picker sends its settings through providerOptions.cursor.

fast defaults off (even though Cursor's own default is fast: true for some models, e.g. Composer and the codex line) so opencode never silently runs the fast tier — pick the fast variant to opt in, or set it per model under options.params.fast below.

opencode's plan agent (Tab) maps to Cursor's plan mode automatically — no manual config needed.

To set controls statically per model:

{ "provider": { "cursor": { "models": {
  "composer-2.5": { "options": { "params": { "thinking": "high" } } }
} } } }

MCP servers

With forwardMcp: true (default), the Cursor agent uses the same MCP servers configured in opencode. The server list is updated live per turn, so enabling or disabling an MCP server takes effect on the next message.

| opencode config.mcp | → Cursor | | --- | --- | | { type: "local", command: [cmd, ...args], environment } | { type: "stdio", command, args, env } | | { type: "remote", url, headers } | { type: "http", url, headers } | | Remote with registered OAuth clientId | { type: "http", url, auth: { CLIENT_ID, … } } |

Disabled entries (enabled: false) are skipped. Remote servers requiring OAuth without a shareable clientId are also skipped (a one-time toast says which). Disable forwarding with forwardMcp: false.

Note: This forwards MCP servers. opencode's own skills and subagents are not exposed to the Cursor agent. To load your local Cursor skills/rules, use settingSources: ["project","user"].

Delegation tools

Both tools resolve the API key from your opencode auth login session (or CURSOR_API_KEY) and are gated by opencode's permission config:

{ "permission": { "cursor_delegate": "ask", "cursor_cloud_agent": "ask" } }

cursor_delegate (local)

Runs one Cursor turn as a permission-gated tool call. Your primary opencode model hands off a discrete subtask and gets the result back.

| Arg | Required | Meaning | | --- | --- | --- | | prompt | ✅ | The subtask to delegate | | model | ✅ | Cursor model id | | mode | — | "agent" or "plan" | | thinking | — | Thinking level (e.g. "high") | | cwd | — | Working directory | | sandbox | — | Run in Cursor's sandbox | | agentId | — | Resume a specific Cursor agent |

cursor_cloud_agent (cloud)

Launches a background Cursor cloud agent on a remote repo. Can run for minutes and optionally open a PR.

| Arg | Required | Meaning | | --- | --- | --- | | prompt | ✅ | The task | | repoUrl | ✅ | Target repository URL (e.g. https://github.com/owner/repo) | | startingRef | — | Branch/ref to start from | | model | — | Cursor model id | | mode | — | "agent" or "plan" | | thinking | — | Thinking level | | autoCreatePR | — | Open a PR when finished | | workOnCurrentBranch | — | Operate on the current branch instead of a new one |

Tool display

toolDisplay controls how Cursor's internal tool activity appears in opencode:

  • "blocks" (default) — structured, collapsible tool blocks with inputs and outputs. Common Cursor tools are mapped to their opencode equivalents (edit → diff viewer, shell → bash console, etc.). Requires opencode 1.17+.
  • "reasoning" — compact inline lines ([tool] write {"path":…}). Works on any host; use this on older opencode versions.

To force the fallback:

{ "provider": { "cursor": { "options": { "toolDisplay": "reasoning" } } } }

Runtime: Bun and the Node sidecar

opencode runs on Bun, which has an node:http2 incompatibility with the Cursor SDK's streaming RPC. The plugin transparently hosts the Cursor SDK in a short-lived Node child process when running under Bun. Under Node it runs in-process.

This is why Node.js 22+ on your PATH is required. If Node isn't found, the plugin warns once and falls back to in-process (native Cursor tools will misbehave until Node is available).

Override with OPENCODE_CURSOR_SIDECAR=1 (always sidecar) or OPENCODE_CURSOR_SIDECAR=0 (never).

Troubleshooting

  • Native Cursor tools hang / "Tool execution aborted" (NGHTTP2_FRAME_SIZE_ERROR). Node isn't on your PATH. Install Node.js 22+, or force the sidecar with OPENCODE_CURSOR_SIDECAR=1.
  • "Running under Bun without a usable Node sidecar" warning. Install Node.js 22+, or set OPENCODE_CURSOR_SIDECAR=0 to accept in-process behavior and silence the warning.
  • Plugin enabled but no cursor provider/models appear. Stale opencode plugin cache. Pin an exact version (@stablekernel/opencode-cursor@<version>) or delete ~/.cache/opencode/packages/ and restart.
  • Only the four fallback models appear. The live catalog loads after the first authenticated use. Restart opencode once after login, or run cursor_refresh_models.
  • Invalid or expired key. Validated on first use — that's where the error surfaces.
  • Need more detail? Set OPENCODE_CURSOR_DEBUG=1.

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md for dev setup, test/typecheck/build commands, and the release process. Report bugs at the issue tracker; for security reports see SECURITY.md.

License

MIT