Cairn
by Zrzzzz
README.md
# Cairn
> 跨 AI 编程工具、跨会话的项目进度中枢 —— 每个 agent、每个会话,干活前先读"走到哪了",干完自动堆上新的进度标记。
[](./LICENSE)
[](#开发)
[](#)
[](https://modelcontextprotocol.io)
[](#路线图)
Cairn 在 `~/.cairn/` 维护一份每项目的 `PROGRESS.md`,作为 Claude Code / Codex / Cursor 等 AI 编程工具共用的"事实来源"。
- **Web Console** 把当前任务(NOW)、下一步(NEXT)、里程碑时间线、Todos、各工具的 token / session 用量集中到一个深色仪表盘。
- **MCP server** 暴露 `cairn_read_progress` / `cairn_write_progress` / `cairn_add_activity` / `cairn_mark_milestone` 等工具,让 agent 一上来就读、干完就写。
- **SessionEnd hook**(目前覆盖 Claude Code)会话结束时自动追加进度。
- 文件级单一事实源:所有写入落到 `PROGRESS.md`,没有任何隐藏状态,能 `git diff` 看清楚。
当前为 MVP:单工具闭环(Claude Code)已通;Codex / Cursor 走日志扫描 + MCP 读写,未接 SessionEnd hook。详见 [路线图](#路线图)。
---
## 目录
- [核心理念](#核心理念)
- [快速上手](#快速上手)
- [CLI 命令](#cli-命令)
- [MCP 集成](#mcp-集成)
- [数据布局](#数据布局)
- [架构](#架构)
- [开发](#开发)
- [路线图](#路线图)
- [贡献](#贡献)
- [License](#license)
---
## 核心理念
1. **进度是文档,不是数据库。** `PROGRESS.md` 用 YAML frontmatter + 几节 Markdown 描述「正在做 / 接下来 / 里程碑 / Todos / 活动流」。AI 工具可以直接读,人也可以直接编辑。
2. **跨工具共享同一份记忆。** Claude Code 干一半,明天用 Codex 继续 —— 只要它接了 Cairn MCP,第一件事就是 `cairn_read_progress`,自然衔接。
3. **会话结束自动落账。** SessionEnd hook 抽 transcript 要点写进活动流,不靠用户记得。
4. **派生数据隔离。** Token / session 统计放在 `db.sqlite` 里,是缓存,可以随便删 —— `PROGRESS.md` 才是源。
## 快速上手
> 需要 Node ≥ 18,推荐 pnpm。
```bash
# 克隆并构建
git clone https://github.com/Zrzzzz/Cairn.git
cd Cairn
pnpm install
pnpm build
# 把当前项目接入 Cairn
node dist/cli/index.js init ~/dev/my-project
# 把 Cairn 注册到 Claude Code / Codex / Cursor 的 MCP 配置里
node dist/cli/index.js mcp-install --all
# 启动 Console(默认 http://127.0.0.1:3737)
node dist/cli/index.js serve
```
打开浏览器访问 `http://127.0.0.1:3737`,就能看到这个项目和其它已接入项目的进度仪表盘。
需要后台常驻:
```bash
node dist/cli/index.js serve -d # daemon 模式
node dist/cli/index.js status # 查看 pid / url
node dist/cli/index.js stop # 停掉后台
```
## CLI 命令
| 命令 | 作用 |
|---|---|
| `cairn init [path]` | 接入项目:写 `~/.cairn/projects/<id>/PROGRESS.md`、注入 `CLAUDE.md` / `AGENTS.md` / `.cursorrules`、注册 Claude Code SessionEnd hook |
| `cairn serve [-p PORT] [--tools ...] [-d]` | 启动 Console Web + SSE;`--tools` 选要扫的工具日志,省略走交互式 |
| `cairn stop` / `cairn status` | 管理后台 daemon |
| `cairn hook session-end` | Claude Code SessionEnd 调用:把会话总结追加到当前项目的活动流 |
| `cairn mcp` | 在 stdio 上启动 MCP server,供 agent 接入 |
| `cairn mcp-install [-t ...\|-a] [-s user\|project]` | 把 Cairn MCP 注册到 Claude Code / Codex / Cursor 的配置里,省略 `-t` 走交互式 |
| `cairn mcp-uninstall [-t ...\|-a]` | 反操作 |
`cairn init` 关键 flag:
- `--id <slug>` 覆盖项目 id(默认从目录名 slugify)
- `--name <name>` 友好名称
- `--tool claude-code,codex,cursor` 一次性接入多个工具
- `--no-hook` 不写 Claude Code 的 SessionEnd hook
- `--force` 覆盖已有 `PROGRESS.md`
## MCP 集成
跑过 `cairn mcp-install` 之后,agent 在每个新会话开始时应当:
1. 调 `cairn_list_projects` 找到当前 cwd 对应的项目(或显式 `project` 参数)。
2. 调 `cairn_read_progress` 读取 Now / Next / Milestones / Todos。
3. 干活过程中用 `cairn_add_activity` / `cairn_mark_milestone` 回写。
可用工具:
| Tool | 说明 |
|---|---|
| `cairn_list_projects` | 列出已接入项目(带 cwd 命中标记) |
| `cairn_read_progress` | 读 PROGRESS.md(结构化输出 frontmatter + sections) |
| `cairn_write_progress` | 部分更新 Now / Next / Milestones / Todos |
| `cairn_add_activity` | 追加一条活动流 |
| `cairn_mark_milestone` | 把里程碑标成 done / current / blocked / next |
| `cairn_list_todos` | 列出未完成 Todos |
在 `CLAUDE.md` / `AGENTS.md` 里建议加这段提醒(`cairn init` 已自动写入):
```md
## Cairn 进度
本项目接入了 Cairn 跨工具进度中枢。会话开始前,请先通过 MCP 工具
`cairn_read_progress({ project: "<project-id>" })` 读取当前进度。
推进工作后,用 `cairn_add_activity` / `cairn_mark_milestone` / `cairn_write_progress` 回写。
```
## 数据布局
```
~/.cairn/
├── projects/
│ └── <project-id>/
│ └── PROGRESS.md # 单一事实源
├── db.sqlite # 派生缓存:token / session 统计
└── config.json
```
`PROGRESS.md` 示例:
```md
---
schema: cairn/v1
id: my-project
name: My Project
repo: ~/dev/my-project
tools: [claude-code, codex]
last_activity: 2026-06-19T20:11:00.000Z
created: 2026-06-18T09:30:00.000Z
---
## Now
把仪表盘的数据抓取从 fetch 换成 SWR + suspense
## Next
迁移登录页 · 灰度 10% 用户
## Milestones
- [x] 设计系统 — 6/02
- [x] 认证流 — 6/10
- [~] 仪表盘 — 进行中
- [ ] 上线
## Todos
- [ ] 设计 token 颜色梳理 <!-- src:web 2026-06-19 -->
- [x] 接通 SSE 实时刷新
## Activity
- 2026-06-19T20:11:00.000Z · claude-code · 把 ProjectCard 重写为时间线版
```
`db.sqlite` 只是用来撑仪表盘的派生数据,删了 `cairn serve` 下一次扫描会重建。
## 架构
```
┌───────────────────────────────────────────────────────────┐
│ ~/.cairn/projects/<id>/ │
│ PROGRESS.md │ <- 单一事实源
└────^──────────────────────────────────────^───────────────┘
│ 文件监听 (chokidar) │ 读 / 写
│ │
┌────┴──────────────┐ ┌──────────────────┴──────────────┐
│ cairn serve │ │ cairn mcp (stdio) │
│ · Hono + SSE │ │ · Claude Code / Codex / Cursor │
│ · React Console │ │ · cairn_read_progress 等 │
└────────^──────────┘ └─────────────────────────────────┘
│ HTTP / SSE
│
浏览器 Dashboard
```
- **后端**:`src/web` 用 Hono 起 HTTP 服务,文件变更走 chokidar → SSE 推到前端。
- **MCP server**:`src/mcp` 走 `@modelcontextprotocol/sdk` 的 stdio transport。
- **派生统计**:`src/core/jsonl.ts` / `codex.ts` / `cursor.ts` 定时扫各工具的本地 transcript,把 token / session 聚合写入 `db.sqlite`。
- **前端**:`ui/` 是独立的 Vite + React 工程,构建产物被 `cairn serve` 直接 mount。
## 开发
```bash
pnpm install
# 前端热更(默认 http://localhost:5173)
pnpm dev:ui
# 后端 + MCP 热更
pnpm dev:server
# 一键类型检查
pnpm typecheck
# 全量构建
pnpm build
```
代码组织:
```
src/
├── cli/ # cairn 子命令:init / serve / hook / mcp / mcp-install ...
├── core/ # 进度文件解析、文件监听、各 AI 工具日志扫描
├── hook/ # SessionEnd hook 实现
├── mcp/ # MCP server + tools
├── shared/ # 前后端共享类型 (api.ts)
└── web/ # Hono routes + SSE
ui/ # React + Vite 控制台
templates/ # PROGRESS.md / CLAUDE.md / AGENTS.md / .cursorrules 模板
scripts/ # 构建辅助
```
详细贡献流程见 [CONTRIBUTING.md](./CONTRIBUTING.md)。
## 路线图
- [x] PROGRESS.md schema + 解析器
- [x] CLI `init` / `serve` / `mcp` / `mcp-install`
- [x] React Console(时间线 / 当前任务高亮 / 工具筛选 / 搜索)
- [x] Claude Code SessionEnd hook
- [x] Claude Code / Codex / Cursor 日志扫描
- [ ] Codex / Cursor 的"会话结束"等价 hook
- [ ] 多项目里程碑联动视图
- [ ] 远程 Console(认证 + 多用户)
- [ ] `PROGRESS.md` schema 版本号兼容机制
## 贡献
欢迎 issue / PR。开始之前请读一下 [CONTRIBUTING.md](./CONTRIBUTING.md) 和 [行为准则](./CODE_OF_CONDUCT.md)。
## License
[MIT](./LICENSE) © 2026 Zrzzzz
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues