内容
# 🧭 海图(Hải Đồ)
[](https://github.com/lebac-svg/haido/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/haido)
[](LICENSE)
> **AI 编程代理的日志记录** — 项目记忆锚定在代码中,感知代码自身的新旧程度。
AI 编程代理会遗忘。上下文窗口被填满,会话结束,每个艰难的决定 —— *"金额是整数美分,不会是浮点数"*, *"我们尝试过 X 库,它破坏了 Y"* —— 都蒸发了。惯例文件(`CLAUDE.md`,规则,记忆库)试图提供帮助,但它们会悄悄地失效:没有人知道哪些笔记仍然与代码匹配。
**海图(haido)** 解决了这个问题。每个笔记都被 **锚定** 在特定的函数或文件中,并带有内容指纹。当代码更改时,笔记会 **提醒** —— 它出现在审查队列中,显示旧/新指纹,得到确认、移动或退休。笔记在代理 **触及相关文件时** 被注入到上下文中,精确到 token 预算。无需云服务,无需嵌入,无需大型语言模型猜测 —— 只需一个 SQLite 文件和诚实的哈希。
*Hải Đồ* 是越南语中航海图的含义;这个日志记录工具让船舶的知识保持诚实。
## 使用感受
```text
$ (代理编辑 src/board.ts)
⚠ haido: 笔记 [m_x1] 锚定在 `src/board.ts#Board.move` 刚刚发生漂移
因为这个更改 —— 如果它不再成立,请重新锚定或更新笔记。
$ (代理读取 src/pricing.ts — 钩子注入,未被提示)
### 相关记忆(haido)
- ⛔ 不变式 [m_9k] `src/pricing.ts#computeTotal`
金额是整数美分 —— 不会是浮点数。原因:浮点数舍入误差导致发票损坏。
```
代理不必 **记住要记住**。会话开始时,`sessionStart` 注入压缩的项目地图和现行规则;触及文件时,注入该文件周围的锚定笔记(每个会话一次);编辑代码使笔记失效时,立即触发警告。
## 查看实时演示
`haido viz --live` 在 127.0.0.1 上提供地图,并将每个更改流式传输到打开的页面:
新文件生长,正在编辑的文件发光并冷却,笔记在保存时闪烁黄色。

*桥梁,头部记录在这个仓库中:2D 地图及其仪表 —
3D 球体、活动带、检查器(结构 + 选择的笔记)和航海日志。
青色 = 代理编辑 `src/viz/*`,新文件生长,然后人类编辑漂移笔记
`m_boot_010` (黄色闪烁,记录在活动带中)并在恢复时愈合。*
```bash
haido viz --live --open # 在第二个显示器上保持打开
```
## 安装
需要 Node ≥ 22.12。建议全局安装 —— 钩子调用 `haido` 从您的 PATH 中。
### 与 Claude Code 结合使用(钩子 + MCP —— 全套体验)
```bash
npm install -g haido
cd /your/project
haido init # 创建 .haido/,索引代码,挖掘 git 协变
haido install claude-code # 将钩子写入 .claude/settings.json + MCP 写入 .mcp.json
# 重启您的 Claude Code 会话 —— 它现在有记忆
```
从那时起,自动执行:项目地图在会话开始时注入(并在每次上下文压缩后重新简报),锚定笔记在触及文件时出现,编辑使笔记失效时立即警告,在会话结束时提供一次反思提示。标志:`--global` 将钩子写入 `~/.claude/settings.json` 以供所有项目使用;`--command node /path/to/dist/cli.js` 覆盖源构建的启动器。
### 与 Claude Desktop 结合使用(仅 MCP - 按需召回)
```bash
cd /your/project
haido install claude-desktop # 注册 MCP 服务器 'haido-<project>' 固定到此仓库
# 重启 Claude Desktop
```
桌面版没有钩子,因此不会自动注入 —— 而是询问:
*"调用 `map_overview`" · *"回忆 `src/pricing.ts` 周围的笔记"* · *"记住这个决定:…"* · *"在 `stale_memories` 中有什么?"*。每个项目都有自己的命名服务器。
维护:添加 `.haido/` 到 `.gitignore` (init 提醒您)—— 数据库是每个机器的;
知识通过存储库的记忆包随项目一起旅行。
从源代码而不是 npm:`git clone https://github.com/lebac-svg/haido.git && cd haido && npm install && npm run build`,
然后在 `haido` 的位置使用 `node /path/to/haido/dist/cli.js` (并将
`--command node /path/to/haido/dist/cli.js` 传递给安装程序)。
## 组件
| 界面 | 您获得的内容 |
|---|---|
| **钩子** (Claude Code) | 自动注入:项目地图在会话开始时(在每次压缩后重新简报);触摸文件时锚定笔记;编辑使笔记失效时立即警告;在繁忙的会话中未记录任何内容时提供一次反思提示 |
| **MCP 工具** | `recall` · `remember` · `find_related` · `map_overview` · `stale_memories` · `reanchor` |
| **CLI** | `init · index [--watch] · serve · install · remember · recall · related · overview · stale · reanchor · export · import · viz [--live] · stats · doctor` |
| **`haido viz`** | 自包含的桥梁控制台(一个 HTML 文件,零依赖):2D 地图 — 文件由目录着色,导入/协变链接带有悬停聚光灯,记忆为钻石卫星 — 周围有仪表:旋转 3D 球体,检查器(每个符号的结构 + 锚定笔记)和航海日志 |
| **`haido viz --live`** | 相同的桥梁,作为一个活着的东西,在 127.0.0.1 上提供:新文件生长,正在编辑的文件发光(青色 = 您的代理,白色 = 人类),笔记在编辑使它们漂移时闪烁黄色,活动带记录每个事件的时间戳 — 实时观察您的代理工作 |
| **记忆包** | `export/import --pack`: 每个笔记一个 Markdown 文件,提交到 git — 知识通过存储库旅行,并在 PR 中审查;记录的指纹在机器间传递新鲜度 |
## 新旧程度的工作原理(核心技巧)
1. `remember` 捕获 **规范化内容哈希** 的锚定符号/文件
(注释和空格被剥离 —— `prettier` 运行从不引起狼嚎)。
2. 每个索引传递都会重新检查所有锚点与当前代码:
- 哈希匹配 → **新鲜** (恢复自动治愈漂移笔记)
- 哈希不同 → **漂移** ,带有旧/新指纹供审查
- 目标消失但存在相同的双胞胎 → **移动** :锚点跟随重命名/移动静默
- 目标永远消失 → **缺失** ,带有候选建议
3. 具有任何漂移/缺失锚点的笔记进入审查队列:`confirm`
(仍然正确 — 捕获新哈希),`move`,或 `retire`。没有任何东西会默默地腐烂。
卫生在写入时强制执行:每个笔记都需要一个 **原因** 和 **≥ 1 个锚点** ,每个笔记一个事实
(≤ 700 个字符),重复项会被标记。笔记记录 **决定,不变式,注意,约定** —— 从不源自代码的可推导事物。
## 命令参考
| 命令 | 它执行的操作 |
|---|---|
| `haido init` | 创建 `.haido/`,索引存储库,挖掘 git 协变,编写一个启动器 `haido.toml` |
| `haido index [--watch]` | 重新索引更改的文件 + 调和锚点;`--watch` 在每次保存时重新运行 |
| `haido install claude-code [--global] [--command …]` | 连接钩子和 MCP 到 Claude Code(幂等,备份它所触摸的内容) |
| `haido install claude-desktop` | 为 Claude Desktop 注册每个项目的 MCP 服务器 |
| `haido viz [--out <file>] [--open]` | 编写自包含的地图 HTML(默认 `.haido/map.html`) |
| `haido viz --live [--port <n>] [--open]` | 在 127.0.0.1 上提供地图并将存储库更改流式传输到其中(默认端口 6160) |
| `haido remember --type <t> --title <…> --body <…> --why <…> --anchor <sym:qname\|file:path>` | 记录笔记;类型:`decision · invariant · gotcha · convention · todo` |
| `haido recall [query] [--file <path>] [--symbol <qname>] [--budget <tokens>]` | 文件/符号/自由文本查询的排名笔记 |
| `haido related <file-or-qname> [--limit <n>]` | 与目标最相关的文件(导入,协变,同目录) |
| `haido overview [--budget <tokens>]` | 项目地图 + 现行规则 — 新会话应首先阅读的内容 |
| `haido stale` | 审查队列:锚定代码更改的笔记,带有旧→新 token 差异 |
| `haido reanchor <id> --confirm` \| `--retire` \| `--move <anchorId> --to <target>` | 解析漂移笔记:仍然正确 / 不再正确 / 代码已重定位 |
| `haido export --pack <dir>` · `haido import --pack <dir>` | 记忆包:每个笔记一个可审查的 `.md`,通过 git 旅行 |
| `haido export --viz <file>` | 原始地图 + 记忆 JSON 快照(稳定格式) |
| `haido stats` | 自用指标:按类型/新鲜度记忆,锚点,会话注入的笔记 |
| `haido serve [--root <path>]` | 手动运行 MCP stdio 服务器(安装程序为您配置) |
| `haido doctor` | 诊断工作区:node,git,db,配置 |
每个命令都回答 `--help` 以及它的标志。
## 配置(`haido.toml`,与您的存储库一起提交)
```toml
[index]
exclude = ["generated/**"] # 在内置跳过(node_modules,dist,…)之上
[cochange]
min_together = 3 # 文件必须一起更改 ≥ N 次提交才能成为一条边
[recall]
budget_tokens = 800 # 钩子注入预算每个文件
[ui]
lang = "zh" # 输出语言:"zh"(默认)| "vi"
```
TypeScript/TSX/JS + Python 是符号索引的;markdown/JSON/YAML/TOML 是文件级
锚定目标(是的,您可以将决策锚定到您的规范)。100% 本地:无网络
调用,无遥测。
## 设计文档
英文概述: [docs/DESIGN.md](docs/DESIGN.md) · 工程宪法:
[docs/QUALITY.md](docs/QUALITY.md) · 完整设计文档(越南语原文 — 该
项目由越南语团队构建,haido 的存储库中的记忆包
[docs/memory/](docs/memory/) 是狗粮的一部分): [docs/vi/](docs/vi/)
## 状态
已在 npm 上发布(`npm install -g haido`)。核心循环在实时
Claude Code 会话中验证(钩子金丝雀 + MCP 环行),
自托管在此存储库上 — 存储库中的记忆包和 README GIF
都是该狗粮的产物。路线图:doc↔code "spec-of" 边缘,地图的语义缩放,
用于 Claude Desktop 的 `.mcpb` 包。
## 许可证
MIT