Skip to main content
Glama

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,不要管理员权限。

用法:复制一段话给你的 AI,然后回答几个问题。

打开软件时面板是空的,上面有一段可复制的提示词(带着这次运行的真实端口与 token)。 把它粘给正在编辑你项目的那个 AI —— Kiro / Claude Code / Cursor / Codex / opencode / Gemini CLI / Copilot CLI 都行,它会自己认出自己是哪个。然后它会:

  1. 连上这个已经跑着的窗口(不会去 clone 或再装一份)

  2. 认出自己是哪个宿主,把 MCP 配好(动你的配置之前会先问你)

  3. 在你的工作区里递归找出候选项目 —— 一个文件夹里有好几个仓库/子项目是常态, 它会把清单给你看,问你要接哪个(还是全都接)

  4. 注册 + 建索引 + 建图(索引不存在时它自己会建,大仓几分钟)

  5. 再问你要不要现在写语义摘要(那一步烧 token,所以必须问)

你只需要回答几个问题,然后等窗口里出现图。做法写在 CONNECT-FOR-AI.md(软件里那段提示词就指向它), 带真实端口与 token 的实况版在运行时的 /onboarding.md。

完全不用 AI 也能出图。 首屏是并列的两栏,右边那栏就是这条路:点「选择文件夹…」 弹出目录选择器(带盘符、快捷入口、以及「像是项目 / 已接入」的角标)→ 选中 → 确认 id → 注册 → 点卡片上的「重建数据」。它会自己代跑 codegraph init 建索引再建图。

这条路一个 AI 都不需要,因为拓扑本来就全部来自 tree-sitter 静态分析(第 3 节铁律 1)—— AI 只是把每个节点的摘要从「由签名合成的兜底句」换成人话。图先出来,摘要以后随时补。

三个入口之间可以随便切

情况

行为

先 archview serve 在浏览器里用,中途想开桌面版

桌面版复用那个正在跑的服务,不会新起端口。窗口里和浏览器里是同一个进程、同一批数据

已经开着桌面版,又敲 archview serve

命令行提示「本机已经有一个在跑」并给出它的 URL;确实要再起一个隔离实例就加 --no-reuse

桌面版点窗口的 ×

问一句:最小化(保持服务运行,默认) / 退出 / 取消。最小化后收进托盘,下次打开秒开

复用的是命令行起的服务,然后在桌面版点 ×

第二项变成「只关窗口,服务由起它的终端管」—— 桌面版不去关别人的服务

接缝是 ~/.archview/running.json(服务启动时登记、退出时撤销)。判活三段缺一不可: 登记里 host 是本机、pid 还活着、GET /api/ping 回的 pid 与登记一致。 第三条是关键 —— 只验「端口能连上」会让桌面版连上一个抢到同一端口的别的程序。

⚠️ 没有代码签名,第一次运行会被 SmartScreen 拦一次(「更多信息」→「仍要运行」)。

Related MCP server: rpg-encoder

或者装命令行版

npm i -g archview                 # 四个命令进 PATH:archview / archview-serve / archview-mcp / archview-skill
archview init d:/code/my-repo && archview build && archview serve --open

npx archview init .               # 不装,试一次就走

已发布在 npm:archview。不需要 pnpm、不需要 clone、不需要 build,唯一的硬门槛是 Node ≥ 22.5(node:sqlite)。首次 npm i 会顺带下 CodeGraph 的平台子包(Windows x64 那个 248.7 MB,自带 node.exe 与原生模块)—— 这是预期的, 我们刻意不把它打进包里(打进去等于让每个平台的用户都下载全部六份)。

三条路怎么选:

想要

走哪条

不碰终端,装个软件点开就看

⬆ 上面那个安装包

命令行 / CI / 接 MCP

npm i -g archview

改代码、跑验收脚本

源码

三者共用同一份工作区注册表(~/.archview/workspaces.json),所以随便混着用, 都看到同一批项目。桌面版细节见 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 应用(这就是本项目的起因)。你想要两样东西:

  1. 给自己看:一张能点开、能下钻、能看到「entry 依赖了哪几个 HAR、commons 被谁用」的图;

  2. 给 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)。

发布状态:两种形态都已上线

形态

地址

体积

npm 单包 archview(四个 bin)

https://www.npmjs.com/package/archview

1.3 MB 压缩 / 4.0 MB 解包 / 219 文件

