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/february

v1.0.7

Published

Cursor SDK (private alpha).

Readme

@cursor/february

TypeScript SDK for Cursor agents (private alpha — codenamed).

The primary API is the static Agent namespace. It creates durable agents, starts runs, streams normalized run events, waits for completion, resumes existing agents, and inspects persisted agent state.

Quick Start

import { Agent } from "@cursor/february/agent";

const agent = Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  local: { cwd: process.cwd() },
});

try {
  const run = await agent.send("Refactor the utils module", {
    onDelta: ({ update }) => {
      console.log("raw update", update.type);
    },
    onStep: ({ step }) => {
      console.log("completed step", step.type);
    },
  });

  for await (const event of run.stream()) {
    if (event.type === "assistant") {
      for (const block of event.message.content) {
        if (block.type === "text") {
          process.stdout.write(block.text);
        }
      }
    }
  }

  const result = await run.wait();
  console.log(result.status);
} finally {
  await agent[Symbol.asyncDispose]();
}

Creating Agents

Agent.create(options) returns an SDKAgent immediately. Runtime initialization is deferred until the first send. agent.agentId is populated immediately for both local and cloud agents: local uses an agent-<uuid> ID, cloud uses a bc-<uuid> ID the SDK generates and reserves with the server on first send.

const localAgent = Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  local: { cwd: "/path/to/repo" },
});

const cloudAgent = Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  cloud: {
    repos: [
      {
        url: "https://github.com/owner/repo",
        startingRef: "main",
      },
    ],
  },
});

Agent Options

  • model: Model selection for runs. Required for local agents. Optional for cloud — omit to use the server-resolved default. Structure is { id, params? }; see Cursor.models.list() for valid selections.
  • apiKey: Cursor API key. Required for cloud agents and real local execution.
  • local.cwd: Working directory for local agents. May be a string or string array.
  • local.settingSources: Ambient Cursor settings layers to load from the local filesystem. Local agents only.
  • cloud.repos: GitHub repository configuration for cloud agents.
  • agentId: Optional durable agent ID. If omitted, the SDK generates one.
  • mcpServers: Inline MCP server definitions available to local runs.
  • platform: Advanced local persistence/workspace configuration.

Sending Messages

Use agent.send(message, options) to create a follow-up run.

const run = await agent.send(
  {
    text: "Explain this repository",
    images: [
      {
        data: base64Png,
        mimeType: "image/png",
      },
    ],
  },
  {
    model: { id: "composer-2" },
    local: { force: false },
  }
);

Send Options

  • model: Per-run model override for local agents. Cloud follow-up model overrides are unsupported in v1.
  • local.force: Local agents only. Expire an active persisted run before starting this message. Use this as an explicit recovery path after a crashed local process. Cloud enforces a busy-run check server-side, so no equivalent is needed.
  • onDelta: Callback for raw InteractionUpdate deltas as the executor emits them.
  • onStep: Callback when a conversation step finishes after batching text, thinking, or tool updates.

onDelta and onStep are awaited before the update continues through the run pipeline, so callback backpressure is preserved.

Runs

A Run represents one durable agent turn.

const run = await agent.send("Update the README");

console.log(run.id);
console.log(run.agentId);
console.log(run.status);

const result = await run.wait();

Run Operations

  • run.stream(): Async generator of normalized SDKMessage events.
  • run.wait(): Resolves to a terminal RunResult.
  • run.cancel(): Cancels a supported running run.
  • run.conversation(): Returns accumulated ConversationTurn[] for this run.
  • run.supports(operation): Checks whether stream, wait, cancel, or conversation is supported.
  • run.unsupportedReason(operation): Explains why an operation is unavailable.
  • run.onDidChangeStatus(listener): Subscribes to run status changes.

run.cancel() is supported for both local and cloud runs. For cloud runs it calls the server's cancel endpoint and reconciles local status from the authoritative server response.

Streaming Events

run.stream() emits SDKMessage events. This is the stable public stream surface shared by local and cloud runs.

for await (const event of run.stream()) {
  switch (event.type) {
    case "user":
      console.log(event.message.content.map(block => block.text).join(""));
      break;
    case "assistant":
      for (const block of event.message.content) {
        if (block.type === "text") {
          process.stdout.write(block.text);
        }
      }
      break;
    case "thinking":
      process.stdout.write(event.text);
      break;
    case "tool_call":
      console.log(event.call_id, event.name, event.status);
      if (event.args) {
        console.log("args", event.args);
      }
      if (event.result) {
        console.log("result", event.result);
      }
      break;
    case "status":
      console.log(event.status);
      break;
    case "task":
      console.log(event.text);
      break;
  }
}

SDKMessage Types

  • SDKUserMessageEvent: User prompt content for the run.
  • SDKAssistantMessage: Assistant text and tool-use content blocks.
  • SDKThinkingMessage: Thinking text.
  • SDKToolUseMessage: Tool call metadata with call_id, name, status, and optional args, result, and truncated payload fields.
  • SDKStatusMessage: Run lifecycle status such as RUNNING, FINISHED, or ERROR.
  • SDKTaskMessage: Task-level status or summary text.
  • SDKSystemMessage: System/init metadata when available.

Tool payload fields are emitted when the runtime provides them. Cloud V1 stream payloads use the public stream shape from the API; local runs forward the normalized local tool call arguments and results from InteractionUpdate.toolCall.

