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

cursor-openai

v0.1.4

Published

Drop-in OpenAI-shaped client for Cursor models (LangChain / LangGraph optional). Pass apiKey + model.

Readme

cursor-openai (SDK)

Drop-in OpenAI-shaped client for Cursor models. Pass a Cursor API key + model id; call chat.completions.create (or use LangChain / LangGraph). In-process via @cursor/sdk — no Express gateway.

Requires Node.js >= 22.13.

flowchart LR
  App[App] -->|"chat.completions.create"| Client[cursor-openai]
  Client --> Models[Cursor models]

This is not a Cursor IDE coding agent. Built-in filesystem / shell / skills are disabled. Only tools you pass (tools[] / bindTools) are available.

Install

Published on npm as cursor-openai:

npm install cursor-openai @langchain/core

For LangGraph also install @langchain/langgraph. Keep a single @langchain/core 1.x copy (npm ls @langchain/core).

OpenAI-shaped client (primary)

import { createCursorClient } from "cursor-openai";

const client = createCursorClient({
  apiKey: process.env.CURSOR_API_KEY!,
  model: "composer-2.5-fast",
});

const res = await client.chat.completions.create({
  messages: [{ role: "user", content: "Hello" }],
});
console.log(res.choices[0]?.message.content);
client.dispose();

Stream:

for await (const chunk of client.chat.completions.stream({
  messages: [{ role: "user", content: "Hello" }],
})) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}

LangGraph / LangChain

import { CursorChatModel, CursorModels } from "cursor-openai";
import { HumanMessage } from "@langchain/core/messages";

const model = new CursorChatModel({
  apiKey: process.env.CURSOR_API_KEY!,
  model: CursorModels.composer25Fast,
  mode: "ask",
  outputType: "stream",
  sessionId: "user-thread-123",
});

const res = await model.invoke([new HumanMessage("Say hello in one sentence.")]);
console.log(res.content);
model.dispose();

Caller tools only:

const withTools = model.bindTools([
  {
    name: "get_weather",
    description: "Get weather for a city",
    schema: {
      type: "object",
      properties: { city: { type: "string" } },
      required: ["city"],
    },
  },
]);

| Option | Values | Effect | | --- | --- | --- | | mode | ask / agent / plan | Default ask (chat). tools[] / bindTools always bridge when present | | outputType | json / stream | Prefer .stream() for TTFT | | sessionId | string | Reuse underlying Cursor agent across turns (scoped per resolved model) |

Model resolution

composer-2.5 resolves to the non-fast variant even when the live Cursor catalog uses an inverted id/alias shape (id: composer-2.5-fast, alias composer-2.5). Use composer-2.5-fast explicitly for the fast variant.

Debug resolution against your catalog (no agent run):

import { Cursor } from "@cursor/sdk";
import { debugResolveModel } from "cursor-openai";

const models = await Cursor.models.list({ apiKey: process.env.CURSOR_API_KEY! });
console.log(debugResolveModel(models, "composer-2.5", "composer-2.5"));

Token usage

Non-stream responses always include OpenAI-shaped usage for this turn:

const res = await client.chat.completions.create({
  messages: [{ role: "user", content: "Hello" }],
  metadata: { session_id: "thread-1" },
});
console.log(res.usage); // { prompt_tokens, completion_tokens, total_tokens, ... }
console.log(res.cursor_session_usage); // cumulative for session_id
console.log(client.getChatUsage({ sessionId: "thread-1" }));

Stream: set stream_options: { include_usage: true } so the final chunk carries usage (and cursor_session_usage when a session is tracked).

Cutting tokens (without changing answer quality)

  • Prefer default ask mode (not agent) for plain chat — skips thinking unless you opt in.
  • Pass metadata.session_id on follow-ups so history is not replayed every turn.
  • Omit tools[] when unused — the client injects a short no-tools guardrail so the model does not burn a turn hunting IDE tools.
  • Built-in Cursor agent skills may still load in the runtime; hooks deny IDE tools regardless.

Examples

export CURSOR_API_KEY=...
npm run example:openai
npm run example:basic
npm run example:tools

Limits

  • Not for browsers / edge without Node
  • Tool-calling bridge needs runtime: "local" (default)
  • Embeddings not supported
  • No Express dependency
  • Not an IDE agent: no host repo access unless you implement it as a caller tool