CockpitCockpit
← 返回博客

把代码读成地图,而不是树

发布于 2026年5月7日 · 阅读约 7 分钟

文件树告诉你字节存在哪里,但不告诉你代码如何流动。Cockpit 新的 Code Map 视图把任意源文件渲染为函数 chip 画布——左侧列出谁调用了这个函数,右侧列出它调用了谁,点击 pin 即可跳转。陌生代码库五次点击就能走完一遍鉴权流程。下面是 5 个真实使用场景。

你 clone 了一个新仓库。npm installnpm run dev,跑起来了。

接下来要真正读懂它。

文件树展开:47 个文件夹、312 个文件。其中几个叫 utils、几个叫 lib、一个叫 core 还有一个叫 kernel(你怀疑它们重叠)。从哪开始?大概 index.ts 吧。20 分钟之后你已经飘进了第三层子目录,开了 11 个 tab,仍然不知道你要修的那个 bug 入口在哪个函数里。

文件树告诉你的是字节存在哪里,而不是代码怎么流动

换一个单位

Cockpit 新的 Code Map 把"单位"换掉了。你看到的不再是"文件夹里的文件",而是函数 + 它们之间的连线

每个函数变成画布上的一张卡片:

  • 中间是函数体 —— 真实代码、语法高亮。
  • 左侧:所有调用这个函数的地方(caller)。
  • 右侧:这个函数调用的所有目标(callee)。
  • 两侧每一项都可点击。点一下,画布平移到那个函数。

整个界面就这么简单。文件树还在,想要随时切回去。但只要你点进一个文件,你看到的就不再是 "payment.ts 第 1–840 行",而是四张 chip:chargeCardrefundwebhookHandlerrecordLedgerEntry —— 每张都画着自己的进出箭头。

场景一:新仓库的第一天

这是 Code Map 最初被造出来要解决的场景。早上 9 点入职,10 点你被要求"看一下我们的鉴权流程"。靠文件树,这是一场 90 分钟的"找地鼠"。靠 Code Map:

  1. 打开你猜是入口的文件 —— routes/auth.ts
  2. 文件里五个路由处理函数各自变成一张 chip。
  3. 选你关心的那个:loginHandler。这张 chip 高亮。
  4. 右侧列出:它调用了 validateCredentialsissueTokenrecordLogin。点击 validateCredentials
  5. 画布平移。现在 validateCredentials 在中间。它的 callee 是 hashPasswordlookupUser;它的 caller —— 左侧 —— 告诉你它还被 resetPassword 调用,而你之前根本不知道有这个函数。

五次点击就把鉴权树走完了。没 grep 过 "login",没在 utils/index.ts 里迷路。这张地图本来就藏在代码里 —— 只是需要有人把它画出来。

场景二:追一个你不放心的调用

这是每个资深工程师都会偷偷做、却没人教新人的事:当你对一个函数为什么被调用感到不安,你会沿着调用链往上走,直到看清入口。

传统做法是 grep + 直觉grep -r 'createOrder' 命中 23 次:19 个在测试里,2 个在注释里,2 个是真正的调用点。你打开两个,上下翻找,琢磨哪个"先发生"。

在 Code Map 里,createOrder 左侧那一列就是答案。已排序、已去重,默认不混测试文件(除非你要看)。点每一项就跳到具体那行。"这个函数到底是从哪里被调用的"这个问题,从五个 tab 的挖掘变成 10 秒钟的视觉检查。

场景三:评审 AI 写的 PR

你让 Claude "修一下限流器的 bug"。它给你交出 8 个文件、3 个目录的改动。Diff 看上去合理。你正打算 Approve。

先别。

把同样这些文件切到 Code Map。Diff 不再是一长串 +/- 行,而是一张 chip 视图,改动过的函数被高亮,周围还画着它们的 caller 和 callee。你立刻能看到:

  • Agent 改了 rateLimit。它的 caller 是 apiHandlerwebhookHandler。这次改动会不会把 webhook 那条路径搞坏?点进去,读 chip,30 秒搞定。
  • 它还改了 getClientIp,这个函数有11 个 caller,其中一半在鉴权子系统里。Agent 没在 PR 里提这件事。你大概率得先把这 11 处都看一遍再 approve。

你自己写的 PR 这么做有点小题大做。但凌晨 3 点 Agent 趁你睡觉时写的 PR,这就是"我相信它"和"我应该相信它"之间的差别。

场景四:跨文件追 bug

用户报告:"偶尔刷新一下,购物车会丢一件商品。"你的猜测是 syncCart 里有竞态。在 Code Map 里打开 syncCart

五个 callee:一个 fetchCart、两个 mergeCart 的变体、一个看上去可疑的 dedupeItems。点击 dedupeItems,函数体里有一个以 id 为 key 的 Set —— 但 bug 报告里说有些商品 id 相同、尺寸不同抓到了。

三次点击。没 grep、没有"开十个 tab 上下翻滚"。地图把"出 bug 的那一节"放在你眼前,是因为它周围的 chip 给了你正确的上下文。

场景五:飞机上、没有 LSP,照样能读

Code Map 完全跑在你笔电上,由 tree-sitter 解析。没有 language server、没有项目索引、没有后台守护进程。打开一个目录,立刻有 chip 视图。合上电脑、飞去柏林,飞机上打开同一个目录 —— 还是那张 chip 视图,零索引等待。

这件事比听上去重要。基于 LSP 的工具(VSCode 的 "find references"、JetBrains 的 "show callers")都需要项目完全启动:tsconfig 解析完、pip install 装完、go.mod 完整。Code Map 跳过这些前置。它像一个仔细的人类读者那样读你的代码:能解析就能出 chip 视图,仅此而已。

目前支持 TypeScript / JavaScript、Python、Go、Rust。作为用户,你只需要知道这一句。

什么时候用它

老实说:Code Map 没打算取代你的编辑器。如果你正在新代码,你应该在 Explorer 的常规视图里,带着光标和 LSP 类型提示。Code Map 是为了你写之前的那一刻 —— 你需要先读懂。

一个有用的分工:

  • 文件树 + 编辑器:你已经知道要改什么、改在哪。
  • Code Map:问题是"什么调用了什么,我该从哪里下手?"

你会一整天在两者之间来回切。它们看的是同一份文件,回答的是不同的问题。

上手

打开 Cockpit → Explorer → 打开任意源文件 → 点 Code Map 切换。Chip 视图替换原来的编辑器面板 —— 同一个文件,换一个镜头。点击 callee pin 飞到下一个函数。读完了切回来。

那个你从一月就想读、一直没动的仓库?现在是 5 分钟的 walkthrough。


npm i -g @surething/cockpit · GitHub · Try Online