Conversation State

run.conversation() returns old-style accumulated ConversationTurn[] for the run.

const run = await agent.send("Inspect package scripts");
await run.wait();

const turns = await run.conversation();

Live local runs can accumulate tool steps from raw executor deltas. Persisted replay reconstructs conversation from SDKMessage events, so replayed conversations can include tool-call steps when the persisted stream contains tool payload data.

Raw Delta Callbacks

onDelta exposes the lower-level InteractionUpdate stream.

const run = await agent.send("Run tests", {
  onDelta: ({ update }) => {
    switch (update.type) {
      case "text-delta":
        process.stdout.write(update.text);
        break;
      case "tool-call-started":
        console.log("tool started", update.toolCall.type);
        break;
      case "tool-call-completed":
        console.log("tool completed", update.toolCall);
        break;
    }
  },
});

The callback surface is useful for local UI integrations that need detailed tool payloads. The normalized run.stream() surface is the cross-runtime public stream.

Resuming and Inspecting Agents

Durable agents can be resumed later by ID.

const resumed = Agent.resume(agent.agentId, {
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  local: { cwd: process.cwd() },
});

const run = await resumed.send("What changed last time?");
await run.wait();

You can also inspect persisted agent and run state:

const agents = await Agent.list({ runtime: "local", cwd: process.cwd() });
const runs = await Agent.listRuns(agent.agentId, {
  runtime: "local",
  cwd: process.cwd(),
});
const run = await Agent.getRun(runs.items[0]!.id, {
  runtime: "local",
  cwd: process.cwd(),
});
const messages = await Agent.messages.list(agent.agentId, {
  runtime: "local",
  cwd: process.cwd(),
});

Agent.messages.list(...) reads persisted conversation/checkpoint messages. It is complementary to run.conversation(), which is scoped to one run.

Managing Cloud Agents

Cloud agents support lifecycle operations beyond create/resume/list:

const info = await Agent.get("bc-abc123", { apiKey });
await Agent.archive("bc-abc123", { apiKey });
await Agent.unarchive("bc-abc123", { apiKey });
await Agent.delete("bc-abc123", { apiKey });

Agent.get returns the same SDKAgentInfo shape as Agent.list. archive, unarchive, and delete return nothing; a missing agent throws.

apiKey falls back to process.env.CURSOR_API_KEY if omitted.

Account and Platform

The Cursor namespace exposes account-level queries that aren't tied to a specific agent.

import { Cursor } from "@cursor/february/agent";

const me = await Cursor.me({ apiKey });
const models = await Cursor.models.list({ apiKey });
const repos = await Cursor.repositories.list({ apiKey });
  • Cursor.me() returns the authenticated user's apiKeyName, userEmail, and createdAt.
  • Cursor.models.list() returns the model IDs available to the caller.
  • Cursor.repositories.list() returns GitHub repositories the caller has connected to Cursor, for use as cloud.repos entries on Agent.create.

All three are cloud-only and require an API key (param or CURSOR_API_KEY env var).

Local Settings and MCP

Store-backed local agents do not load ambient Cursor settings unless you opt in. Use local.settingSources to choose which settings layers can affect MCP servers, hooks, skills, rules, subagents, team policy, MDM hooks, and plugins. This field is only available on the local shape — on cloud agents, project / team / plugins are always on and user / mdm / local have no VM equivalent.

const agent = Agent.create({
  apiKey: process.env.CURSOR_API_KEY!,
  model: { id: "composer-2" },
  local: {
    cwd: process.cwd(),
    settingSources: ["project", "plugins"],
  },
  mcpServers: {
    docs: {
      type: "http",
      url: "https://example.com/mcp",
      auth: {
        CLIENT_ID: "client-id",
        scopes: ["read", "write"],
      },
    },
    filesystem: {
      type: "stdio",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-filesystem", process.cwd()],
      cwd: process.cwd(),
    },
  },
});

local.settingSources: ["all"] loads every ambient source. Inline mcpServers are explicit API input, so they are available even when local.settingSources is omitted or []. Inline MCP server definitions are not persisted for Agent.resume(...); pass them again when resuming if the run needs those servers.

Call agent.reload() after local hook, MCP, or settings files change and you want the underlying local executor to pick them up.

Artifacts

The SDKAgent interface includes artifact helper methods:

const artifacts = await agent.listArtifacts();

Artifact support is still runtime-dependent. Local SDK agents currently return no artifacts and throw for downloadArtifact.

Resource Management

Dispose agents when you are done with them.

await agent[Symbol.asyncDispose]();

agent.close() starts best-effort disposal without awaiting it. Prefer [Symbol.asyncDispose]() in scripts and tests.

Static API Reference

  • Agent.create(options): SDKAgent
  • Agent.resume(agentId, options?): SDKAgent
  • Agent.prompt(message, options?): Promise<RunResult>
  • Agent.list(options?): Promise<ListResult<SDKAgentInfo>>
  • Agent.listRuns(agentId, options?): Promise<ListResult<Run>>
  • Agent.getRun(runId, options?): Promise<Run>
  • Agent.messages.list(agentId, options?): Promise<AgentMessage[]>

Known Limitations

  • Persisted conversation replay can only reconstruct information present in the public SDKMessage stream.
  • Inline MCP server definitions are not persisted across Agent.resume(...).
  • Artifact download support is not implemented for local SDK agents yet.