Windows 安装包(独立窗口,自带 Node 与 CodeGraph)

Release 页

35 MB 压缩 / 268 MB 解包

npm 那份在一个完全干净的临时目录里被真装真跑过(从 registry 拉,不是本地 tarball): npm i archview 8.8 秒 → archview init 真调 CodeGraph 建索引 → archview build 建出图 (单包布局自动下钻出 2 个模块)→ archview-serve 起服务、图端点与接入端点全部 200、 prompt 由 @archview/skill 渲染而不是内置兜底、两份 zod 的 alias 隔离生效(mcp 3.25.76 / core 3.24.1)。

@archview/core 这些名字永远不会出现在 npm 上:它们是仓库内部的 workspace 包名 (六个包的 package.json 都标了 private: true),发布的只有 archview 这一个包。 所以 MCP 配置不要写 npx -y @archview/mcp(那个包名不存在),要写 npx -y -p archview archview-mcp, 或者直接用装出来的 archview-mcp 这个 bin —— 最好的写法是指向本机真实存在的 mcp.js 绝对路径 (面板与 GET /api/onboarding 给的就是它)。

要发新版本的人(需要 npm login,或者 ~/.npmrc 里有带 publish 权限的 token; npm 现在默认要求 2FA,交互式发布得加 --otp=<6 位码>):

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 script pnpm 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

跑完会发生什么(五步,每步都幂等,重复跑只是把现状告诉你):

  1. 环境检查(Node 版本、目录存在、是不是 git 仓库)

  2. 在你那个仓库里建 CodeGraph 索引 .codegraph/codegraph.db(已有就跳过)

  3. 写 .archview/config.json(已有就不覆盖;--force-config 才重写),并按 oh-package.json5 / pnpm-workspace.yaml / Cargo.toml / go.mod 自动预填模块骨架

  4. 幂等地往你那个仓库的 .gitignore 追加一个带标记的块(详见第 7 节)

  5. 把它登进 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 的活。

零安装路径(先用这个)

  1. 列表页点 复制 agent 提示词(等价于 GET /w/<id>/api/prompt)。

  2. 把提示词粘给正在编辑那个仓库的 AI。提示词很短,主要作用是指向工作区里的 <workspace>/.archview/AGENT-GUIDE.md —— 一个本地文件,任何工具都能读。

  3. AGENT-GUIDE.md 需要生成一次(build 不会自动生成它):

    pnpm archview skill guide --workspace d:/code/my-repo --write

    本次实跑写出 22 KB(22185 字节),十节内容:铁律、这个工作区现在的样子、具体缺哪些摘要(逐个 nodeId 列出)、过期的摘要、你的输入(结构简报路径)、按检测到的语言挑好的指导、输出格式与提交方式、触发重建 + 只读地确认现状的端点、交付前自检清单、报告格式。提示词里也带了这条命令,agent 自己会跑。

    生成一次之后就不用再管它:往后每次重建(面板按钮 / archview build / POST api/rebuild / MCP archview_rebuild)都会把它整份重写(契约第 2 节要求如此,所以它在 gitignore 里)。重建的 steps 里能看到 writeAgentGuide 这一步跑了没跑。反过来说,文件不存在时重建不会替你创建 —— 我们不往你的工作区塞你没要过的文件。

  4. agent 照指南往 .archview/summaries/<分片>.json 写摘要。分片名 = 模块 key 里的 / 换成 _(模块 packages/core → packages_core.json)。这个目录是平的,写进子目录的摘要一条都不会被读(会告警,但那一轮活白干了)。

  5. 重建:pnpm archview build,或列表页点「重建数据」,或 agent 自己 POST /w/<id>/api/rebuild?token=…。

  6. 面板上出现语义,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 的命令),否则你测的可能是另一个仓库。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides a dependency graph of any local repository with tools for change impact, transitive dependents, health audits, and more, enabling AI coding agents to see structure and refactor safely.
    4,912 npm
    4
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables LLM agents to navigate source code structurally via tree-sitter over MCP, offering outline-based reading, AST pattern search, workspace-scale symbol indexing, call graph analysis, and built-in security audit queries.
    15
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides local-first repository architecture analysis with file-level proof, enabling agents to map codebases, locate implementations, trace call paths, and assess change impact with deterministic evidence.
    4 npm
    9
    MIT