Cursor 的 SDK、CLI 与 Bridge:三条接入路怎么选
想把 Cursor 的 agent 接进自己的流程,第一次翻文档时最容易懵的地方是:它给了不止一条路,而这几条路分散在不同的文档区里,没有一张总表把它们并排放着。结果就是:在 CI 里先装了 CLI,之后想给 agent 挂自家函数,才发现得改用 SDK;或者一上来去啃 Bridge 的 protobuf,其实自己写的是 Python——官方对 Python 早就给了首方包。
这篇不排名,只沿着官方文档写明的边界,把选择路径倒推一遍。
官方自己是按什么分叉的
cursor.com/docs/sdk/bridge 的「When to use it」表给了四行,这是文档里最接近「总表」的东西:
| 路径 | 官方文档写明的适用场景 |
|---|---|
| TypeScript SDK | 你在写 TypeScript 或 JavaScript |
| Python SDK | 你在写 Python |
| SDK Bridge | 你需要 Go、Rust、Java、C# 或别的语言 |
| Cloud Agents API | 你只需要云端 agent、走 HTTP,不需要本地 agent 运行时 |
注意这张表里没有 CLI。它的第一分叉是「调用方用什么语言」,而命令行的 agent 属于另一条轴——终端与脚本,文档在 cursor.com/docs/cli/overview 里单讲。把这两条轴混成一条,是选型第一步就跑偏的原因。
同一页还写明了 Bridge 的定位:它面向 SDK 作者与平台团队,应用代码应当依赖 @cursor/sdk 或 cursor-sdk。这句话把 Bridge 排在了「兜底路」的位置,而不是并列的第三选项。
第一问:调用方是人,还是你的程序
命令行那条路有两种形态:agent 直接进交互式会话,agent -p(print 模式)用于脚本与 CI。CLI 文档写明它支持与编辑器相同的三种模式——Agent、Plan、Ask,可用斜杠命令、快捷键或 --mode 切换,其中 Ask 是只读探索、不做修改。
SDK 那条路是库:Agent.create() 返回一个 handle,Agent 是持有会话状态的持久容器,Run 是一次 prompt 提交的单位,各自管自己的流、状态、结果与取消。
Bridge 那条路是一个本地服务器:它内嵌 TypeScript SDK,把同一套 agent 接口用 Connect/protobuf 协议暴露出来,你的适配器把它拉起来(或接到平台已经跑着的那个)。文档明确写了「Classic gRPC over HTTP/2 will not connect」——必须用 Connect 客户端,或者直接发带 protobuf / JSON body 的 POST。这条限制不写在显眼处,但踩上去会以「连不上」的形式表现出来。
第二问:你要多细的事件
这是三条路差异最大的一处,也是最该在选型阶段就定下来的。
CLI 侧:--output-format 有 text(默认)、json、stream-json 三档,且只在 --print 或推断出 print 模式(非 TTY 的 stdout、管道 stdin)时有效。json 只在成功时输出一个 JSON 对象,不发增量与工具事件;失败时不产生格式良好的 JSON,只有非零退出码和 stderr 上的错误信息。stream-json 是 NDJSON,成功时以一个终结的 result 事件收尾,失败时流可能提前中断、没有终结事件。要字符级增量得再加 --stream-partial-output,此时 assistant 事件有三类,官方给了判别表:timestamp_ms 存在且 model_call_id 不存在的那一类才带新文本,另外两类是工具调用前的缓冲刷新和回合末的最终刷新,都该跳过。
SDK 侧:run.stream() 产出规范化的 SDKMessage,按 type 判别(system、user、assistant、thinking、tool_call、status、task、request、usage);想要更细就把 onDelta 回调传给 send(),拿到的是 InteractionUpdate,里面有 text-delta、thinking-delta、tool-call-started、step-completed、turn-ended 这一层。文档同时给了稳定性免责:tool_call 事件上的 args 与 result 反映各工具的内部形状、会随工具演进而变,工具名也可能被改名或替换,应当当作 unknown 防御式解析;稳定的只有信封本身(type、call_id、name、status)。
Bridge 侧:流走 sdk.v1 的 run-stream 信封,协议由七个 proto 文件构成(agent service、cursor service、bridge control service、custom tool callback service、store callback service、messages、errors)。文档要求你 vendor 时不要动 proto/,因为 Cursor 每次 SDK 发布都会重新生成这些文件。
咬人的地方在这里:如果你打算在 shell 里用 jq 串 CLI 的输出,失败路径上你没有 JSON 可解;如果你打算在 SDK 里解析工具参数做业务判断,官方已经先声明了那部分不稳定。
第三问:谁批准工具调用
三条路的默认口径不一样,这是最容易想当然的一处。
CLI 的 print 模式默认不落盘:文档写明不加 --force(或 --yolo)时,改动只是被提议、不会真的改文件。要在脚本里让它动文件,得显式加上。
SDK 的本地 agent 默认相反:快速上手那一节明说,默认的本地 agent 会直接执行 shell、edit、write 之类的工具调用,headless 模式下没有人工审批环节。要 gate 住,官方给的两条路是配置 hooks(如 beforeShellExecution、preToolUse),或者开 local.sandboxOptions.enabled: true。
sandbox 本身两侧都有,但形态不同。CLI 用 /sandbox 或 --sandbox <mode>(enabled 或 disabled),文档写明设置跨会话保留。SDK 的 local.sandboxOptions.enabled 默认是 false(这是文档写明的默认值,随版本可能变动);开启后写入被限制在 local.cwd 与一小组允许路径、工作区外的读被阻断,shell 命令跑在平台 sandbox 里(Linux 上 bubblewrap、macOS 上 seatbelt、以及随包发的 @cursor/sdk-<os>-<arch> helper),出网默认拒绝,要放行得在工作区放 .cursor/sandbox.json 列出允许的主机。宿主不支持沙箱时,SDK 会抛 ConfigurationError 并在消息里点名缺的依赖。云端 run 一律在隔离 VM 里执行,sandboxOptions 不适用。
还有一层是 local.autoReview: true,把本地工具调用交给 Auto-review 分类器判定。文档自述这条:分类器是 best-effort 的便利手段、不是安全边界,且因为 headless 没有交互审批,被判定拦截的调用是直接拒绝而非升级给人,agent 会拿到拦截原因再换路子。
Bridge 这一侧,文档没有单列它自己的权限口径——它嵌的是 TypeScript SDK,能力随二进制版本走。这一点我们没有独立依据,不比。
const agent = await Agent.create({
apiKey: process.env.CURSOR_API_KEY!,
model: { id: "composer-2.5" },
local: {
cwd: process.cwd(),
sandboxOptions: { enabled: true },
},
});
示例里的 model id 只是官方文档当时的示例值,平台上有哪些模型随时在变,不要当清单用。
第四问:跑在本地还是云端
SDK 把这件事做成了同一套接口下的两个运行时:Agent.create() 传 local 还是 cloud 决定跑在哪,两边用同一个 CURSOR_API_KEY;本地 agent 拿到 agent-<uuid> 形式的 ID,云端是 bc-<uuid>,Agent.resume() 按前缀自动判定运行时。文档专门澄清了一句容易误解的话:这里的「Local」说的是 agent 循环与文件访问在本地,推理在两种模式下都走 Cursor 托管的模型。
CLI 侧的对应能力是会话中途移交:在消息前加 & 前缀,就把任务推给 Cloud Agent 继续跑。
两个运行时各有独占项,这直接决定选型。云端独有:产物列取与下载(本地 SDK agent 目前返回空的产物列表,downloadArtifact 会抛错)、cloud.envVars 这类随 agent 或随 run 注入并在结束后移除的环境变量、autoCreatePR、以及挂在 agent 上的 metadata 标签。本地独有:自定义工具、tools / disallowedTools 工具集裁剪(文档的措辞是「目前仅本地 agent」,且这两项不会持久化在 agent 上,Agent.resume() 时要再传一遍)、autoReview、sandboxOptions、以及 local.settingSources——文档写明这一项对云端 agent 不适用,云端总是加载 project、team、plugins。
各自不可替代的那一块
CLI 的不可替代处是终端本身:交互式会话、会话管理(agent ls 列出并恢复、agent resume、--continue、--resume="chat-id-here")、需要提权时的掩码密码提示(文档写明密码经安全 IPC 通道直达 sudo,模型不会看到),以及 agent acp 这条给自定义客户端用的 ACP 通道(stdio 传输、JSON-RPC 2.0 信封、按行分隔的 JSON 帧)。这几项在我们引到的 SDK 文档页里没有找到对应说明。
SDK 的不可替代处是「跑在你自己的进程里」:自定义工具的 execute 就在你的进程中执行,能碰到你代码能碰到的一切,且它们跳过交互审批(沙箱与 auto-review 的限制仍然生效)——但这项是本地 agent 专属,传给云端 agent 会抛 ConfigurationError。此外还有内联 subagent 定义、工具集白名单与黑名单(deny 优先)、prewarmLocalWorkspace() 预热工作区扫描、每次 send() 都有的 requestId 用来把脚本跑批和后端日志对上号。
Bridge 的不可替代处只有一句话:语言不在首方覆盖范围时,它是官方给的那条通路。它的协议策略写得很清楚——sdk.v1 只做加法式变更,字段不重编号也不复用,破坏性变更会以 sdk.v2 与 v1 并存的方式发布;运行时想 gate 能力就调 SdkBridgeControlService.GetVersion 看 protocol_version 与 capabilities。代价也写得很清楚:Cursor 支持的是已发布的 sdk.v1 protos、独立的 cursor-sdk-bridge 二进制和首方 TS / Python SDK;社区或自研适配器的版本管理、支持与安全审查由你自己负责。
Windows 侧
CLI 有两条不同的安装路径。WSL 与 macOS、Linux 走同一条:
curl https://cursor.com/install -fsS | bash
Windows 原生走 PowerShell:
irm 'https://cursor.com/install?win32=true' | iex
装完用 agent --version 验证,agent update 手动更新(文档写明默认会尝试自动更新)。要注意文档里那两条把 ~/.local/bin 加进 PATH 的步骤只给了 bash 与 zsh 的写法,Windows 原生 PowerShell 下的等价步骤,官方文档没有说明这一点。
Bridge 的归档解开后是 bin/cursor-sdk-bridge(Windows 上带 .exe)、proto/sdk/v1/ 和 manifest.json;平台标识用 darwin、linux 或 win32 配 x64 或 arm64,其中 Windows 只有 x64。装了 cursor-sdk 的 Python 包之后,同一个二进制会随 wheel 装到 PATH 上,调试适配器之前先确认它是新的:
cursor-sdk-bridge --help
RPC 失败而适配器看不出原因时,用 --verbose(或设 CURSOR_SDK_BRIDGE_LOG=1)把每个 RPC 的名字、结果、耗时和完整错误打到 stderr——文档同时写明请求与响应的载荷从不记录。
SDK 侧的环境门槛:TypeScript SDK 要求 Node.js 22.13 或更高,并随包发 per-platform 的 @cursor/sdk-<os>-<arch> 二进制用于沙箱与内置 ripgrep;Python SDK 要求 Python 3.10 或更高。前面沙箱那段只点名了 Linux 的 bubblewrap 与 macOS 的 seatbelt,Windows 上沙箱怎么落地,官方文档没有说明这一点。
还有一个只在打包时才暴露的坑:默认构建会在运行时懒加载自身的一部分,单文件打包器跟不过去,编译出来的应用会在第一次 Agent.create() 时报形如 Cannot find module './986.js' 的错。官方给的解法是改用 @cursor/sdk/bundled 入口;并写明这些 bundled 入口跑在 Bun 上(包括 bun build --compile 出来的可执行文件),在 Node 上也能加载但 SQLite store 不可用、默认的本地 agent store 会退回 JSONL。
三条路共有的部分,别当差异比
- 认证:都用
CURSOR_API_KEY。SDK 与 Bridge 的文档口径一致——接受用户 API key 与服务账号 API key,Team Admin API keys 文档写明尚不支持(not yet supported)。Bridge 多一层:除 Cursor API key 外还有握手时按进程生成的 bridge bearer token,每个 RPC(含流式)都要带Authorization: Bearer <token>,服务默认监听127.0.0.1。 - 计费口径:SDK 的 run 与 IDE、Cloud Agents 遵循同一套定价、请求池与 Privacy Mode 规则,用量会带 SDK 标记出现在团队用量面板上。具体数值本文不写,以官方定价与用量说明页为准。
收成一条决策路径
- 调用方是人、在终端里 → CLI 交互式会话。
- 调用方是程序,语言是 TypeScript / JavaScript → TypeScript SDK;是 Python → Python SDK。
- 调用方是程序,语言是 Go、Rust、Java、C# 等 → Bridge,并接受适配器由你自己维护。
- 只要云端 agent、不需要本地运行时 → 文档表里的第四行,Cloud Agents API。
- 只是 CI 里的一段 shell、不想引依赖 → CLI 的 print 模式,别忘了
--force和选对--output-format。 - 需要在同一个进程里给 agent 挂自家函数 → SDK 的自定义工具,且必须是本地运行时。
有一类维度这篇不比:速度、生成质量、稳定性——我们没有装过、跑过,没有依据。CLI 那一侧有没有与 SDK 自定义工具、工具集裁剪相对应的能力,本文只依据上面引到的那几页文档,没找到对应说明的也不比。
以上命令与参数组合为按官方文档中的参数语义组合的示例,未经实测,以官方文档与 --help 的实际输出为准;文中的 TypeScript 片段为按官方文档中的字段语义组合的示例,同样未经实测,以官方文档与 API 的实际响应为准。该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。
本文依据 Cursor 官方文档(cursor.com/docs 与 cursor.com/help)于 2026-08-18 的公开内容整理。
该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现;
我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。
该产品迭代频繁,文中涉及的设置项与命令随版本变动,请以官方文档最新内容为准。
本文不涉及订阅价格、额度与模型清单,相关信息请以官方定价与模型说明页为准。
本文对照的是同一产品内的三种接入形态,依据均为上述官方文档,不对这几种形态做优劣排名, 选型结论只在官方文档写明的能力边界内成立。
安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。