一个规范的 .agents/ 目录,扇出到你所有的 AI 编程智能体。
位于 ~/.agents/ 这一规范目录的 Commons(共享配置区)保存着你共享的每一份配置的唯一真实副本——技能、指令、MCP 服务器、斜杠命令、子智能体、钩子。agent-sync sync 把它扇出到你安装的每一个智能体,共支持十二个:字节可以完全相同的地方用符号链接,不能相同的地方用渲染后的键级合并。没有状态文件,将来也不会有。
# Commons — 你共享的一切,只有这一份真实副本 ~/.agents/ ├── skills/ research/ tdd/ code-review/ ├── commands/ ship.md triage.md ├── agents/ reviewer.md ├── AGENTS.md 你的指令,只写一次 ├── mcp.json 标准 mcpServers 结构 └── hooks/ SessionStart.toml PreToolUse.toml
扇出
只改一个文件,每个智能体都能看到。
$ ls -l ~/.claude/skills/ research -> ../../.agents/skills/research tdd -> ../../.agents/skills/tdd code-review -> ../../.agents/skills/code-review $ ls -l ~/.pi/agent/skills/ research -> ../../../.agents/skills/research tdd -> ../../../.agents/skills/tdd code-review -> ../../../.agents/skills/code-review
加进 Commons 的技能,会以相对符号链接的形式出现在 Claude Code、pi、OpenClaw 和 Hermes 里——链接是计算出来的,不是手写的,所以整棵目录树被移动或在别处恢复之后依然有效。
Codex、opencode、oh-my-pi、Gemini CLI 和 Cursor 本来就会自己读取 ~/.agents/skills,所以 agent-sync 完全不为它们写技能链接——如果 Codex 或 Cursor 还在读取旧的扇出目录,sync 会把我们如今重复的链接从中清理掉。我们自己的链接一旦悬空就会被清理;指向别处的链接属于外来项(Foreign),一律不动。
两种机制
能用符号链接就用符号链接,不能用就渲染。
技能、指令、斜杠命令和子智能体在每个智能体那里都可以字节完全相同,所以它们是同一个文件被十处引用——漂移在构造上就不可能发生。MCP 服务器和钩子存在于智能体自己也拥有的文件里,而且格式各不相同,所以采用渲染加键级合并:你的其他键原样保留,只有 Commons 中点名的条目会被改写。
# ~/.agents/mcp.json — 只需写这一次
{
"mcpServers": {
"serena": {
"type": "stdio",
"command": "uvx",
"args": ["--from", "serena-agent", "serena"]
}
}
}
# ~/.codex/config.toml — 合并,而不是替换 model = "gpt-5.3-codex" # 原样保留 [mcp_servers.serena] command = "uvx" args = ["--from", "serena-agent", "serena"] [projects."/Users/you/work"] # 原样保留 trust_level = "trusted"
无状态
文件系统就是状态。
同类工具靠复制、渲染,并在你的配置旁边留一份记录来记住自己拥有什么。一旦记录与磁盘不一致,输掉的是你的手工修改。agent-sync 完全不留记录,因为归属可以直接从磁盘上读出来。
- 链接身份
- 解析进 Commons 的符号链接就是我们的:它会被规范化,悬空时会被清理。
- 名字身份
- 名字出现在 Commons 里的 MCP 服务器,或命令出现在 Commons 里的钩子,是我们的。同一文件里的其他名字都是外来项(Foreign),原样保留。
- 标记身份
- 完全由生成得到的文件带有一行注释声明这一点。有标记的是我们的;没有标记的出自别人之手。
克制
变体是特性,不是冲突。
$ agent-sync status
claude (.claude/skills) 12 linked
variant plannotator — left alone
variant-identical old-notes — identical to the
Commons, could be re-linked
foreign vendor-thing — not ours
mcp (mcp.json)
managed serena → claude
foreign xapi → claude — not in the
Commons — left alone
2 items need attention — run `agent-sync sync`.
遮蔽 Commons 条目的真实目录是一个变体(Variant):有意为之,永远被保留,只有当内容与 Commons 副本完全相同时才会被标出——去重因此是你主动的决定,而不是一次意外。
凡不是 agent-sync 写下的都是外来项(Foreign)——只报告,绝不修改。退出码就是契约:0 干净,1 出错,2 有事可做。
覆盖范围
十二个智能体,六大配置族。
| 智能体 | 技能 | 指令 | MCP | 命令 | 子智能体 | 钩子 |
|---|---|---|---|---|---|---|
| Claude Code | fan-out | import-line | key-merge | fan-out | fan-out | key-merge |
| Codex | native | symlink | key-merge (TOML) | fan-out | none | key-merge |
| opencode | native | symlink | key-merge | fan-out | fan-out | none |
| pi | fan-out | symlink | none | none | none | none |
| oh-my-pi | native | symlink | native | native | none | none |
| OpenClaw | fan-out | none | none | none | none | none |
| Hermes | fan-out | none | none | none | none | none |
| Gemini CLI | native | symlink | key-merge | render | none | key-merge |
| Cursor | native | none | key-merge | fan-out | none | none |
| Windsurf | none | symlink | key-merge | fan-out | none | none |
| Roo | none | rules-dir link | none | fan-out | none | none |
| Cline | none | none | key-merge | none | none | none |
sync 会把 agent-sync 如今重复的链接从中清理掉。安全
还没建立信任,也可以放心运行。
$ agent-sync sync --dry-run
dry run — no changes will be made
claude (.claude/skills)
missing research
missing tdd
mcp (mcp.json)
missing serena → codex — not in this agent's config yet
3 changes would be made.
- 先规划,后写入
- 每个配置族都在第一次写入之前完成勘察;Commons 里的任何错误都会报告完整清单并且什么也不写,所以一次配置失误绝不会留下一台半同步的机器。
- 第二次 sync 是空操作
- 连续运行两次,第二次会报告 Everything is up to date,文件字节完全相同。
- 每次写入都是原子的
- 私有临时文件、fsync、再原子重命名——目标路径先经符号链接解析,所以 dotfiles 的接线不会被破坏。
- 密钥不进 Commons,也不进终端
${env:VAR}在 sync 时解析,并从每一行输出中脱敏,Commons 因此始终可以提交进版本库。- 它向 CI 汇报
status --json与mcp list --json,退出码2专门表示「有事要做」。
安装
macOS、Linux 与 Windows。
# 预编译二进制 — 无需工具链,没有 postinstall 脚本 npm install -g agent-sync-sh # 或以 wheel 形式安装同一个二进制 pip install agent-sync-sh # 或从源码构建,需要 Rust 1.97+ cargo install agent-sync-sh # 或者先试用,无需安装 npx agent-sync-sh doctor uvx agent-sync-sh doctor # 或在 macOS 与 Linux 上,从本仓库自带的 tap 安装 brew tap agent-sync-sh/tap https://github.com/agent-sync-sh/agent-sync brew trust agent-sync-sh/tap brew install agent-sync # 然后,在一台你已经用了一段时间的机器上 agent-sync init
init 先创建 Commons,然后告诉你现有配置里有哪些可以接管——按配置族列出,并附上对应的命令。
边界
它不做什么。
不做跨机器同步。Commons 是一个普通目录——用 git 或 chezmoi 做版本管理。自建同步就意味着自建冲突解决,而这场仗 git 早已赢了。
不做记忆同步。智能体记忆不是一种有明确定义的产物,agent-sync 不会假装它是。
没有 GUI,没有守护进程,没有文件监听,也没有撤销——拒绝发生在写入之前,sync 和 adopt 都可以用 --dry-run 预览。它不负责安装技能——Commons 里有什么就扇出什么,不管是谁放进去的。也没有 mcp add,因为添加服务器不过是编辑一个有文档的标准文件。