ramp
将不熟悉仓库中的某个主题构建成交互式地图:分组节点、标记边、可点击详情面板以及按运行时顺序编号的导览。
整个流程被刻意拆分为几个阶段。静态分析阶段找出哪些代码重要,由你来决定它们的含义,最后由渲染器绘制地图。跳过静态分析而直接通读仓库,速度更慢且容易遗漏文件;跳过你的解读阶段,只会产生一个没人能从中学到东西的调用图。
工作流程
1. 扫描
node ~/.claude/skills/ramp/scripts/scan.js <repo> --topic "<topic>" --max 30 --out /tmp/scan.json
路径使用绝对路径,因为你将从目标仓库运行,而不是从当前目录。
如果你还不了解仓库的结构,可以先不带 --topic 运行——它会打印一个概览,包括语言构成、最大的目录以及被导入最多的文件(hubs),这通常足以让你选择一个好的主题。
主题扫描返回排好序的 nodes(文件,包含 score、匹配到的 matched 词以及提取的 defs)以及它们之间的 edges。seed: true 标记了直接匹配主题的文件;其余的文件是通过图扩展得到的,是构成完整画面的调用者和被调用者。
如果扫描结果为空,则说明主题词没有出现在代码中。尝试使用代码库自身的词汇,而不是用户使用的词汇。
2. 阅读
阅读种子文件,以及任何名字有启发性的扩展节点。要彻底地阅读——地图的全部价值就在于解释说明,你不可能仅凭文件列表写出有用的 detail。
阅读时,特别注意寻找:
- 入口点——这个流程在运行时从哪里开始?
- 非显而易见之处——防止 bug 的守卫条件、真正干活儿的配置标志、会让新人感到惊讶的东西
- 实际顺序——运行时,谁调用了谁,顺序如何
3. 建模
编写符合以下 schema 的模型 JSON。这部分需要判断力。
4. 渲染
node ~/.claude/skills/ramp/scripts/render.js /tmp/model.json -o /tmp/<repo>-<topic>.html
它会严格校验,拒绝渲染一个格式错误的模型——比如在边中引用了不存在的节点 id、重复的 id、导览中存在悬空引用。关于未说明或孤立节点的警告值得修复,而不是忽略。
5. 发布
使用 Artifact 工具发布渲染后的文件,并将链接交给用户。不要先加载 artifact-design——模板已设计好,直接按原样发布即可。
模型 schema
{
"title": "登录流程",
"repo": "my-app",
"summary": "一两句话:事物的形态以及关于它最有用的一个事实。",
"groups": [{ "id": "boot", "label": "应用启动", "hint": "可选的提示气泡" }],
"nodes": [{
"id": "provider",
"label": "AuthProvider",
"group": "provider",
"role": "持有会话状态",
"detail": "新人真正需要的那段话。",
"files": ["src/context/AuthContext.jsx:12"],
"symbols": ["AuthProvider", "signInWithGoogle"]
}],
"edges": [{ "from": "provider", "to": "supabase", "label": "getSession, OAuth" }],
"walkthrough": [{ "node": "provider", "text": "此步骤发生了什么。" }]
}
groups 是从左到右、按依赖顺序排列的列——入口点在左侧,基础组件在右侧。边从导入者指向被导入者,因此按此顺序排列的模型会布局整洁。最多六个组,会分配不同的颜色。
walkthrough 是可选的,但它是真正起到教学作用的功能。请按运行时顺序而非文件结构来排列节点。一个节点可以出现多次——流程会循环回来,展示这一点才是关键。
好地图与无用地图的区别
节点是概念,不是文件。 两个文件如果是一个概念(如 AuthContext.jsx + AuthContextValue.js),可以合并为一个节点;一个文件如果包含两个不相关的职责,可以拆成两个节点。无论哪种情况,都需将所有真实文件放入 files 字段。
6–14 个节点。 包含 40 个节点的地图仍然是用户原先盯着的那团乱麻。只保留承载流程的关键节点——扫描结果的 score 排序会告诉你该保留什么。在 summary 中说明你省略了什么。
role 是一个职责,而不是对节点名的复述。 例如“持有会话状态”——而不是“认证提供者组件”。
detail 值得点击。 在 detail 中放入那些从节点名中看不出来的东西:为什么要这样拆分、哪个标志很重要、它防止了什么故障、它做了哪些假设。如果一个 detail 仅仅复述了节点名,要么删除这个节点,要么去搞清楚它到底做了什么。
为每条边标注实际关系——例如“基于用户进行门控”、“getSession, OAuth”——而不是“使用”或“导入”。
引用行号。 在 files 中使用 path/to/file.ts:42 将读者指引到精确位置。
说明哪些是关键负载,哪些不是。 新人最需要知道哪些部分是可以忽略的。
备注
- 扫描脚本是零依赖的 Node 脚本,无需安装。当目标是 git 仓库时,它会遵守
.gitignore。 - 对于 Swift 以及同包内的 Java/C#,没有文件级别的导入;对于这些语言,扫描脚本改为根据唯一类型引用推断边。将这些边视为强提示而非确定性结论。
- 导入解析基于正则表达式,而非类型检查器。它能解析相对路径、打包工具别名(
@/)以及按路径后缀匹配的包风格说明符。动态和生成的导入会被遗漏——如果你期望的文件没有出现,请自行将其添加到模型中。