archview
Provides agents with read-only access to local code architecture graphs (structure from tree-sitter, semantic summaries from LLMs), including per-workspace graph/config/status/rebuild tools, while enforcing that topology comes only from static analysis.
README
ArchView
给一个仓库画一张「模块之间怎么依赖」的架构图 —— 拓扑全部来自 tree-sitter 静态分析,LLM 只负责给每个节点写一句人话摘要。同一份图通过 MCP 暴露给你 IDE 里的 agent。
单机、本地、只绑 127.0.0.1。默认中文界面。
📦 直接下载(Windows,不用装 Node、不用 clone)
⬇ ArchView_0.1.0_x64-setup.exe · 35 MB · Windows 10/11 x64
装完双击就有一个独立窗口,里面就是网页版那个面板。自带 Node 与 CodeGraph,
装到 %LOCALAPPDATA%\ArchView,不要管理员权限。用法三步、全程不碰终端:
填一个仓库路径 → 点「重建数据」→ 看图。
⚠️ 没有代码签名,第一次运行会被 SmartScreen 拦一次(「更多信息」→「仍要运行」)。
三条路怎么选:
| 想要 | 走哪条 | 现在能用吗 |
|---|---|---|
| 不碰终端,装个软件点开就看 | ⬆ 上面那个安装包 | 能 |
| 命令行 / CI / 接 MCP | npm i -g archview |
还不能 —— 包已打好并真装过,但作者机器没登录 npm,npx archview 目前 404 |
| 改代码、跑验收脚本 | 源码 | 能 |
完整现状见 第 4 节;桌面版细节见 Windows 独立窗口版。
🚀 让 AI 帮你从源码装
想要命令行版(CI、脚本、接 MCP),或者想改代码 —— 这件事可以整个丢给 AI。
把下面这段整段复制,粘给任何能读网页、能跑命令的 AI 助手(Kiro / Cursor / Claude Code / Codex …),
把 <我的项目路径> 换成你要分析的仓库:
帮我装 ArchView 并把我的项目接进去。
仓库:https://github.com/LZZLHY/archview
安装剧本(先读这个,它是给你写的):https://raw.githubusercontent.com/LZZLHY/archview/main/SETUP-FOR-AI.md
我的项目在:<我的项目路径>
照剧本走:环境体检 → clone → pnpm install + pnpm build → archview init 我的项目 → archview build → 起服务。
剧本里标了「决策点」的地方问我一下再决定(尤其是装到哪、要不要改我的 AI 宿主配置、要不要现在开始写摘要)。
最后把带 token 的面板 URL 给我。
剧本(SETUP-FOR-AI.md)里每个阶段都有「怎么知道这一步成了」,还有一节
「常见失败与对策」。它设计成 AI 在 clone 之前就能通过 raw URL 读到。
自己动手:跳到 第 5 节,五步命令能复制粘贴跑通; 或者一条命令搞定前两步:
# Windows PowerShell(先 clone,再跑仓库里的脚本)
powershell -ExecutionPolicy Bypass -File scripts\setup.ps1
# macOS / Linux
bash scripts/setup.sh
想先判断值不值得看:第 3 节(它凭什么存在)与第 10 节(已知限制 / 谁不该用它)。
1. 它解决什么问题
假设你一个人在写一个 9 个 ohpm 模块的 HarmonyOS 应用(这就是本项目的起因)。你想要两样东西:
- 给自己看:一张能点开、能下钻、能看到「entry 依赖了哪几个 HAR、commons 被谁用」的图;
- 给 agent 看:Cursor / Kiro / Claude Code 里的助手能准确知道项目结构,别再靠 grep 猜。
现成的东西各缺一半:
| 工具 | 有什么 | 缺什么 |
|---|---|---|
| CodeGraph | tree-sitter 挖出来的确定性结构事实,几十种语言 | 没有界面 |
| Understand-Anything | 很好的 React + ELK 架构图 dashboard | 图里的结构是 LLM 挖的;不认 ohpm/ArkTS |
ArchView 把两头接起来:CodeGraph 出事实,UA 的面板出界面,LLM 只补语义。
⚠️ 先看这个:你会得到几个模块,取决于你的仓库形状
「模块之间怎么依赖」这张图的前提是有多个模块。模块不是我们猜的,是从你仓库里的 事实派生的(铁律 1),所以不同形状的仓库结果不一样:
| 你的仓库 | 模块从哪来 | 结果 |
|---|---|---|
pnpm/npm workspace、Cargo workspace、多 go.mod、HarmonyOS ohpm(oh-package.json5 的 file: 依赖) |
包声明 | 一个包一个模块,总览图有连线。这是最理想的情况 |
单个包(一个 package.json + src/core、src/api、src/utils) |
目录层级 | 自动按目录切:src 只有 1 个模块时会往下钻一层,切出 src/core、src/api、src/utils。总览图有连线 |
代码全在一个目录里(src/ 下平铺,或全在 src/lib/ 里) |
目录层级,但切不出来 | 只有 1 个模块,总览图自然没有连线 —— 这不是 bug,是「一个模块内部不存在模块间依赖」。这时候看下钻视图(点开那个模块看文件级依赖),或者在 .archview/config.json 里设 modules.strategy: "pathDepth" + modules.pathDepth 指定切到第几层 |
archview build 每次都会打印一行说明模块是怎么来的,例如:
模块策略 pathDepth —— 未命中工程化模块声明(…),退化到路径深度切分;
按路径首段只得到 1 个模块(src),已自动下钻到第 2 层,切出 4 个模块:src、src/api、src/core、src/utils
archview status 与面板列表页给的是同一句话。看不懂自己的模块为什么是这样分的时候先看它。
⚠️ 一个反直觉的点:modules.labels 只能给已经被识别出来的模块改显示名和描述,
它不能定义模块。往里写一个不存在的 key 不会创造出模块(build 会为此报一条告警)。
要改「模块怎么分」,改的是 modules.strategy / modules.pathDepth。
⚠️ 仓库里有大目录(构建产物、预编译二进制、容器上下文)的话,先写一份 codegraph.json
这是两个不同的开关,作用点不一样,第一次用的人几乎都会踩:
| 想要 | 改哪个 | 效果 |
|---|---|---|
| 让某些目录根本不被索引 | <仓库根>/codegraph.json(CodeGraph 自己的配置) |
索引更快更小。这是根治 |
| 索引它们但不进图 | .archview/config.json 的 include.excludePathPrefixes / excludePathPatterns |
索引照样花那几分钟、照样占那几百 MB |
codegraph.json 是 CodeGraph 的配置文件,不是我们的 —— ArchView 从不生成也从不修改它,
所以不会有人替你写,它也不会被我们覆盖。形状就这么简单:
{ "exclude": ["prebuilt/", "docker/output/", ".tmp-build/", "third_party/"] }
写完删掉 .codegraph/ 再重建一次(索引要重新建才会让 exclude 生效)。
本轮的实测,数字就是这么来的 —— 同一个 HarmonyOS 仓库(281 个 .ets),
唯一差别是有没有这份文件:
| 索引库 | 重建耗时 | 图 | |
|---|---|---|---|
有 codegraph.json(7 条 exclude) |
56 MB | 5.9 秒 | 9,007 节点 / 27,952 边 / 11 个模块 |
| 没有 | 1,493 MB | 4 分钟 | 364,690 节点 / 1,244,410 边 —— 写不出来 |
最后那一格不是夸张:graph.json 靠 JSON.stringify 落盘,而 V8 的字符串上限约 512 MiB,
超过会抛一句 Invalid string length。所以现在有两道拦阻,都会点名 codegraph.json:
索引文件数偏大时在建图之前就给一句告警(不让你白等四分钟),图真的超限时明确拒绝写入
并给出上面那份 JSON。
2. 它是两个 MIT 项目的融合体,这里不避讳
| 层 | 来源 | 归属 |
|---|---|---|
| 结构提取(事实) | CodeGraph | 外部 npm 依赖 @colbymchenry/codegraph,我们只读它的 SQLite 索引、调它的 bin |
| 界面(React + xyflow + ELK dashboard) | Understand-Anything | 全量 vendor,逐文件带上游标注,成为我们的代码 |
| 图 schema / 校验器 | Understand-Anything | 原样搬(packages/core/src/types.ts、schema.ts),刻意保持字节级兼容,好让 vendored 面板不改就能渲染 |
| skill / 语言与框架指导 / agent 流程 | Understand-Anything | 搬过来后逐份改造。上游 24 门语言之外补了 ArkTS 与 13 门 CodeGraph 支持而上游缺指导的语言,合计 38 份 |
| 语义摘要 | 你自己的 LLM agent | 运行时产生,存在被分析仓库里 |
| 缝合、单端口服务、MCP、多工作区、模块策略、框架 deriver | ArchView 原创 | — |
两者皆 MIT。署名与逐文件出处在 NOTICE,本项目自己的许可在 LICENSE。
3. 为什么值得单独存在:LLM 永远不写拓扑
这是本项目唯一的技术根据,也是唯一一条不许妥协的规则:
节点和边只能由 CodeGraph 的 tree-sitter 输出派生。LLM/agent 只能提供
summary与tags,永远不写节点、不写边、不写模块划分。
区别很具体。拓扑由 LLM 生成的项目,必须再写一堆修补脚本擦屁股:规范化对不上的 ID、丢掉指向不存在节点的悬空边、翻转方向搞反的边。这些脚本本身就是「结构不可信」的证据。ArchView 不需要它们 —— 一条边存在,是因为 tree-sitter 在源码里真的解析到了那个引用。
配套的三条规则(覆盖率、layer 覆盖、文件级边上卷)与全部实现约束在 CONTRACT.md。MCP 的工具面里不存在任何写图的工具。
4. 需要什么
| 依赖 | 版本 | 为什么 |
|---|---|---|
| Node.js | >= 22.5(各包 engines 就是这么写的) |
packages/core 用内置的 node:sqlite(DatabaseSync)只读 CodeGraph 的索引库。这个模块在 Node 22.5 之前不存在,低版本连 import 都过不去 |
| pnpm | 10.x(根 package.json 的 packageManager 钉的是 pnpm@10.28.2) |
这是个 pnpm workspace,六个包互相 workspace:* 依赖 |
| git | 任意近期版本 | 可选。没有 git 也能建图,只是 graph.project.gitCommitHash 会是 unknown,「这张图对应哪个 commit」这条线索没了 |
不需要全局安装 CodeGraph:它是 packages/core 的普通 npm 依赖,archview init 会从 node_modules 解析它的 bin 并代你调用(一律带 DO_NOT_TRACK=1 与 CODEGRAPH_NO_UPDATE_CHECK=1)。
发布状态:打包形态已就绪,但还没按下发布键
说清楚现状,不含糊:
- 发布产物已经做出来并真装过:一个叫
archview的单包,带四个 bin (archview/archview-serve/archview-mcp/archview-skill),1.3 MB(压缩)/ 4.0 MB / 217 个文件。 它在一个完全干净的临时目录里被真装了一遍并跑通全流程(init → build → serve → status → skill → MCP)。 - 但 npm 上现在还搜不到它 —— 作者这台机器没登录 npm,所以最后那条
npm publish还没跑。 在它跑之前,npm i archview/npx archview都会 404。 @archview/core这些名字永远不会出现在 npm 上:它们是仓库内部的 workspace 包名 (六个包的package.json都标了private: true),发布的只有archview这一个包。 所以 MCP 配置不要写npx -y @archview/mcp(那个包名不存在),要写npx -y -p archview archview-mcp, 或者直接用装出来的archview-mcp这个 bin。
发布之后(一条命令的事,见下)安装方式就是这两条:
npm i -g archview # 全局装,之后 archview / archview-serve / archview-mcp / archview-skill 四个命令都在 PATH 里
archview init d:/code/my-repo && archview build && archview serve --open
npx archview init . # 不装,试一次就走(每次都会重新下载)
装出来之后不需要 pnpm、不需要 clone、不需要 build。唯一的硬门槛还是 Node ≥ 22.5
(node:sqlite)。@colbymchenry/codegraph 仍然是外部依赖,npm 会只按你的平台装一个子包
(Windows x64 那个 248.7 MB,自带 node.exe 与 tree-sitter 的原生模块)—— 所以第一次 npm i 会下不少东西,
是预期的,我们刻意不把它打进包里(打进去等于让每个平台的用户都下载全部六份)。
要发布的人(需要先 npm login):
pnpm run npm:publish # = 先 build 六个包 → 组装 npm-package/ → npm publish
只想看会发出去什么:
pnpm run npm:pack # 产出 npm-package/archview-<版本>.tgz
npm publish ./npm-package --dry-run # 逐条清单,不落地
组装器是 scripts/build-npm-package.mjs,它的文件头写清了
「为什么是单包」「为什么不用 bundler」以及四道守卫(dist 缺失 / dist 比 src 旧 / 版本号不统一 /
产物自检不过 → 一律拒绝打包,不会发出空包或旧代码)。
仍然可以从源码装(第 5 节):想改代码、想跑验收脚本、想用 pnpm --filter 单独构建某个包,
都走源码路。那条路需要 Node ≥ 22.5 与 pnpm,首次要等一次 pnpm install + pnpm build
(本机实测:全新克隆 install 5.0s、build 17.1s,全流程 25.6s;pnpm store 冷的机器上几分钟正常),
更新走 git pull + 重新 build(dist/ 是 gitignore 的,pull 只换源码不换产物)。
skill 安装器写 MCP 配置时按「本机真实存在的文件优先」:npm 装的形态下它指向
node_modules/archview/packages/mcp/dist/bin/mcp.js,源码形态下指向
packages/mcp/dist/bin/mcp.js,两边都拿不到才退回 npx -y -p archview archview-mcp
并在文案里说明那条要求包已发布。command 用的是当前进程的 node 绝对路径而不是裸
"node":桌面版自带运行时、不要求用户装 Node,而裸 "node" 依赖宿主的 PATH
(可能没有、可能是 18、可能被 nvm 切走)。
Windows 独立窗口版(安装包)
除了命令行,还有一个有自己窗口的 Windows 软件 —— desktop/,Tauri 2 的壳。
已发布,直接下载:
⬇ ArchView_0.1.0_x64-setup.exe (35 MB,Windows 10/11 x64,
%LOCALAPPDATA%安装免 UAC)
也可以自己打:
cd desktop
npm install # 只装 @tauri-apps/cli 一个本机开发工具
npm run build # 产出 ArchView_<版本>_x64-setup.exe(~35 MB)
(需要 Rust 工具链:rustup + MSVC。npm run build 会自己先跑
scripts/stage-resources.mjs 把 npm 单包与生产依赖摆进 bundle.resources,
那一步任何环节失败都会中止构建 —— 所以打不出「缺东西的安装包」。)
它跟浏览器版不是两个东西:窗口里装的就是 packages/web/dist 那个 SPA,
壳只负责 spawn 同一份 packages/server 并在退出时收掉它,Rust 侧一行服务逻辑都没有
(CONTRACT.md 第 9 节把这条钉成了硬约束)。所以面板、CLI、MCP、
桌面版对同一件事给同一个数。
装出来的软件自带 Node 与 CodeGraph,用户机器上什么都不用先装:
| 命令行(npm / 源码) | 独立窗口版 | |
|---|---|---|
| 要先装 Node ≥ 22.5 | 要 | 不要(随包自带) |
| 要下 CodeGraph | 首次 npm i 时下 |
不要(已在安装包里) |
| 安装包体积 | 1.3 MB + 依赖 | ~35 MB(解包 268 MB) |
| 装到哪 | 全局 / 项目 node_modules |
%LOCALAPPDATA%\ArchView,免 UAC |
| 工作区注册表 | ~/.archview/workspaces.json |
同一份(两边看到同一批工作区) |
装完的用法就是「开窗 → 在列表页填一个仓库的绝对路径 → 点重建 → 看图」,全程不碰终端。
没有索引时重建会自己代跑 codegraph init(契约第 6 节)—— 老实现在这里回一条
「先跑 archview init」,而那是一条只有窗口的用户没法执行的命令。
还没做的两件事,说清楚:没有代码签名(第一次运行会被 SmartScreen 拦一次,
「更多信息 → 仍要运行」)、只有 Windows x64(打包脚本按当前平台取 CodeGraph 的
平台子包,跨平台要在目标平台上各打一次)。细节见 desktop/README.md。
平台现状(别指望我们全平台都测过)
- Windows —— 主要开发与验证平台。本 README 里的命令与输出都来自 Windows 11(build 26200)+ PowerShell + Node 22.20.0 + pnpm 10.28.2 上的实跑。skill 安装用 junction,不需要管理员权限。查端口占用:
netstat -ano | findstr :7420。 - macOS / Linux —— 代码里所有平台相关分支都写了(打开浏览器用
open/xdg-open,skill 安装退化成 symlink),但我们没有在这两个平台上系统性跑过验收。遇到问题请开 issue,别当成「官方支持」。 - 运行时会看到一行
ExperimentalWarning: SQLite is an experimental feature。这是 Node 对node:sqlite的常规提示,不是错误。
5. 上手:从取代码到看见图
五步。每一步都写清楚在哪跑、跑完发生什么、怎么知道成功了。
不想自己走这五步?把 开头那段提示词 粘给你的 AI 助手, 它会照
SETUP-FOR-AI.md做完前三步。
第 1 步:取代码
npm 上现在还没有它(见第 4 节:包已经打好、还没 publish),所以第一步是把仓库弄到本机。
发布之后这一节整节都可以跳过 —— npm i -g archview 之后直接从第 3 步(archview init)开始。
四条路,挑一条:
A. git clone(首选) —— 以后 git pull 就能更新。
# Windows PowerShell
git clone --branch main --single-branch https://github.com/LZZLHY/archview.git "$env:USERPROFILE\archview"
cd "$env:USERPROFILE\archview"
# macOS / Linux
git clone --branch main --single-branch https://github.com/LZZLHY/archview.git "$HOME/archview"
cd "$HOME/archview"
B. 下载 zip(没有 git 时) —— 代价:以后更新只能重新下载覆盖。
# Windows PowerShell
Invoke-WebRequest https://github.com/LZZLHY/archview/archive/refs/heads/main.zip -OutFile "$env:TEMP\archview.zip"
Expand-Archive "$env:TEMP\archview.zip" -DestinationPath "$env:TEMP\av" -Force
Move-Item "$env:TEMP\av\archview-main" "$env:USERPROFILE\archview"
# macOS / Linux
curl -L https://github.com/LZZLHY/archview/archive/refs/heads/main.zip -o /tmp/archview.zip
unzip -q /tmp/archview.zip -d /tmp/av && mv /tmp/av/archview-main "$HOME/archview"
解压出来的目录名是 archview-main,记得改名(上面两条已经代你改了)。
C. gh repo clone(装了 GitHub CLI 时)
gh repo clone LZZLHY/archview "$HOME/archview"
D. 一键脚本(把第 1、2 步一起做完) —— 取代码 + pnpm install + pnpm build + 再 pnpm install 一次(补 bin 链接)+ 自检。
先用 A/B/C 拿到代码,然后:
# Windows PowerShell。-ExecutionPolicy Bypass 只影响这一次调用,不改系统策略
powershell -ExecutionPolicy Bypass -File scripts\setup.ps1
powershell -ExecutionPolicy Bypass -File scripts\setup.ps1 -Dir D:\tools\archview -Ref main
# macOS / Linux
bash scripts/setup.sh
bash scripts/setup.sh --dir /opt/archview --ref main
还没 clone、想直接从云端拿脚本的话,先下载看一眼再跑,别无脑管道执行远程脚本:
irm https://raw.githubusercontent.com/LZZLHY/archview/main/scripts/setup.ps1 -OutFile "$env:TEMP\av-setup.ps1"
Get-Content "$env:TEMP\av-setup.ps1" -TotalCount 60 # 看一眼
powershell -ExecutionPolicy Bypass -File "$env:TEMP\av-setup.ps1"
curl -fsSL https://raw.githubusercontent.com/LZZLHY/archview/main/scripts/setup.sh -o /tmp/av-setup.sh
less /tmp/av-setup.sh # 看一眼
bash /tmp/av-setup.sh
脚本参数:-Dir/--dir <路径>(默认 ~/archview)、-Ref/--ref <分支或 tag>、
-SkipBuild/--skip-build、-Help/--help。三条行为保证:目录已存在且是 archview 仓库 →
git pull + 重新 build,不重复 clone;已存在但不是 archview 仓库 → 报错退出、那个目录一个字节都不动;
前置检查失败 → 给可执行的下一步而不是裸 exit 1。它刻意不做 archview init 与起服务 ——
那涉及你自己的仓库和常驻进程,得你或你的 AI 显式决定。
怎么知道成功了:安装目录下
package.json存在且它的name是archview。 用 git 取的还能git rev-parse --short HEAD看到一个 sha。路径尽量别带空格 —— 能用,但之后每条命令的路径参数都得记着加引号。
第 2 步:装依赖 + 构建
在仓库根(也就是第 1 步落地的那个目录,比如 ~/archview):
pnpm install
pnpm build
跑完会发生什么:六个包各自编译。五个 node 包 tsc 出 dist/,packages/web 用 Vite 出 packages/web/dist/(面板前端产物,服务靠它才有页面)。
怎么知道成功了:packages/cli/dist/bin/archview.js 与 packages/web/dist/index.html 都存在,且下面这条能打出帮助:
pnpm archview --help
pnpm install首次会刷一串WARN Failed to create bin at ... ENOENT。 四个包的bin都指向dist/,而首次 install 时dist/还不存在,所以 pnpm 建不出node_modules/.bin/里的链接(最近一次从 GitHub 全新克隆实测 13 条;此前另一次运行是 12 条 —— 条数随 pnpm 版本与 store 布局微变,别把条数当判据,看到这类 WARN 就当正常)。它是无害的:下面所有命令走的是仓库根的 npm scriptpnpm archview(等价于node packages/cli/dist/bin/archview.js),不依赖 bin 链接。 想拿到真正的archview/archview-skill命令:pnpm build之后再跑一次pnpm install,这次链接会建好,之后pnpm exec archview --version与pnpm exec archview-skill …都能用。 走一键脚本(scripts/setup.ps1/setup.sh)的话这一步已经代你做了(它在 build 之后又 install 了一次,并当场验证archview-skill的链接在不在)—— 少了它,文档里所有pnpm exec archview-skill …的命令都会报not recognized/Command "archview-skill" not found。 我们刻意没加prepare脚本自动编译 —— 只想装依赖(CI 缓存、只改文档)的场合不该被迫等一次 Vite 全量构建。
⚠️
typecheck必须在build之后跑pnpm -r run build # 先这个 pnpm -r run typecheck # 再这个反过来一定失败,报一串
TS2307: Cannot find module '@archview/core'(或它的 subpath,例如'@archview/core/themes')or its corresponding type declarations。原因是跨包类型走的是各包package.json的exports→dist/*.d.ts,而dist/是 gitignore 的:没 build 就没有.d.ts。仓库里没有 TS project references,也没有把类型指回src的 path 别名,所以这不是配置疏漏,而是既有性质 —— 陌生人一定会踩,记住顺序就行。同一条机制在日常开发里也会咬人:只要有人在某个包的
src/里新增了一个导出 subpath,其它包在那个包重新 build 之前都 typecheck 不过。看到TS2307先想「是不是该先 build」。
第 3 步:接入第一个要分析的仓库
还在 ArchView 仓库根。把路径换成你自己的仓库:
pnpm archview init d:/code/my-repo
跑完会发生什么(五步,每步都幂等,重复跑只是把现状告诉你):
- 环境检查(Node 版本、目录存在、是不是 git 仓库)
- 在你那个仓库里建 CodeGraph 索引
.codegraph/codegraph.db(已有就跳过) - 写
.archview/config.json(已有就不覆盖;--force-config才重写),并按oh-package.json5/pnpm-workspace.yaml/Cargo.toml/go.mod自动预填模块骨架 - 幂等地往你那个仓库的
.gitignore追加一个带标记的块(详见第 7 节) - 把它登进
archview/workspaces.json(工作区注册表)
怎么知道成功了:最后打印工作区 id 与下一步命令。实跑输出(本次用的是 ArchView 自己的源码副本作为被分析仓库):
[2/5] CodeGraph 索引(结构事实的唯一来源,铁律 1)
→ codegraph init "…/selfcopy"(大仓可能要几分钟,超时 1800s)
* Indexed 160 files
• 2,142 nodes, 6,797 edges in 1.4s
✓ 索引建好了(exit 0,2.5s)-> …/selfcopy/.codegraph
[3/5] .archview/config.json
✓ 已写入:…/selfcopy/.archview/config.json
模块识别:npmWorkspaces —— 自动识别命中 pnpm-workspace.yaml / package.json workspaces,6 个模块
[5/5] 登记进 workspaces.json
✓ 已登记:selfcopy -> …/selfcopy
接入完成。下一步:
archview build selfcopy # 建面板数据(codegraph sync + 建图 + 简报)
archview serve --open # 起服务(127.0.0.1:7420),打开列表页
archview status selfcopy # 随时看索引/图/摘要覆盖率/漂移
常用选项:--id <id>(进 URL,只允许 [a-z0-9][a-z0-9_-]*)、--name "显示名"、--skip-index、--telemetry-off、--json(机器可读:工作区 id、配置/gitignore 动作、模块识别结论、下一步命令;五步进度进 log 字段)。完整清单:pnpm archview init --help。
第 4 步:建面板数据
pnpm archview build # 只登记了一个工作区时可以不带 id
pnpm archview build my-repo # 多个工作区时说清是哪个
跑完会发生什么:codegraph sync(让索引跟上磁盘)→ 建图 → 写 .archview/graph.json 与 meta.json → 生成 .archview/briefs/*.json(给 LLM 的结构简报)→ 再确认一次 .gitignore 块。
怎么知道成功了:每一步前面是 ✓,末尾给出节点/边/模块与摘要覆盖率。本次实跑:
✓ codegraph sync 319 ms exit 0
✓ buildGraph 72 ms 981 节点 / 3851 边 / 7 layer
✓ writeGraph 6 ms
✓ writeMeta 1 ms
✓ buildAllBriefs 3 ms 7 份简报
✓ ensureGitignoreBlock 0 ms unchanged
节点 981 边 3851(文件级 734) 文件节点 158 模块 7
摘要 已应用 0 覆盖率 0.0%(分母=文件节点+框架组件)
覆盖率 0% 是正常的第一次结果 —— 语义摘要要靠 agent 写,见第 6 节。
有告警时(摘要被误放进子目录导致一条都没读到、config.json 校验失败整份回退、modules.labels 里的 key 对不上任何模块)build 会把它们单独拎出来重打一遍并给出修法。告警不是失败,图确实建出来了,但那些东西没生效。
要在脚本/agent 里解析结果就用 --json(比 --quiet 有用得多:它给的是完整的 RebuildResult —— steps / log / warnings / before / after / files / moduleStrategy / summaries / agentGuide,与面板的 POST api/rebuild、MCP 的 archview_rebuild 是同一个对象):
pnpm archview build my-repo --json
随时复查实况:
pnpm archview status # 不带 id 就把注册表里所有工作区各打一段
pnpm archview status my-repo --json
status 的数字与列表页、MCP 的 archview_status 来自同一个函数 —— 不会出现两个不同的覆盖率。
第 5 步:起服务看图
pnpm archview serve --open
跑完会发生什么:一个进程、一个端口服务所有已登记的工作区。默认 127.0.0.1:7420;被占用时自动往上找(最多 20 个),显式给了 --port 就不换、占用即失败。启动打印一次性 session token,所有 api/* 都校验它。
怎么知道成功了:横幅长这样(本次实跑,token 已截断):
ArchView 服务已启动 127.0.0.1:7420(只绑本机)
注册表 …\workspaces.json
工作区 selfcopy
面板产物 …\packages\web\dist
🔑 http://127.0.0.1:7420/?token=be5fea76…27d1
所有 api/* 都要带这个 token(?token= 或 x-archview-token 头)。token 每次启动随机生成,进程重启会换。
Ctrl-C 停止。(进程重启会换 token。)
给了 --token <你定的串> 时最后两行改成「token 由 --token 指定,重启不变」并提醒别提交它 ——
文案按「有没有显式给 --token」分岔,免得固定了 token 的人以为没生效。
「面板产物」那一行必须指到一个真实存在的 packages/web/dist —— 没构建前端时列表页会显式提示 面板前端未构建,这时跑 pnpm --filter @archview/web build。
列表页上每个工作区一张卡片,四个按钮:打开面板 / 重建数据 / 复制 agent 提示词 / 漂移详情。
本次对服务的实测(全部带 token):
| 端点 | 结果 |
|---|---|
GET / |
200,工作区列表页(32.7 KB) |
GET /w/<id>/ |
200,dashboard SPA |
GET /w/<id> (少了尾斜杠) |
301 -> /w/<id>/(带上原 query)。少了这条重定向面板会白屏 |
GET /w/<id>/api/graph.json |
200,1.5 MB |
GET /w/<id>/api/config.json meta.json staleness.json |
200 |
GET /w/<id>/api/prompt |
200,给 agent 的引导提示词 |
GET /api/workspaces |
200 |
GET /skill/download |
200,160 KB gzip |
GET /w/<id>/api/domain-graph.json |
404(我们不产出它,vendored 面板会安静降级) |
不带 token 取 graph.json |
403 |
三种调用方式,随便挑
上面所有命令都写成 pnpm archview …(仓库根的 npm script),因为它在首次 install 之后立刻可用,
不依赖 bin 链接。另外两种等价写法:
# ① 直接跑 node,连 pnpm 都不要(脚本化、给 AI 用最省事)
node packages/cli/dist/bin/archview.js --help # 总览
node packages/cli/dist/bin/archview.js init --help # 每个子命令都有 --help
node packages/server/dist/bin/serve.js --port 7500 # 只起服务,跟 archview serve 是同一个 startServer
# 注意它没有 --help:给任何参数都直接起服务并常驻
# ② 真正的 archview 命令 —— 需要 bin 链接,也就是 build 之后再 install 一次
pnpm install # 这次不会再刷 ENOENT WARN,链接会建好(一键脚本已代你做过)
pnpm exec archview --version
pnpm exec archview-skill --help
注意 ② 只在这个仓库内有效(bin 链接在仓库的 node_modules/.bin/)。想让这四个命令进全局 PATH
就得走 npm 那条路(npm i -g archview),而它现在还没 publish —— 见第 4 节。
6. 让 agent 补上语义
图建好之后节点是有了,但每个节点的 summary 还只是确定性兜底句(docstring / 由签名合成 / <名字> —— <路径> 中的 <kind>)。把它们换成人话是 agent 的活。
零安装路径(先用这个)
-
列表页点 复制 agent 提示词(等价于
GET /w/<id>/api/prompt)。 -
把提示词粘给正在编辑那个仓库的 AI。提示词很短,主要作用是指向工作区里的
<workspace>/.archview/AGENT-GUIDE.md—— 一个本地文件,任何工具都能读。 -
AGENT-GUIDE.md需要生成一次(build不会自动生成它):pnpm archview skill guide --workspace d:/code/my-repo --write本次实跑写出 22 KB(22185 字节),十节内容:铁律、这个工作区现在的样子、具体缺哪些摘要(逐个 nodeId 列出)、过期的摘要、你的输入(结构简报路径)、按检测到的语言挑好的指导、输出格式与提交方式、触发重建 + 只读地确认现状的端点、交付前自检清单、报告格式。提示词里也带了这条命令,agent 自己会跑。
生成一次之后就不用再管它:往后每次重建(面板按钮 /
archview build/POST api/rebuild/ MCParchview_rebuild)都会把它整份重写(契约第 2 节要求如此,所以它在 gitignore 里)。重建的steps里能看到writeAgentGuide这一步跑了没跑。反过来说,文件不存在时重建不会替你创建 —— 我们不往你的工作区塞你没要过的文件。 -
agent 照指南往
.archview/summaries/<分片>.json写摘要。分片名 = 模块 key 里的/换成_(模块packages/core→packages_core.json)。这个目录是平的,写进子目录的摘要一条都不会被读(会告警,但那一轮活白干了)。 -
重建:
pnpm archview build,或列表页点「重建数据」,或 agent 自己POST /w/<id>/api/rebuild?token=…。 -
面板上出现语义,
status的覆盖率往上走。
摘要提交有服务端护栏(默认值在 packages/core/src/limits.ts):每条 30–140 字、标签 ≤6 个且每个 ≤16 字、单批 ≤200 条(超了整批拒绝,一条都不写盘,不截断),再加一份「空话词表」拦截「负责处理相关逻辑」这类废话。阈值与词表的真身只有一份,在 @archview/core:MCP 用它执法、skill 用同一份写指南 —— 免得说明书和执法者不一致(历史上就出过这个 bug)。
⚠️ 护栏只在 MCP 提交这条路上自动执法。 上面第 4 步那样直接写摘要分片时没有任何东西检查它们(写砸了不报错,静默进面板)。所以直接写文件之后跑一次自检,判据与 MCP 完全同一份代码(@archview/core 的 checkSummaryItem):
pnpm exec archview-skill check-summaries --workspace d:/code/my-repo
# 报 "archview-skill not found" 就是 bin 链接还没建(build 之后没再 install 过)。
# 两条出路,任选一条:
pnpm install # 补上链接,之后上面那条就能用
node packages/skill/dist/bin/skill.js check-summaries --workspace d:/code/my-repo # 不依赖链接
逐条报告孤儿 nodeId、长度越界、tags 数量/长度/与确定性标签撞车、空话命中、hash 是否等于当前 content_hash,外加 summaries/ 下有没有子目录、分片 JSON 是否合法;有不合规项时退出码非 0。AGENT-GUIDE 的方式 A 段落与自检清单里都指向它。
进阶路径:装 skill + MCP
更省 token(不必通读源码,读结构简报即可),提交时有结构化校验。
pnpm archview skill hosts # 支持哪些宿主与各自的路径依据
pnpm archview skill install kiro --dry-run # 先看它要动哪些文件(什么都不写)
pnpm archview skill install kiro # 真装
pnpm archview skill verify # 语言/框架指导自检
实测:skill hosts 列出 7 个已确认宿主(kiro、claude、cursor、codex、opencode、gemini、copilot CLI)与一批明确不支持的(路径随平台/版本变、没法复现验证的,我们不猜,用 /skill/download 手动放)。skill verify 实测「语言指导 38 份,框架指导 10 份,全部存在、非占位符、都有上游标注与 ArchView 改造段落」。
Kiro 优先:skill 装到 ~/.kiro/skills/archview,agent 定义 ~/.kiro/agents/archview.json,MCP 写 ~/.kiro/settings/mcp.json。安装器合并不覆盖(只动 mcpServers.archview 一个键),改写已有文件前留 .bak-<时间戳>,Windows 用 junction 不用 symlink。--dry-run 会把要写的内容原样打出来(实测确认它一个字节都不写),--home <dir> 可以把 HOME 指到别处试。
MCP 配置也可以不装 skill 自己抄:AGENT-GUIDE.md 与 api/prompt 的 meta.mcp.snippet 里就带着可直接粘的片段,指向同仓已构建的 packages/mcp/dist/bin/mcp.js。
六个 MCP 工具,只读 + 提交摘要,没有任何写图的工具:
| 工具 | 作用 |
|---|---|
archview_status |
索引/图/摘要覆盖率/漂移 |
archview_list_modules |
模块清单与依赖,附各模块的分片名 |
archview_missing_summaries |
缺摘要或过期的节点,每条附结构简报 |
archview_submit_summaries |
提交摘要,服务端逐条校验并回报哪条被拒、为什么、怎么改 |
archview_rebuild |
codegraph sync + 重建图 |
archview_validate |
校验当前图并回报 issues |
任何宿主都能直接下载 skill 包:GET /skill/download(tar.gz),或 GET /skill/* 明文浏览单个文件(比如 /skill/SKILL.md)。
7. 数据放哪 / 什么该提交进 git
这一节决定了你换机器之后摘要还在不在。 数据全落在被分析的那个仓库里,不在 ArchView 仓库里:
<你的仓库>/
.codegraph/ CodeGraph 索引(SQLite,外部工具的,我们只读) → 不提交
codegraph.json CodeGraph 的排除清单,可选、手写 → 写了就提交(团队共享口径)
.archview/
config.json 语言、模块策略与标签、边阈值、输出语言 → **提交**
summaries/*.json LLM 摘要,按模块分片 → **提交**(这是资产)
graph.json 派生图,面板的数据源 → 不提交
meta.json content_hash 快照(漂移检测的依据) → 不提交
briefs/*.json 给 LLM 的结构简报 → 不提交
AGENT-GUIDE.md 给 agent 的操作说明(每次生成整份重写,含时间戳)→ 不提交
判断标准只有一条:人和 LLM 攒出来的东西提交,工具能重新算出来的东西不提交。
summaries/是几百条人工/LLM 写的中文摘要,重新生成要花掉真金白银的 token。它跟着代码走 —— 换机器、换人、换 agent 都还在。config.json是团队对「模块怎么分、边阈值多少、输出什么语言」的共识。- 其余都是
archview build十秒内能重算的。AGENT-GUIDE.md尤其不该提交:它每次重建整份重写并带时间戳,提交它只会制造冲突。
archview init 与每次 rebuild 都会幂等地往你那个仓库的 .gitignore 追加这个块(靠标记识别,重复运行不重复追加,也不动你原有的行):
# >>> archview >>>
.codegraph/
.archview/graph.json
.archview/meta.json
.archview/briefs/
.archview/AGENT-GUIDE.md
# .archview/summaries/ 与 .archview/config.json 故意不忽略——它们要提交
# <<< archview <<<
ArchView 仓库自己的 .gitignore
本仓库的 .gitignore 排除 node_modules/、dist/(五个包的 tsc 产物与 packages/web 的 Vite 产物同名,一条覆盖)、dist-pack/、*.tsbuildinfo、.tmp/、.codegraph/ 与 *.db*、*.log、.env*、编辑器目录,以及 workspaces.json。
workspaces.json 是工作区注册表,内容是本机绝对路径(d:/code/my-repo),因机器而异 —— 所以新克隆的仓库里这张表一定是空的,这是设计而不是缺失。用 archview init 自己造。
8. 验收脚本
五个脚本加一组单元测试,合起来一百五十多项断言。大部分是「起服务 → 测 → 停」,不留常驻进程,对被检查工作区的写入可逆。
共同前置只有一条:pnpm build。协议层的三个脚本(packages/server/scripts/acceptance.mjs、packages/mcp/scripts/acceptance.mjs、final-check.mjs)不给 --workspace 就自建一次性 fixture 工作区,不需要你准备任何工作区 —— 陌生克隆下来直接 node final-check.mjs 就能跑。只有 packages/core/scripts/selfcheck.mjs 仍然必须给一个真实工作区目录。
下面「实测」一列给两套数字:fixture 模式(默认,见下)与 --workspace <id> 打真实工作区。ArkTS 专项断言在 fixture 与任何非 ArkTS 工作区上都会明确标成「跳过 / 不适用」,不算失败。
「跳过」与「失败」的界线:只在某项检查的前提在这个工作区上不成立时才跳过(图里没有 .ets
节点 → ArkTS 高亮无从检查;只有 1 个 layer → 模块间连线无从成立)。多模块工作区上没有模块间
连线是真 bug,照样报失败(先看「铁律4 文件级边」是不是 0 —— 不上卷就没有模块总览连线)。
默认路径一个字节都不碰用户数据
协议层验收有两种模式,界线就是有没有 --workspace:
- 不给
--workspace(默认):脚本自己在os.tmpdir()里造一个一次性 fixture 仓库 (scripts/lib/fixture-workspace.mjs:pnpm-workspace.yaml+ 4 个包、包之间走深路径的真实跨模块 import、十几个.ts含 class/function/interface、git init+ 一次 commit、按护栏写好的摘要每分片 ≥ 2 条),跑 CodeGraph 索引、建两次图,登记进它自己的临时注册表,跑完删掉。你的仓库、 你的摘要、仓库根那张workspaces.json,一个字节都不会被碰。 想留下 fixture 看看:--keep-fixture。 - 给了
--workspace <id>:跑在那个真实工作区上,开跑前用一个方框显眼地告诉你这次会写什么。mcp那个会写该工作区的.archview/(挪走一条摘要造缺口、改graph.json、真跑一次 rebuild), 备份 / 逐文件 sha256 校验 / 先拷再 rename / 结束时比对,护栏一条不少。
为什么默认换成 fixture。 「刻意不用桩数据、真实数字才有价值」这条理由只对
packages/core/scripts/selfcheck.mjs 成立 —— 它验的是 builder 在真实代码上的语义
(2253 条 auto-corrected 警告就是在真实数据上才暴露的)。而 server / mcp 的验收验的是
端点行为与工具协议,自建一个小仓库完全够。代价却是真实的:这些脚本会删摘要条目、改
graph.json、真跑 rebuild。此前的两轮修补(修还原逻辑、取消「注册表第一条」默认回退、加备份校验)
都没动根因 —— 只要默认靶子是用户的真实仓库,安全就永远只靠「每一处备份代码都没写错」,
而事故(一次 restore() 静默删掉一个工作区里 308 条不可再生的人工摘要,脚本还报
PASS 已恢复原样)已经证明这个假设不成立。
rebuild 的写入面比 .archview/ 大一圈,备份名单跟着走。 ensureGitignoreBlock 碰的是
工作区根的 .gitignore(改写前的原文落在 .gitignore.archview-bak),所以 mcp 验收的备份名单
现在相对工作区根解析:.archview/graph.json、.archview/meta.json、.archview/briefs、
.archview/summaries、.archview/AGENT-GUIDE.md、.gitignore、.gitignore.archview-bak。
备份 → 逐文件 sha256 校验 → 还原 → 结束时比对,这两个根文件与 .archview/ 走的是同一条路。
(此前名单相对 .archview/ 解析,于是一次 --workspace 验收改写了用户的 .gitignore 而护栏
一无所知 —— 它只看 .archview/。)server 那个脚本在 --workspace 模式下也给这两个文件加了
备份 / 还原 / 逐字节比对。
名单外唯一会被写的东西是 .codegraph/codegraph.db(codegraph sync 改它):刻意不还原 ——
几十到几百 MB 的可再生索引,拷进备份的代价远大于收益。
托管块内的行不再被静默清除。 块的语义是整块替换,所以写在 # >>> archview >>> 与
# <<< archview <<< 之间的用户规则以前会在下一次 rebuild 消失。现在 ensureGitignoreBlock
发现块内有不是自己生成的行时拒绝写入(refused),把行号与原文报进 rebuild 日志、
archview status、列表页与 archview_status 的 warnings,一个字节都不动。自己的规则写在块外。
| 脚本 | 怎么指定工作区 | 实测 |
|---|---|---|
node final-check.mjs |
不给 = fixture(只读,跑完删);--workspace <id> / ARCHVIEW_CHECK_WS 打真实工作区,同样只读、不 rebuild |
断言总数随工作区形状变,跳过的项不计入分母(所以打印出来的永远是 N/N)。实测:fixture 14/14 + 1 跳过(ArkTS 高亮不适用);ArkTS 多模块真实工作区 15/15;单模块工作区 13/13 + 2 跳过(再跳过「模块总览有连线」—— 只有 1 个 layer 时跨 layer 的边无从成立,见第 1 节那张表) |
node packages/server/scripts/acceptance.mjs |
不给 = fixture;--workspace <id> / ARCHVIEW_ACCEPT_WS 打真实工作区(只读,除非 --rebuild —— 那会真的重建它的 .archview/)。没有「注册表第一条」这种回退 |
fixture 46 通过 / 0 失败(ArkTS 与 json5 两条断言在 fixture 上自动跳过);ArkTS 真实工作区 47 通过 / 0 失败 |
pnpm --filter @archview/server run test |
不用指定;末项会遍历注册表里所有工作区校验它们的列表页 payload | 17/17 通过(node --test,跑完约 0.8s;比旧版多一项:CONTRACT.md 第 2 节的 gitignore 块与 GITIGNORE_BLOCK_BODY 逐字一致 —— 这条约束以前只写在契约里,没有判据) |
node packages/mcp/scripts/acceptance.mjs |
不给 = fixture(fixture 自带合规摘要,缺口造得出来);--workspace <id> / ARCHVIEW_MCP_WS / ARCHVIEW_ACCEPT_WS 打真实工作区,那个工作区必须已经有 LLM 摘要(脚本靠挪走一条造缺口)。--skip-rebuild 跳过最后那次真重建;ARCHVIEW_WORKSPACES 可以换注册表 |
fixture 37/37 通过,含末项「工作区已恢复原样(.archview/ 与工作区根的 .gitignore 逐文件 sha256 相同)」。显式模式下开跑就打印备份目录路径;备份做完会与工作区逐文件比对 sha256,不一致就当场 exit 1(那时还一个字节都没改)。Ctrl-C 走与 finally 同一条清理路径,退出码 130 |
node packages/core/scripts/selfcheck.mjs --workspace <dir> |
--workspace 必填,且是目录不是 id;--summaries <dir> 可选;--keep 保留中间产物。不传参数时打印用法与本机已登记的工作区 |
9/9 通过(其中一项:.gitignore 在五种真实形状下用户自有行一字不少 —— 第五种是「用户把规则写在托管块里」,判据是必须 refused)。被检查的工作区一个字节都不写(末项就是验证这个) |
pnpm archview skill verify |
无前置,不碰任何工作区 | 语言指导 38 份 + 框架指导 10 份全部通过 |
跑之前先清环境变量残留
# PowerShell
Remove-Item Env:ARCHVIEW_ACCEPT_WS,Env:ARCHVIEW_WORKSPACES,Env:ARCHVIEW_MCP_WS,Env:ARCHVIEW_CHECK_WS -ErrorAction SilentlyContinue
# bash / zsh
unset ARCHVIEW_ACCEPT_WS ARCHVIEW_WORKSPACES ARCHVIEW_MCP_WS ARCHVIEW_CHECK_WS
ARCHVIEW_WORKSPACES 换掉的是读哪张注册表,ARCHVIEW_ACCEPT_WS / ARCHVIEW_MCP_WS / ARCHVIEW_CHECK_WS 换掉的是测哪个工作区。它们在 shell 里残留一次,就会出现「明明没改代码,验收数字却变了」这种最费时间的假象 —— 因为你测的已经是另一个仓库了。同一个道理也适用于命令行:archview init|build|status --workspaces <file> 可以显式指定注册表,多注册表并行时建议每条命令都写上,别靠环境变量记状态。
三个坑,踩过才知道:
selfcheck.mjs结束时会把整个archview/.tmp/删掉(除非给--keep),不只是它自己那个子目录。别把想留的东西放在.tmp/下。- 裸跑三个协议层脚本现在会自建 fixture,不再
exit 1。 上一版是「不给--workspace就打印用法并退出」,现在是「不给就用一次性 fixture」。所以node packages/mcp/scripts/acceptance.mjs直接跑得通 —— 它打的是os.tmpdir()里自己造的仓库,不是你的。 - MCP 验收里「写入现有分片时先合并再写」这条断言,要求被挑中的那个分片里除了缺口之外还有别的条目。 脚本按文件名排序取第一个含 file 节点的分片来造缺口,如果那个分片恰好只有一条摘要(比如只有一个文件的
_other模块),缺口造完分片就空了,这条断言就无从成立,会报一条36/37。fixture 因此刻意给每个 file 节点都写摘要(每个分片 ≥ 2 条,生成器里有硬断言把关)。打真实工作区遇到这条失败是工作区形状问题,不是代码问题:把摘要写全一点,或让第一个分片对应一个多文件模块即可。 --workspace模式下「幂等重建」那条断言要求工作区的graph.json与它的源码是同步的。 断言比的是重建前后的节点数;如果该仓库在上次archview build之后改过源码,重建自然会得出不同的节点数(实测:某工作区 8972 → 8969,因为源码里少了一个文件),报一条36/37。这是工作区状态问题:先archview build一次再跑验收。fixture 模式没有这个问题(图是刚建的)。
9. 实测数字(附出处)
数字随仓库内容变化,所以每一条都标明是哪个仓库、什么时候、什么口径。
A. ArchView 分析自己(本次为写这份 README 重跑;被分析的是 ArchView 源码的一份副本,排除了 node_modules/、dist/、.tmp/;Windows 11 / Node 22.20.0 / pnpm 10.28.2):
| 项 | 值 |
|---|---|
| CodeGraph 索引 | 160 文件 / 2142 节点 / 6797 边(1.4s);语言 typescript(114) tsx(37) javascript(7) yaml(2) |
| 图 | 981 节点(function 578 / class 245 / file 158) / 3851 边,建图 72 ms |
| 文件级边(铁律 4 的上卷) | 734(其中上卷新增 680) |
| layer | 7(6 个 pnpm 包 + _other),模块策略 npmWorkspaces(命中 pnpm-workspace.yaml) |
| 模块总览连线 | 8 对模块之间共 210 条聚合边 |
空 summary 节点 |
0(981 个节点全非空,这是铁律 2 的验收指标) |
| 摘要覆盖 | 首次建图 0 / 158(0%)—— 语义要靠 agent 写,这就是一个新工作区该有的样子 |
| 各模块文件数 | web 84 / server 23 / core 17 / cli 12 / skill 11 / mcp 10 / _other 1 |
数字会随源码变动漂移:同一套口径在此前一个更早的源码版本上跑出来是 899 节点 / 6 模块 / 618 文件级边 / 6 对模块之间 148 条聚合边。差异全部来自源码本身长大了,不是口径变了 —— 所以别把这些数当基准值去断言,要断言就跑验收脚本。
B. AMCL(作者机器上的一个 HarmonyOS / ArkTS 应用,ohpm 多模块) —— 这些数字是只读观测到的(读它已经建好的 graph.json,没有重建过它):8972 节点 / 27864 边 / 11 模块 / 文件级边 3216 / 摘要 308 条(覆盖 308 / 682,其中框架组件 71),模块策略 ohpm。更早一个版本上同一套口径是 4277 节点 / 16124 边 / 10 模块 / 摘要 304 —— 差异全部来自那个应用自己长大了。packages/core/src/limits.ts 里的摘要长度区间(40–80 字)就是从这批人工摘要量出来的:min 36 / p50 57 / p95 78 / max 108 字。
C. 验收用的一次性 fixture 仓库(scripts/lib/fixture-workspace.mjs 现造现删,所以这些数字每次都一样,可以拿来当基准):4 个 pnpm 包 / 13 个 .ts / 20 个文件 → CodeGraph 索引 0.8s → 49 节点 / 150 边 / 4 模块 / 文件级边 43 / 摘要 13 条(覆盖 13/13),模块策略 npmWorkspaces,模块总览 6 对模块之间 26 条聚合边,gitCommitHash 是真的(git init + 一次 commit)。从造目录到图就绪约 2.0s。
10. 已知限制 / 谁不该用它
诚实清单。不吹。
- 单机工具,没有多用户模型。 只绑
127.0.0.1,鉴权只有一个进程级一次性 session token。没有账号、没有角色、没有审计。不要暴露到外网,也不要当团队服务部署。 - 并发重建是互斥的,但拿不到锁会直接失败而不是排队。 三个入口(面板 /
archview build/ MCP 的archview_rebuild)走同一把文件锁.archview/.rebuild.lock。第二个请求会立刻收到「另一个进程正在重建(pid X,从 Y 开始)」,HTTP 那层回 409。刻意不排队:排队会让浏览器一直转圈,而两次全量codegraph sync排在一起对你没有价值。死锁自愈两条 —— 同机持锁进程已经不在,或超过 30 分钟。锁只保护重建:它不管「一边重建、一边有人手改summaries/」,那种情况以最后写盘的为准。 - 写盘是原子的(同目录临时文件 +
rename),覆盖graph.json/meta.json/briefs// 摘要分片 /config.json/ 注册表。断电或强杀进程不会留下半截文件。摘要分片另有两道护栏:读不懂旧内容就拒绝覆盖、条目数只允许增加或持平(详见CONTRACT.md第 5 节)。 /skill/download与/skill/*不校验 token,但能读到的东西是白名单化的。 它们吐的是随包发布的 skill 文档(SKILL.md、languages/*.md、frameworks/*.md),本来就要给任何 agent 宿主直接拿,所以刻意没上门禁。可浏览集合 == 随包发布集合,两者共用同一个目录遍历,而那个遍历排除node_modules/dist/.git且只收真实文件 —— 所以符号链接一律不在集合里。这一点是补出来的:老实现只做「不许..+ 前缀检查」,挡住了传统穿越,却挡不住 pnpm 在packages/skill/node_modules/@archview/core放的那个指向packages/core的链接(链接的文本路径是 skill 目录的子路径,前缀检查一路放行),实测GET /skill/node_modules/@archview/core/src/builder.ts返回 200 加 25 KB 源码 —— 那已经不是「无 token 的取舍」,是无鉴权的任意文件读。会读你代码的端点(api/graph.json、api/file、api/rebuild…)全部校验 token。- 摘要质量完全取决于你的 agent 和你给它的预算。 ArchView 只保证「拓扑是真的」和「不许写空话」,不保证摘要写得好。护栏能拦住空话词表里的废话,拦不住一句正确但没用的话。
- HarmonyOS / ArkTS 是唯一验证充分的场景。 ohpm 模块识别、ArkUI 组件树两跳折叠、
.ets高亮都是在真实 ArkTS 工程上打磨的。其它语言只做了结构层验证(能索引、能建图、模块能识别、面板能渲染),没有针对性的框架推导,语言指导也只做了文档层自检。 - 只在 Windows 上系统性跑过验收。 macOS / Linux 的平台分支写了但没测。
- 不是「一键理解任意仓库」。 第一次
init大仓可能要几分钟(CodeGraph 索引),摘要要 agent 跑好几轮。它适合你打算长期维护的项目,不适合十分钟浏览一个陌生仓库。 - 模块总览的 layer 间边是无向的。 vendored 的
aggregateLayerEdges把 A→B 与 B→A 合并了。方向信息在下钻视图里还在。 - 走「包根 barrel」的跨包 import 解析不出来,所以模块总览上会少边。 CodeGraph 能解析深路径的跨包引用(
import … from '../../server/src/rebuild.js'这种),但import { startServer } from '@archview/server'—— 即指向包入口、由package.json的exports再转发到实现文件的那种 —— 解析不到目标符号,于是这条依赖不进图。本仓库自己就是例子:packages/cli/src/commands/serve.ts走 barrel,简报的importsFrom里没有 server;build.ts走深路径,解析出来了。看到模块总览上少一条你确信存在的边,先怀疑这个原因(去简报里看那个文件的importsFrom:为空或缺目标,就是它)。这是上游 CodeGraph 的解析能力边界,不是可配置项;我们刻意不在 builder 里按包名猜补这条边 —— 猜出来的拓扑就是 LLM 写拓扑的另一种形式,违反铁律 1。真要在图上看到它,把那处 import 改成深路径(或等 CodeGraph 支持)。 - 边按
confidence/resolvedBy过滤(默认阈值 0.7,丢弃heuristic)。不过滤会出现纯靠名字撞出来的假模块依赖(实测存在confidence: 0.3的 fuzzy 边)。反过来说,被过滤掉的真依赖也就看不见了。 - CodeGraph 遥测默认开启,但我们代你调它时一律带
DO_NOT_TRACK=1与CODEGRAPH_NO_UPDATE_CHECK=1(写在runCodegraph里,不是可选项)。想把它的全局开关也关掉:pnpm archview init … --telemetry-off。 - 源码浏览端点有硬限制:
/w/<id>/api/file只允许图里出现过的filePath(白名单)、拒绝..与绝对路径、上限 1 MB、拒绝二进制。
11. 架构与包结构
archview/
package.json pnpm workspace 根(scripts: build / typecheck / selfcheck / archview)
LICENSE NOTICE README.md CONTRACT.md
AGENTS.md 仓库根路牌(多个 agent 工具会自动读它):装 → SETUP-FOR-AI,改代码 → CONTRACT
SETUP-FOR-AI.md 给 AI 的一次性安装剧本(阶段 + 成功判据 + 决策点 + 失败对策)
scripts/setup.ps1 一键准备(Windows):取代码 + install + build + 补 bin 链接 + 自检。幂等,不碰你的仓库
scripts/setup.sh 同上(macOS / Linux;只做过 bash -n 语法检查,未在真实 Unix 上跑过)
workspaces.json 工作区注册表(本机绝对路径,不提交)
final-check.mjs 整体验收(起→测→停)
packages/
core/ 图模型与校验(vendored UA schema)、CodeGraph 读取、builder(CG→图)、
模块策略、框架 deriver、结构简报、.archview/ 布局与选择性 gitignore、
提交护栏阈值与空话词表(唯一真身)
web/ vendored 改造的 dashboard。按 /w/<id>/api/* 取数,中文默认开
server/ 单端口服务:工作区列表页 + 每工作区的面板与只读 API + rebuild
bin: packages/server/dist/bin/serve.js (archview-serve)
mcp/ MCP server(stdio)。六个工具,只读 + 提交摘要
bin: packages/mcp/dist/bin/mcp.js (archview-mcp)
skill/ SKILL.md 顶层提示词、38 份语言指导 + 10 份框架指导、
AGENT-GUIDE.md 生成器、多宿主安装器
bin: packages/skill/dist/bin/skill.js (archview-skill)
cli/ 统一入口:init | build | serve | status | skill
bin: packages/cli/dist/bin/archview.js (archview)
「六个包」与
pnpm install打的Scope: all 7 workspace projects说的是同一件事。packages/下确实是六个包;第七个是仓库根自己(archview,pnpm 把 workspace 根也算一个 project,因为它有自己的package.json与 scripts)。根这个 project 不产出dist/,也不发布 —— 它只承载pnpm build/pnpm typecheck/pnpm archview这些 script。看到 7 别以为多装了东西。
cli 不重实现任何逻辑:build 调 server 的 rebuildOnce,status 调 inspectWorkspace,serve 调 startServer,skill 原样转发给 archview-skill。理由是面板、MCP、命令行对同一件事必须给同一个数 —— 覆盖率这种指标一旦有两个来源,两个数一定会分叉。
数据流一句话:
你的源码 ──tree-sitter──▶ .codegraph/codegraph.db ──builder──▶ .archview/graph.json ──▶ 面板 / MCP
▲
.archview/summaries/*.json ──┘ (只贡献 summary 与 tags)
▲
你的 LLM agent ┘(读 .archview/briefs/*.json,不读源码)
12. 许可与致谢
ArchView 自己是 MIT(LICENSE)。它站在两个同样是 MIT 的项目上:
- Understand-Anything — MIT, © Yuxiang Lin and Infinite Universe, Inc. 面板、图 schema、校验器、skill 与语言/框架指导都来自它。我们全量 vendor 并改造,每个 vendored 文件头部都写着上游路径与改了什么。
- CodeGraph — MIT, © Colby McHenry. 全部结构事实的来源。没有 vendor:我们依赖发布的 npm 包,只读它的 SQLite 索引,调它的 bin。
逐文件出处与两者的完整署名在 NOTICE。如果这个项目对你有用,请先去给上面两个仓库点星 —— ArchView 只是把它们接了起来。
13. 想改点什么
先读 CONTRACT.md(AGENTS.md 是给 agent 的一页速览,指向同一处)。
它是硬约束地基,不是风格指南 —— 四条铁律(LLM 不写拓扑 / summary 非空 / layer 覆盖全部文件节点 / 文件级边必须上卷)、冻结的节点 ID 方案、图 schema、模块策略、服务端点表、MCP 工具面,全在里面,每一条都写了「为什么」和「违反了会发生什么」。违反其中任何一条是设计错误。
尤其注意两处:
- 节点 ID 方案是冻结的。 摘要文件用节点 ID 做 key,改 ID 等于作废所有人已有的摘要资产。
- 图 schema 与 vendored 的 UA schema 完全一致,不加不减。 面板是照搬的,schema 一动就要改面板。私有信息走节点的 passthrough 字段(边不是 passthrough,额外字段会被静默 strip,别依赖)。
改完至少跑:
pnpm -r run build # 一定在 typecheck 之前
pnpm -r run typecheck
pnpm --filter @archview/server run test
node packages/core/scripts/selfcheck.mjs --workspace <你的工作区目录> # 只有这个必须给真实工作区
node packages/server/scripts/acceptance.mjs # 不给 --workspace = 自建一次性 fixture
node packages/mcp/scripts/acceptance.mjs # 同上;给了 --workspace 它才会写那个工作区
node final-check.mjs # 同上;只读
跑之前先清掉 ARCHVIEW_* 环境变量残留(第 8 节给了两个 shell 的命令),否则你测的可能是另一个仓库。
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.