安装
# macOS 和 Linux 的预编译二进制 — 无需工具链,没有 postinstall 脚本, # 因此可以离线安装,也可以在沙箱化的 CI 里安装 npm install -g agentstow # 或从源码构建 — 需要 Rust 1.97 或更新版本 cargo install agentstow
npm 包只是一个小启动器;真正的二进制按目标平台各打一个包,声明为可选依赖,npm 只会安装与你机器匹配的那一个。在没有预编译二进制的平台上,你会得到一条说明它找过什么、并指向 cargo install 的消息,而不是文件缺失的崩溃。
不支持 Windows。v1 只支持 macOS 和 Linux。让漂移不可能发生的符号链接扇出,前提是创建符号链接不需要特权。
最初五分钟
$ agentstow init
Created the Store at ~/.agents
skills/
commands/
subagents/
Found 6 agents: claude, codex, opencode, pi, oh-my-pi, gemini
3 skills not in the Store:
claude/skills/my-workflow
claude/skills/review-loop
codex/skills/notes
take one with `agentstow adopt <path>`
4 MCP servers not in the Store: serena, xapi, node_repl, computer-use
take them all with `agentstow mcp adopt --all`
init 回答的是一台用过的机器真正关心的问题:不是 agentstow 能做什么,而是你现有配置里有哪些可以被接管。把想共享的纳入(adopt)进来,然后 sync。
$ agentstow adopt ~/.claude/skills/my-workflow adopted my-workflow from claude into the Store (skills) $ agentstow mcp adopt --all adopted serena from claude scoped to claude — remove the allowlist in agentstow.toml to share it $ agentstow sync
adopt 把真实文件移进 Store,在原处留下一条链接。如果 Store 里已有同名且内容完全相同的条目,它会把重复副本折叠成链接;内容不同则拒绝并说明原因——决定丢弃哪一边不是 agentstow 该做的事。
Store
~/.agents/ ├── skills/<name>/ 每个技能一个目录 ├── commands/<name>.md Claude 方言的 markdown ├── subagents/<name>.md Claude 方言的 markdown ├── AGENTS.md 你共享的指令 ├── mcp.json 标准 mcpServers 结构 └── hooks/<Event>.toml [[hook]] 条目:command、matcher、timeout
Store 固定在 ~/.agents/。里面只放生态标准内容——没有任何 agentstow 专属的东西,正因如此其他工具才能直接读取它,opencode 和 oh-my-pi 已经在这么做。工具自身的配置单独放在 ~/.agentstow/agentstow.toml。
六大配置族
- 技能、命令、子智能体
- 符号链接扇出。每个条目在每个智能体目录里有一条规范的相对链接;我们的链接悬空即清理;其他一概不动。
- 指令
- 三种机制,因为智能体天生不同。整个文件可以归我们时用普通符号链接(Codex、pi、oh-my-pi、Windsurf)。Claude 的
CLAUDE.md里有你自己的内容,所以用一行导入行——agentstow 只确保@~/.agents/AGENTS.md存在,只增不改、幂等。Roo 会通配整个目录,所以用规则目录链接。 - MCP 服务器
- 渲染成每个智能体的方言并做键级合并。见下文。
- 钩子
- 命令钩子在
hooks/<Event>.toml里声明一次,按命令字符串合并进 Claude、Codex 和 Gemini:agentstow 只拥有命令与 Store 钩子匹配的那些数组元素,同一事件数组里其他工具的钩子原样保留。Codex 的信任哈希绝不写入——批准代码执行始终是你的决定。
已被其他工具占有的文件——比如 opencode 的 AGENTS.md 里 claude-mem 的样板内容——是一个冲突(Conflict):报告并指出解法,绝不覆盖。
归属,无需状态文件
agentstow 写下的一切,都必须在之后的运行中不查任何数据库就能认出是自己的。三种身份覆盖所有机制。
- 链接身份(Link identity)
- 解析进 Store 的符号链接是我们的——会被规范化,悬空时被清理。解析到别处的链接是外来项(Foreign),永远不碰。
- 名字身份(Name identity)
- 键级合并进共享文件的条目,名字出现在 Store 里才是我们的;对钩子而言,命令字符串就是名字。同一文件里陌生的名字都是外来项。有一个后果是刻意保留的:
sync从不删除 MCP 服务器,因为从 Store 里消失的名字与你手工添加的名字无法区分。删除要用agentstow mcp remove。 - 标记身份(Marker identity)
- 完全生成的文件带有一行注释声明这一点。这正是清理之所以安全的原因:删除带标记的文件,机器回到的是 agentstow 创建过的状态。同一路径上没有标记的文件出自别人之手。
读懂 status
| 状态 | 含义 |
|---|---|
| linked | 指向正确 Store 条目的规范链接。无事可做。 |
| missing | Store 里有,这个智能体还没有。 |
| stale | 我们的链接,但不是规范形式——会被重写。 |
| dangling | 我们的链接,指向的 Store 条目已不存在。会被清理。 |
| variant | 有意遮蔽 Store 条目的真实文件或目录。保留。 |
| variant-identical | 同上,但与 Store 副本字节完全相同——一个可以折叠掉的重复副本。 |
| foreign | 不是我们的。只报告,绝不修改。 |
| conflict | agentstow 本要写入的文件已被另一个工具占有。 |
0 干净,1 出错,2 有可执行的事。内容已分叉的变体和外来项都是尘埃落定的状态,不是待办工作,所以都不会让退出码变成 2。MCP 服务器
一份标准结构的 mcp.json 被渲染成每个智能体的方言:Codex 用带 http_headers 的 TOML 表;opencode 要 local/remote,命令压平成一个数组,env 改名 environment;Gemini 靠使用哪个 URL 键来区分 SSE 和可流式 HTTP;Windsurf 则叫它 serverUrl。
# ~/.agentstow/agentstow.toml [mcp.serena] agents = ["claude", "codex"] # 默认:每个具备能力的智能体 [mcp.node_repl.tweaks.codex] startup_timeout_sec = 120 # 只作用于 Codex
密钥在 Store 里写作 ${env:VAR},sync 时从环境变量解析,并从每一行输出中脱敏——Store 因此始终可以提交进版本库。如果解析后的密钥会落进一个他人可读的文件,agentstow 会明说。
agentstow mcp adopt claude/serena 把已有的服务器反向翻译进 Store,将智能体专属的旋钮变成微调(Tweak)。它会先验证结果:如果重新渲染无法复现你现有的配置,它会拒绝,而不是报告一个下次 sync 就会推翻的成功。
CLI
| 命令 | 作用 |
|---|---|
| init | 创建 Store 骨架,并报告有哪些可以纳入。 |
| sync | 把 Store 扇出到每个已安装的智能体。--dry-run 预览。 |
| status | 什么已同步、什么没有、什么不是我们的。--json。 |
| adopt <path> | 把现有配置吸收进 Store,留下一条链接。 |
| doctor | 已安装的智能体、Store 可用性、卫生警告。 |
| mcp list | Store 里的服务器及其在每个智能体中的状态。--json。 |
| mcp adopt | <agent>/<server>,或 --all。 |
| mcp remove | 把服务器从 Store 和每个智能体里删除。 |
agentstow.toml
可选,位于 ~/.agentstow/agentstow.toml。没有就用默认值。它永远不放进 Store,Store 因此只含生态标准内容。
[targets] cursor = false # 完全不碰这个智能体 [custom.myagent] # 注册表不认识的智能体 root = ".myagent" skills = ".myagent/skills" [mcp.heavy-server] agents = ["codex"]
多台机器
agentstow 刻意不做跨机器同步——那意味着要自建冲突解决,而这场争论 git 早已赢了。Store 是一个普通目录,用版本管理就好:
# 作为 git 仓库 cd ~/.agents && git init && git add . && git commit -m "my agent config" # 或使用 chezmoi chezmoi add ~/.agents ~/.agentstow
在第二台机器上,克隆下来并运行 agentstow sync。
词汇表
- Store
- 规范目录
~/.agents/,保存 agentstow 同步的一切的唯一真实副本。 - 目标(Target)
- 接收扇出的某个智能体的配置面。
- 扇出(Fan-out)
- 一个 Store 条目以符号链接形式落到每个目标里。
- 原生(Native)
- 直接读取 Store、因此不需要扇出的智能体。
- 变体(Variant)
- 目标里有意遮蔽 Store 副本、只对该智能体生效的真实文件或目录。一等公民,永远保留,绝不覆盖。
- 纳入(Adopt)
- 把目标里已有的真实文件或目录吸收进 Store,在原处留下链接。
- 外来项(Foreign)
- 目标里不属于 agentstow 的链接、文件或服务器条目。永远不碰,由
status列出。 - 冲突(Conflict)
- 占据了 agentstow 本要写入位置的外来文件——报告并指出解法,绝不覆盖。
- 渲染(Render)
- 把 Store 条目翻译成某个智能体的原生格式,并合并进该智能体的配置文件。
- 受管(Managed)
- 名字出现在 Store 里的条目:agentstow 在每个目标配置里都拥有它,以 Store 为准。
- 微调(Tweak)
- 合并进单个智能体渲染结果的按智能体附加项,在
agentstow.toml中声明,绝不放进 Store。 - 标记(Marker)
- 每个生成文件里的那一行注释,让文件无需状态文件即可被认出是 agentstow 的。