cursor-relay
v0.3.3
Published
Turn a local Cursor login into an Anthropic-compatible API.
Readme
cursor-relay
Unofficial local relay that exposes a personal Cursor session as an Anthropic Messages API.
Point Claude Code, Cline, OpenCode, or any Anthropic-compatible client at the relay. The client speaks Anthropic; cursor-relay translates to Cursor's upstream APIs.
Requires Bun.
Local Claude Code (tools + cwd)
│
│ POST /v1/messages
▼
cursor-relay (Linux or local)
│
▼
Cursor Agent (inference only)This is not an official Cursor or Anthropic product. It uses only the login already present on your machine.
Install
bunx cursor-relay export
bunx cursor-relay serve <token>From a clone:
bun install
bun run export
bun run serveExport
On a machine where Cursor is installed and signed in:
bunx cursor-relay exportThe command reads Cursor's local state.vscdb and prints a single relay token. In a TTY, press c to copy. In a pipe or CI, output is JSON:
bunx cursor-relay export | jq -r .token{"token":"cr1....","email":"[email protected]"}Treat the token as a password. It expires when the Cursor session expires; run export again and pass the new token to serve.
The token also stores the desktop OS and CPU arch (macos/windows/linux and aarch64/x64). serve sends those as Cursor client headers, so a token exported on a Mac still looks like a Mac client when the relay runs on a Linux VPS. Older cr1. tokens without these fields keep using the machine that is running serve.
Serve
bunx cursor-relay serve <token>The token is stored in data/auth.json. Later starts only need:
bunx cursor-relay serveDefault bind is 127.0.0.1:18788.
ANTHROPIC_BASE_URL=http://127.0.0.1:18788
ANTHROPIC_API_KEY=dummyANTHROPIC_BASE_URL must not include /v1. Clients append /v1/messages themselves.
If RELAY_SECRET is set, send that value as x-api-key or Authorization: Bearer. Otherwise any key is accepted.
Linux host, local Claude Code
export still runs on the machine where Cursor is signed in. Copy the token to Linux. The relay only forwards inference; Claude Code keeps its own working directory and tools.
# Linux
BIND=0.0.0.0 RELAY_SECRET=pick-a-secret bunx cursor-relay serve 'cr1....'On the machine running Claude Code:
ANTHROPIC_BASE_URL=http://<linux-host>:18788
ANTHROPIC_API_KEY=pick-a-secretRemote clients need BIND=0.0.0.0 and a RELAY_SECRET.
Claude Code should pick models from GET /v1/models. Claude ids are official Anthropic names (claude-fable-5, claude-sonnet-4-6); GPT, Gemini, and Composer ids are the Cursor family name without an effort suffix (gpt-5.3-codex, composer-1.5). The relay maps them onto catalog variants using thinking and effort. Raw Cursor ids still work.
Protocol
The first-class API is Anthropic:
| Method | Path | Notes |
|---|---|---|
| GET | /health | Liveness |
| GET | /v1/models | One public family name per Cursor catalog model |
| POST | /v1/messages | Anthropic Messages |
| POST | /v1/messages/count_tokens | Local estimate |
Requests and responses follow the Anthropic Messages shape, including thinking blocks and signatures when the upstream model returns them. Responses echo the client-requested model id.
POST /v1/chat/completions remains as a leftover OpenAI-compatible path. New integrations should use /v1/messages.
Configuration
| Variable | Default | Description |
|---|---|---|
| BIND | 127.0.0.1 | Listen address |
| PORT | 18788 | Listen port |
| RELAY_SECRET | unset | Required API key when set |
| AUTH_FILE | data/auth.json | Saved credentials |
| CURSOR_RELAY_TOKEN | unset | Token from export |
| CURSOR_ACCESS_TOKEN / CURSOR_MACHINE_ID | unset | Inject a session without export |
| CURSOR_CLIENT_VERSION | 3.16.17 | Cursor client version sent upstream |
| UPSTREAM_TIMEOUT_MS | 120000 | Chat-path timeout |
--json forces machine-readable CLI output. Non-TTY environments select JSON automatically.
Release
Bump package.json and src/cli.ts VERSION together, commit, then push a matching tag. GitHub Actions publishes to npm with OIDC trusted publishing and creates the GitHub Release. No NPM_TOKEN secret.
git tag v0.3.3
git push origin v0.3.3One-time on npm package settings → Trusted Publisher:
| Field | Value |
|---|---|
| Organization or user | myWsq |
| Repository | cursor-relay |
| Workflow filename | publish.yml |
| Environment | leave empty |
| Allowed actions | npm publish |
After the first CI publish succeeds, you can set Publishing access to require 2FA and disallow tokens. Trusted publishing still works; long-lived tokens do not.
Limits
- Upstream is a private Cursor protocol and can break without notice.
- The relay is single-account and has no isolated multi-user mode.
- Turns go through Cursor AgentService. Client tools are advertised as MCP tools so Claude Code can run its own tool loop. The relay host cwd is not the workspace.
- Cursor ChatService currently rejects this client shape (
Update Required); the relay does not send tool turns there. - Session tokens expire. Re-run
exportwhen requests start failing with auth errors.
