Understand-Anything 架构笔记
1. 整体架构:Prompt 即代码
Understand-Anything 没有自己的 LLM API,它寄生在 Claude Code 的能力上。
你输入 /understand
↓
Claude Code(背后的 Claude 模型)
↓
加载插件的 57 个 .md 文件作为 prompt
↓
Claude 按照 prompt 指示,扮演各种 agent 角色
↓
产出 knowledge-graph.json → Dashboard
2. 57 个 .md 文档 ------ 项目的核心
understand-anything-plugin/
├── agents/ (9) --- 定义每个 AI agent 的角色和工作流程
│ ├── project-scanner.md 扫描项目、枚举文件
│ ├── file-analyzer.md 分析代码、生成图谱节点/边
│ ├── architecture-analyzer.md 识别架构分层
│ ├── tour-builder.md 生成引导式 tour
│ ├── graph-reviewer.md 验证知识图谱质量
│ ├── assemble-reviewer.md 审查图组装结果
│ ├── article-analyzer.md 分析文章文档
│ ├── domain-analyzer.md 领域分析
│ └── knowledge-graph-guide.md 图谱结构参考
│
├── skills/ (8) --- 定义每个 / 命令的编排逻辑
│ ├── understand/SKILL.md /understand(7 阶段主流程)
│ ├── understand-chat/SKILL.md
│ ├── understand-dashboard/SKILL.md
│ ├── understand-diff/SKILL.md
│ ├── understand-domain/SKILL.md
│ ├── understand-explain/SKILL.md
│ ├── understand-knowledge/SKILL.md
│ └── understand-onboard/SKILL.md
│
├── skills/understand/
│ ├── languages/ (23) --- 每种编程语言的领域知识
│ │ java.md, python.md, typescript.md, go.md, rust.md...
│ │ → 注入给 LLM:这个语言的典型目录结构、关键语法标记
│ │
│ ├── frameworks/ (10) --- 每种框架的知识
│ │ spring.md, react.md, django.md, rails.md, vue.md...
│ │ → 注入给 LLM:框架的约定、注解含义、文件组织方式
│ │
│ └── locales/ (6) --- 多语言输出指南
│ zh.md, ja.md, ko.md, ru.md, zh-TW.md, en.md
│ → 注入给 LLM:tag 用中文写、summary 用中文写,技术术语保留英文
│
└── hooks/ (1)
└── auto-update-prompt.md
核心设计原则
md 文档 = 意图层(告诉 LLM "做什么"、"为什么这样做"、"在什么上下文下做")
ts/js/py 代码 = 执行层(做 LLM 不擅长的精确计算)
3. TypeScript / JavaScript 代码做什么
一句话:LLM 不擅长的机械任务,全部交给代码。
| 类别 | 关键文件 | 为什么 LLM 做不了 |
|---|---|---|
| 类型定义 | types.ts |
KnowledgeGraph 的精确类型约束 |
| 文件过滤 | ignore-filter.ts |
glob pattern 匹配(ignore npm 包) |
| 文件扫描 | scan-project.mjs |
枚举 700+ 文件、逐行数行数、语言检测 → 纯机械 |
| 结构提取 | extract-structure.mjs |
用 tree-sitter 解析 AST → 需要精确解析器 |
| Import 解析 | extract-import-map.mjs |
跨 12 种语言的精确 import 解析 |
| 批次计算 | compute-batches.mjs |
Louvain 社区检测算法 → 数学计算 |
| 图谱合并 | merge-batch-graphs.py |
去重、修正 ID、丢弃悬挂引用 → 数据清洗 |
| Schema 验证 | schema.ts |
JSON Schema 规则校验 |
| 指纹检测 | fingerprint.ts |
MD5 hash → 确定性 diff |
| Dashboard | dashboard/ (React + Tailwind) |
浏览器 GUI |
分工一句话
LLM(读 md prompt): "看懂代码是什么意思"
代码(ts/js/py): "精确、可重复的机械任务"
4. /understand 命令是如何注册和触发的
命令注册(零配置,约定优于配置)
Claude Code 加载插件时:
- 扫描
skills/目录 - 找到每个
SKILL.md - 读取 frontmatter 中的
name字段 - 自动注册为
/name命令
yaml
# skills/understand/SKILL.md
---
name: understand # → 注册为 /understand
description: Analyze a codebase...
argument-hint: ["[path] [--full|--exclude <patterns>]"]
---
agents/ 目录同理------每个 md 自动注册为可调用的 agent。
命令执行流程
1. 你输入: /understand C:\path\to\project --exclude "tests/*"
2. Claude Code 解析:
- 命令: understand
- 参数: C:\path\to\project, --exclude "tests/*"
3. Claude Code 加载 skills/understand/SKILL.md 作为核心 prompt
4. SKILL.md 定义了一个 7 阶段流程:
Phase 0 → 预检(bash 命令)
Phase 1 → 分发 project-scanner agent(注入 agents/project-scanner.md)
Phase 1.5→ 批次计算(node 脚本)
Phase 2 → 分发 file-analyzer agent × N(注入 agents/file-analyzer.md)
Phase 3 → 分发 assemble-reviewer agent
Phase 4 → 分发 architecture-analyzer agent
↓ 注入 languages/java.md + frameworks/spring.md
Phase 5 → 分发 tour-builder agent
Phase 6 → 验证图谱
Phase 7 → 保存 + 启动 Dashboard
5. 每个 agent 都是一个 Claude Code 子会话
→ Claude 读 prompt → 调用脚本 → 读结果 → 产出 JSON
5. 共生关系
┌─────────────────────────┐
│ 57 个 .md 文档 │
│ (意图层) │
│ 定义: 谁、做什么、标准 │
└───────────┬─────────────┘
│ 编排、指导
▼
┌───────────────────┐ ┌──────────────────────────┐
│ Claude 模型 │◄──│ ts / js / py 代码 │
│ (推理引擎) │ │ (执行层) │
│ │ │ 做 LLM 不擅长的确定计算 │
│ 读 prompt │──►│ │
│ 做语义理解 │ │ tree-sitter 解析 AST │
│ 写描述文字 │ │ 文件枚举 + glob 匹配 │
│ 推断架构关系 │ │ 图谱合并 + 去重 │
└───────────────────┘ │ Dashboard 渲染 │
└──────────────────────────┘
三者缺一不可:
✗ 光有 md → LLM 不知道"Java 的抽象语法树长什么样"
✗ 光有代码 → 没法判断"这个 Controller 在图里应该叫什么名字"
✗ 光有 LLM → 没有 prompt 指导,分析质量差
6. 实例:--exclude 功能的改动
这次 PR 完美展示了共生关系------一个功能需要同时改 prompt 和代码:
| 文件 | 类型 | 改了啥 |
|---|---|---|
ignore-filter.ts |
ts 代码 | createIgnoreFilter 加 extraPatterns 参数 |
scan-project.mjs |
js 代码 | 解析 --exclude 参数、传给 filter |
SKILL.md |
prompt 文档 | 告诉 LLM 解析 $ARGUMENTS 中的 --exclude |
project-scanner.md |
prompt 文档 | 告诉 LLM 怎么把 --exclude 传给脚本 |
ignore-filter.test.ts |
测试代码 | 5 个新用例保证逻辑正确 |
代码负责 "能不能" (能正确匹配 glob 吗?能正确排除文件吗?)
Prompt 负责 "知不知道"(LLM 知道有这个参数吗?知道怎么传给脚本吗?)