An adapter that bridges the Cursor CLI agent (`cursor-agent`) to the Agent Client Protocol (ACP). It exposes the Cursor agent over ACP’s ndjson stream so any ACP client can drive it. So far, it can be used in these clients: - Zed - JetBrains (coming soon)
npm install cursor-acpAn adapter that bridges the Cursor CLI agent (cursor-agent) to the Agent Client Protocol (ACP). It exposes the Cursor agent over ACP’s ndjson stream so any ACP client can drive it. So far, it can be used in these clients:
- Zed
- JetBrains (coming soon)
- AionUi
- Emacs via agent-shell.el
- marimo notebook
- neovim
- through the CodeCompanion plugin
- through the yetone/avante.nvim plugin
grepToolCall/globToolCall → ACP tool_call with summaries and file locationsbashToolCall/shellToolCall → ACP tool_call with output + exit codedefault and plan mode, including current_mode_updatecancelled, and flushes final updates before resolve- Node.js 18+
- Cursor CLI (cursor-agent) installed and on PATH
Then:
``bash`
npm install
npm run build
Expose the ACP server:
`bash`
node ./dist/index.js
By default, the adapter calls cursor-agent on your PATH. To use a specific binary:
`bash`
export CURSOR_AGENT_EXECUTABLE=/full/path/to/cursor-agent
Authenticate Cursor if needed:
`bash`
cursor-agent login
Point your ACP client to the adapter’s stdio process. For SDK-based clients, use ndJsonStream with the adapter’s stdin/stdout.
`js
import { spawn } from "node:child_process";
import { Readable, Writable } from "node:stream";
import { ndJsonStream, ClientSideConnection, PROTOCOL_VERSION } from "@agentclientprotocol/sdk";
const env = { ...process.env };
// Optional: target a specific Cursor binary
// env.CURSOR_AGENT_EXECUTABLE = "/usr/local/bin/cursor-agent";
// Start the adapter
const proc = spawn("node", ["./dist/index.js"], { stdio: ["pipe", "pipe", "inherit"], env });
// Wire ACP stream
const input = Writable.toWeb(proc.stdin);
const output = Readable.toWeb(proc.stdout);
const stream = ndJsonStream(input, output);
// Minimal client
class Client { async requestPermission({ options }) { return { outcome: { outcome: "selected", optionId: options?.[0]?.optionId ?? "allow-once" } }; }
async sessionUpdate(u) { if (u.update.sessionUpdate === "agent_message_chunk" && u.update.content.type === "text") console.log(u.update.content.text); } }
const conn = new ClientSideConnection(() => new Client(), stream);
// Drive a simple prompt
const init = await conn.initialize({ protocolVersion: PROTOCOL_VERSION, clientCapabilities: { fs: { readTextFile: true, writeTextFile: true } } });
const { sessionId } = await conn.newSession({ cwd: process.cwd(), mcpServers: [] });
const res = await conn.prompt({ sessionId, prompt: [{ type: "text", text: "Say hello" }] });
console.log("stopReason=", res.stopReason);
proc.kill();
`
Use this adapter as an External Agent in Zed.
1) Build the adapter
`bash`
cd /path/to/cursor-acp/cursor-acp
npm install
npm run build
2) Configure Zed (settings.json)
Add an entry under agent_servers pointing to the built adapter:
`jsonc`
"agent_servers": {
// ... your other agents
"Cursor": {
"command": "node",
"args": ["/absolute/path/to/cursor-acp/cursor-acp/dist/index.js"],
"env": {
// Optional: only if cursor-agent isn’t on PATH
// "CURSOR_AGENT_EXECUTABLE": "/usr/local/bin/cursor-agent"
}
}
}
3) Use it in Zed
- Open the Agent panel in Zed.
- Click "+" → New Thread → choose "Cursor".
- If prompted to authenticate, run cursor-agent login in a terminal and retry.
- CURSOR_AGENT_EXECUTABLE – optional path to the Cursor binary (defaults to cursor-agent)
- The adapter forwards tool call updates even after cancellation, then responds with cancelled as required by ACP.
- For shell tools, empty stdout is rendered as “(no output)” and exit code is included when provided.
- Build: npm run buildnpm run dev`
- Watch:
MIT