Cursor客户端解剖(一)为什么是-VS-Code-Fork

系列:Cursor客户端解剖系列学习笔记

先看应用包里有什么

学习材料对应的是 macOS .appContents 目录,标准 Electron 布局:

路径 角色
MacOS/Cursor 原生启动器(Mach-O),几乎不含业务逻辑
Frameworks/ Electron / Helper 进程
Resources/app/out/ 主程序打包后的 JS(core)
Resources/app/extensions/cursor-* Cursor 内置扩展(Agent 能力的主要落点)
Resources/app/product.json 品牌、更新通道、扩展替换表、API proposal 白名单

不需要传统「二进制反编译」。 业务逻辑主要在 JS。难点是核心被打成超大 bundle(例如 workbench.desktop.main.js 约 45MB),变量名被 mangle,没有 source map。

所以「学 Cursor」更现实的路径是:对照开源 VS Code 的分层,再读 cursor-* 扩展的清单与小扩展逻辑。

一句话设计理念

包内导读把它概括成:

把「AI 编程代理」做成 IDE 的一等公民,同时尽量复用 VS Code 已验证的编辑器 / 扩展 / 进程隔离模型。

具体是三层叠加:

  1. 继承:Monaco + Workbench + Extension Host(VS Code 基因)
  2. 嵌入:Composer / Agent / Retrieval / MCP 作为内置能力
  3. 演化 UIglass 工作台尝试用新壳承载 Agent-first 交互

为什么不是「做一个插件」就够了

VS Code 扩展模型很强,但扩展始终是宿主菜单上的客人:

  • UI 与渲染主路径受 Extension API 边界约束
  • 很难把多文件 Diff、Agent 轨迹、Shadow Workspace 做成一等公民
  • 高频能力(检索、工具执行、长连接)不宜全塞进普通扩展生命周期里碰运气

Cursor 的选择是:Fork 内核拿控制权,再把增量能力拆成多个内置扩展
这是「fork 内核 + 能力插件化 + UI 渐进替换」,不是推倒重来。

Fork 换来的,不只是改皮肤

从包内能直接看到的增量:

  1. 双 Workbench 入口

    • workbench.desktop.main.js — 经典桌面工作台
    • workbench.glass.main.js — Glass 新壳(同量级大 bundle)
      UI 可以换壳,底层服务 / 扩展协议尽量共用。
  2. product.json 的 proposed API 白名单
    大量 extensionEnabledApiProposals(如 cursorcursorAgentHostcursorTracing)。
    含义:用 VS Code 的 proposed API 机制合法扩展宿主能力,而不是到处 hack private API。

  3. 扩展替换表
    extensionReplacementMapForImports 把社区/微软扩展映射到 Anysphere 发行版(例如语言服务、Remote SSH)。
    兼容用户心智,同时控制关键路径的实现版本。

和「手搓一个侧边栏 Chat」的差别

路线 你得到什么 你失去什么
插件 上线快、跟随宿主升级 交互与隔离上限受 API 约束
Fork 编辑器级体验、进程与协议可深度改造 持续 rebase 上游、自己扛发行通道

Cursor 押的是:当编程主路径被 Agent 接管时,编辑器必须跟得上。插件路线很难把「编排 / 执行 / 检索 / 远程权威」做成 IDE 操作系统级能力。

小结

「为什么是 VS Code Fork」在包里的答案很务实:

  • 底座已经证明能规模化(编辑器 + 扩展宿主 + 远程权威)
  • AI 差异集中堆在 Agent 运行时、检索、MCP、Glass
  • 用内置扩展集群表达能力,用 proposed API 扩展宿主,而不是把一切写死在 45MB bundle 的无法维护角落

下一篇把分层摊开:Glass / Workbench Services / Extension Host / Utility / Electron。