agent-milestone
by TisseurdOr
README.md
# agent-milestone
> **MCP server 项目**(MCP-native):给 Agent 的对话/任务轨迹做 git 式版本控制——让每次和 Agent 的协作都能「记住、回看、分支、对比、重放、留档」。
## 项目介绍
agent-milestone 是一个 **MCP-native 的 Agent 轨迹版本控制系统**。
它把 Agent 的对话、工具调用和任务过程抽象成 Git 的同一套模型:
```text
step = 不可变对象(user / assistant / tool call / tool result)
step hash = SHA-256 内容寻址
parent_hash = 把 step 连成一条任务轨迹
milestone = 命名 ref,指向某个 step
branch = 另一个 ref,从某个 milestone 分叉
```
在这个模型上提供:
- **版本控制**:checkpoint / checkout / branch / diff / rollback / undo
- **轨迹重放**:replay dry-run,只输出工具调用计划,不执行工具
- **历史管理**:reflog / rename / delete / gc / prune
- **自动记录**:Claude Code SessionEnd hook 自动解析 transcript
- **Agent 接入**:MCP server,让 Agent 主动调版本控制工具
- **本地控制台**:GitHub 风格分支树、folder/branch/tag 图标、Diff 标签页
- **隐私优先**:本地 SQLite + 写入前密钥脱敏
可以这样理解:
> Git 管代码;agent-milestone 管 Agent 的对话、工具调用和决策轨迹。两者可以配合使用:Git 记录代码状态,agent-milestone 记录当时 Agent 做了什么、为什么这么做。
它适合:
- Claude Code / Codex / MCP Agent 的长期任务
- 多方案排查:同一问题分叉成不同 branch
- 复盘和审计:回到某个 milestone,看当时完整工具调用
- 安全回滚:移动 ref 指针,不删除历史 step
- 导出留档:把轨迹渲染成 Markdown 提交到 GitHub
## 为什么做
每次和 agent 对话、跑任务之后,都会忘记「当时到底在做什么」。想要一个长期的里程碑:能记住、能回看、能撤回、能导出留档。
## 定位
- **做什么**:MCP server,给 Agent 的任务轨迹做 git 式版本控制。
- 核心:`checkpoint` 存里程碑 / `checkout` 回看 / `export` 导出 markdown
- 版本控制:`branch` 分叉 / `diff` 轨迹对比 / `replay` 安全重放计划
- 管理:`list_milestones` / `rename` / `delete` / `gc` / `prune` / `reflog`
- **差异化**:Atlas 管代码(ACP-first),本服务管**对话轨迹**(MCP-native)。
- **不做什么**:多租户、云端同步——刻意不做,本地优先 = 隐私 + 工程判断。
## 核心模型(git 的同一套技巧)
不可变对象 + 指针:
- **step**:轨迹的最小单元——一条 user/assistant 消息、一次 tool 调用或 tool 结果。内容寻址(SHA-256)。
- 每个 step 通过 `parent_hash` 链接成一条链,链就是一次任务的轨迹。
- **milestone(checkpoint)**:一个命名指针,指向某个 step 的 hash。
- 分叉天然免费(branch 只是另一个指针);diff 便宜(走两条链回到分叉点)。
## 组件
| 文件 | 作用 |
|---|---|
| `store.py` | 存储层:SQLite + git 式模型,含 self-check |
| `server.py` | MCP server,暴露 checkpoint/checkout/export/branch/diff/replay 等工具 |
| `record.py` | SessionEnd hook,会话结束自动把 transcript 存档 |
| `view.py` | 只读查看器:把库里所有轨迹渲染成自包含 HTML(零依赖、浏览器直开) |
| `ui.py` | 本地 Web 控制台:分支树、Diff、Replay、Reflog、回滚/撤回、导出 |
| `redact.py` | 写入前做 API key / token / password / 连接串脱敏 |
| `tests/` | pytest:存储、分支、diff、replay、回滚、迁移、脱敏、transcript 解析 |
## 安装
```bash
cd agent-milestone
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]" # 运行 + pytest/ruff 开发依赖
# 或最小安装:pip install -e .
```
## 使用
### 路径 0:本地 Web 控制台(人用)
```bash
python ui.py
# 或安装后:
agent-milestone-ui
```
打开 `http://127.0.0.1:8765`,可以在浏览器里完成:
- 浏览所有 milestone / branch
- 查看完整轨迹
- 新建 checkpoint
- 从任意 ref 新建 branch
- 把 milestone 移动到某个 branch 文件夹
- 选择两个 ref 做 diff
- replay dry-run
- 回滚到指定 ref / 撤回上一个操作
- rename / delete
- 查看 reflog
- 导出 Markdown
- GC dry-run
### 路径一:自动记录(SessionEnd hook)
在 Claude Code 的 `settings.json` 配 SessionEnd hook 指向 `record.py`,每次会话结束自动把整段对话轨迹解析成 step 存库,无需手动操作:
```json
{
"hooks": {
"SessionEnd": [
{
"hooks": [
{ "type": "command", "command": "python3 /path/to/agent-milestone/record.py" }
]
}
]
}
}
```
### 路径二:主动版本控制(MCP 工具)
把 `server.py` 注册成 MCP server 后,agent 在对话里像开发者用 git 一样主动调。
**`checkpoint(name, steps) -> str`** —— 存档
- 输入:一个名字 + 一段轨迹(step 列表)
- 做什么:把轨迹存进 SQLite,给最后一步打上这个名字
- 返回:tip hash(前 12 位)
- 类比:`git commit -m "对账排查"`
**`checkout(name) -> list[dict]`** —— 回看 / 撤回
- 输入:里程碑名字
- 做什么:按名字找到指针,沿 `parent_hash` 往回走,还原整条轨迹
- 返回:轨迹(第一步 → 最后一步)
- 类比:`git checkout 对账排查`
**`export(name) -> str`** —— 导出留档
- 输入:里程碑名字
- 做什么:把轨迹渲染成 markdown
- 返回:markdown 文本,可直接 commit 到 GitHub
- 类比:`git log` 排版成文档
**`branch(name, from_ref) -> dict`** —— 分叉
- 类比:`git branch feature main`
- 分支只是另一个 ref,不会复制 step。
**`diff(left, right) -> dict`** —— 轨迹对比
- 沿两条链回溯到共同前缀,返回 fork hash、左独有、右独有 step 摘要。
**`replay(name) -> dict`** —— 安全重放
- 默认 dry-run,只返回工具调用计划,不执行任何工具。
- 需要真实执行时由调用方自己接 executor。
**`reflog(name?) -> list[dict]`** —— ref 历史
- checkpoint / branch / rename / delete / prune 全记录。
**`gc(dry_run=True)` / `prune(...)`** —— 存储回收
- `gc` 删除没有任何 ref 可达的 step。
- `prune` 按时间或保留数量清理旧 ref,再触发 gc。
**`rollback(name, to_ref)` / `undo_last(name)`** —— 回滚
- `rollback` 把 ref 指针移回指定 milestone/branch,不删除历史 step。
- `undo_last` 沿 reflog 撤回最近一次 checkpoint/rollback。
**`set_parent(name, parent_ref)`** —— 分支文件夹
- 把已有 milestone/branch 移动到某个 branch 文件夹下,控制台会按树形展示。
## 隐私与存储
- 默认写入前脱敏 API key、Bearer token、password、Redis/Postgres 连接串。
- DB 路径可通过 `AGENT_MILESTONE_DB` 覆盖。
- 不想同步 iCloud 查看页时设置 `AGENT_MILESTONE_AUTO_ICLOUD=0`。
## 存储
统一存到 `~/.claude/agent-milestone/milestones.db`(`store.py` 里的 `DEFAULT_DB_PATH`),`record.py` 和 `server.py` 都引用它。
## 验证
```bash
python store.py # 自检,应打印 self-check ok
python test_e2e.py # 端到端:checkpoint → checkout → export
python view.py # 生成 trails.html 轨迹查看页(浏览器直开,看所有里程碑+step)
```
## 操作手册
出问题先查 [RUNBOOK.md](./RUNBOOK.md),每条 = 症状 → 原因 → 处理。
## 状态(2026-10-08 阶段 2 + 本地控制台已跑通)
阶段 1 + 阶段 2 + 本地控制台已完整验证:store 自检、pytest、工具级端到端、以及新会话里 Agent 通过 MCP 实际调用核心工具。
### 已完成并验证 ✅
| 模块 | 说明 | 验证 |
|---|---|---|
| `store.py` | SQLite + git 式模型(内容寻址 step + 命名指针 milestone) | `python store.py` → self-check ok |
| `server.py` | MCP 工具 checkpoint/checkout/export/branch/diff/replay/rollback/undo/reflog/gc/prune | `test_e2e.py` 全通 |
| `record.py` | SessionEnd hook 自动存档真实对话 | 真实库累计 4800+ steps、十余个 milestone |
| `ui.py` | 本地 Web 控制台:分支树 / Diff tab / Replay / Reflog / 回滚 / 导出 | 浏览器实际点击验证通过 |
| `tests/` + `test_e2e.py` | pytest + 工具级端到端 | 16 pytest + e2e 通过 |
### 断点(阶段 1 收尾必做,全部关闭)
1. ~~DB 路径不合一~~ ✅ 统一到 `store.py` 的 `DEFAULT_DB_PATH`。
2. ~~`record.py` 真实 `.jsonl` 解析~~ ✅ 真实 transcript 解析 413 步、tool 关联 100%。
3. ~~`server.py` 注册后 agent 实际调用~~ ✅ 2026-09-08 新会话实际调用验证通过。
### 下一步(roadmap)
- [x] 阶段 2:branch / diff / replay / reflog / gc / prune
- [x] 本地 Web 控制台:分支树 / folder 图标 / Diff tab / 回滚 / 导出
- [ ] 阶段 3:真实 demo 视频、`pipx`/`uvx` 安装体验、发布到 PyPI
- [ ] 数据库加密 / retention 策略
## 铁律
阶段 1 没跑通之前,任何新功能都不许加。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues