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

opencode-cursor-oauth-plus

v0.1.5

Published

OpenCode plugin that connects Cursor's API to OpenCode via OAuth, model discovery, and a local OpenAI-compatible proxy.

Downloads

781

Readme

opencode-cursor-oauth-plus

OpenCode plugin that connects to Cursor's API, giving you access to Cursor models inside OpenCode with full tool-calling support.

Requirements

  • OpenCode >= 1.18
  • Bun >= 1.3 — required by OpenCode's plugin runtime (not just development)
  • Node.js >= 18 for the HTTP/2 bridge process
  • Active Cursor subscription

Installing Bun

This plugin uses Bun APIs (Bun.serve, Bun.spawn, Bun.sleep) and OpenCode runs plugins via its bundled Bun runtime. Bun must be installed on the system and available on PATH before starting OpenCode:

curl -fsSL https://bun.sh/install | bash
# Restart your shell or exec $SHELL, then verify:
bun --version

If OpenCode is started before Bun is installed, the daemon won't find it. Kill any running opencode processes and restart after installing Bun.

Install in OpenCode

Add this to ~/.config/opencode/opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": [
    "opencode-cursor-oauth-plus"
  ],
  "provider": {
    "cursor": {
      "name": "Cursor",
      "models": {
        "composer-2.5": {
          "name": "Composer 2.5",
          "reasoning": true,
          "limit": { "context": 200000, "output": 64000 },
          "modalities": { "input": ["text", "image"], "output": ["text"] },
          "variants": {
            "low": { "effort": "low" },
            "medium": { "effort": "medium" },
            "high": { "effort": "high" },
            "max": { "effort": "max" },
            "xhigh": { "effort": "xhigh" }
          }
        }
      }
    }
  }
}

The cursor provider stub is required because OpenCode drops providers that do not already exist in its bundled provider catalog.

The model list above is an example, not a default. Cursor exposes a different set of models per plan. Generate your own with cursor-models below — do not copy this block verbatim.

Static model definitions

OpenCode v1.18.x does not call the provider.models hook for non-built-in providers. Models must be defined statically in the config. The plugin's auth.loader handles dynamic connection details (proxy port, token refresh) at inference time, so the models above work without specifying npm or options.

This is the single most common source of breakage: an id in the models block that your account cannot use is rejected by Cursor with an opaque error such as Connect error internal: Error, not_found, or resource_exhausted. Since 0.1.1 the proxy rejects unknown ids up front with the list of ids your account does have, instead of forwarding them and surfacing the opaque failure.

Listing the models your plan has

Do not hand-write the models block. Generate it:

# Prints a ready-to-paste provider block for YOUR account
npx opencode-cursor-oauth-plus cursor-models

# Or, if the package is already installed by OpenCode:
bun ~/.cache/opencode/packages/opencode-cursor-oauth-plus@latest/node_modules/opencode-cursor-oauth-plus/dist/cli-models.js

Merge the printed provider block into ~/.config/opencode/opencode.json, then restart OpenCode. Verify with:

opencode models | grep '^cursor/'

Every id it prints came back from Cursor for your plan, so ids that do not exist cannot creep in. Run it again whenever you change plans or Cursor ships a new model — new models will not appear until you add them to the config.

Raw discovery output, without the config scaffolding:

npx opencode-cursor-oauth-plus cursor-models --json

Fields the generator cannot infer

| Field | Why | What to do | |---|---|---| | reasoning | Cursor derives it from thinkingDetails, which it leaves unset even for models that do reason. The generator therefore emits true for everything. | Set false for any model that never streams thinking output. | | modalities | Discovery does not report input modalities. The generator emits ["text","image"] because live probes show both models accept images via Cursor's selectedImages path. | Drop "image" only if a model rejects vision; add "pdf" if needed. | | variants | Effort levels are a Cursor UI feature, not part of discovery. Applied by family: effort for composer*, reasoningEffort for grok*. | Add or remove per model. Extra variants on a model that ignores them are harmless. |

limit.context, limit.output, name and the model id all come straight from Cursor and need no editing.

Troubleshooting

| Symptom | Cause | |---|---| | Cursor missing from the model picker entirely | No provider.cursor.models block, or opencode.json is invalid JSON. Check with opencode debug config. | | Connect error not_found / internal | The model id is not one your plan has. Re-run cursor-models. | | Connect error resource_exhausted | Plan quota for that model is exhausted, or you are being rate limited. | | Connect error unauthenticated | Token rejected — re-run opencode auth login --provider cursor. | | Request hangs, then reports no output | Cursor accepted the stream but never produced output. The proxy aborts after CURSOR_NO_OUTPUT_TIMEOUT_MS (default 90s). |

OpenCode installs npm plugins automatically at startup, so users do not need to clone this repository.

Authenticate

opencode auth login --provider cursor

This opens Cursor OAuth in the browser. Tokens are stored in ~/.local/share/opencode/auth.json and refreshed automatically.

Use

Start OpenCode and select any Cursor model. The plugin starts a local OpenAI-compatible proxy on demand and routes requests through Cursor's gRPC API.

How it works

  1. Bun runtime — OpenCode loads plugins via its bundled Bun runtime. The plugin must have bun on system PATH before the daemon starts.
  2. OAuth — browser-based login to Cursor via PKCE.
  3. Model discovery — queries Cursor's gRPC API for all available models (runs during auth.login but results must be added to config statically).
  4. Local proxy — at inference time, auth.loader starts a local Bun.serve proxy that translates POST /v1/chat/completions into Cursor's protobuf/HTTP/2 Connect protocol.
  5. Native tool routing — rejects Cursor's built-in filesystem/shell tools and exposes OpenCode's tool surface via Cursor MCP instead.

HTTP/2 transport runs through a Node child process (h2-bridge.mjs) because Bun's node:http2 support is not reliable against Cursor's API.

Architecture

OpenCode  -->  /v1/chat/completions  -->  Bun.serve (proxy)
                                              |
                                    Node child process (h2-bridge.mjs)
                                              |
                                     HTTP/2 Connect stream
                                              |
                                    api2.cursor.sh gRPC
                                      /agent.v1.AgentService/Run

Tool call flow

1. Cursor model receives OpenAI tools via RequestContext (as MCP tool defs)
2. Model tries native tools (readArgs, shellArgs, etc.)
3. Proxy rejects each with typed error (ReadRejected, ShellRejected, etc.)
4. Model falls back to MCP tool -> mcpArgs exec message
5. Proxy emits OpenAI tool_calls SSE chunk, pauses H2 stream
6. OpenCode executes tool, sends result in follow-up request
7. Proxy resumes H2 stream with mcpResult, streams continuation

Develop locally

bun install
bun run build
bun test/smoke.ts