Agentstow: Canonical configs, fanned out to all your AI coding agents Agentstow, a new open-source tool, lets developers manage a single canonical store of AI coding agent configs—skills, MCP servers, instructions, and more—at ~/.agents/ and sync them across ten agents like Claude Code, Codex, Cursor, and pi via symlinks or key-merges, with no state file. The tool prunes dangling links, preserves foreign or variant configs, and uses exit codes 0, 1, and 2 to signal clean, error, and attention states. Canonical configs skills, MCP, memory, etc. , fanned out to all your AI coding agents. One Store at ~/.agents/ holds the single real copy of every config you share — skills, instructions, MCP servers, slash commands, subagents, hooks. agentstow sync fans it out to all ten agents you have installed: symlinks where the bytes can be identical, a rendered key-merge where they can't. There is no state file, and there never will be. the Store — one real copy of everything you share ~/.agents/ ├── skills/ research/ tdd/ code-review/ ├── commands/ ship.md triage.md ├── subagents/ reviewer.md ├── AGENTS.md your instructions, once ├── mcp.json standard mcpServers shape └── hooks/ SessionStart.toml PreToolUse.toml Fan-out Edit one file. Every agent sees it. php $ ls -l ~/.claude/skills/ research - ../../.agents/skills/research tdd - ../../.agents/skills/tdd code-review - ../../.agents/skills/code-review $ ls -l ~/.codex/skills/ research - ../../.agents/skills/research tdd - ../../.agents/skills/tdd code-review - ../../.agents/skills/code-review A skill added to the Store appears in Claude Code, Codex, Cursor and pi as a relative symlink — computed, not hand-typed, so the tree survives being moved or restored somewhere else. opencode and oh-my-pi already read ~/.agents/ themselves, so agentstow deliberately writes nothing for them. A link of ours that dangles gets pruned; a link pointing anywhere else is Foreign and is left alone. Two mechanisms Symlinked where it can be, rendered where it can't. Skills, instructions, commands and subagents can be byte-identical everywhere, so they are one file seen from ten places — drift is impossible by construction. MCP servers and hooks live inside files the agent also owns, in formats no two agents share, so those are rendered and key-merged: your other keys are preserved, and only the entries named in the Store are rewritten. ~/.agents/mcp.json — you write this once { "mcpServers": { "serena": { "type": "stdio", "command": "uvx", "args": "--from", "serena-agent", "serena" } } } ~/.codex/config.toml — merged, not replaced model = "gpt-5.3-codex" untouched mcp servers.serena command = "uvx" args = "--from", "serena-agent", "serena" projects."/Users/you/work" untouched trust level = "trusted" No state The filesystem is the state. Other tools in this space copy, render, and remember what they own in a record beside your configs. When that record disagrees with the disk, your hand-edits lose. agentstow keeps no record at all, because ownership is legible from the disk itself. - Link identity - A symlink that resolves into the Store is ours. It gets canonicalised, and pruned when it dangles. - Name identity - An MCP server, or a hook whose command appears in the Store, is ours. Every other name in the same file is Foreign and survives untouched. - Marker identity - A wholly generated file carries one comment line saying so. Marked is ours; unmarked was written by somebody else. Restraint Variants are a feature, not a conflict. bash $ agentstow status claude .claude/skills 12 linked variant plannotator — left alone variant-identical old-notes — identical to the Store, could be re-linked foreign vendor-thing — not ours mcp mcp.json managed serena → claude foreign xapi → claude — not in the Store — left alone 2 items need attention — run agentstow sync . A real directory shadowing a Store entry is a Variant : deliberate, preserved forever, and flagged only when its contents are identical to the Store copy, so you can dedupe on purpose rather than by accident. Anything agentstow did not write is Foreign — reported, never modified. Exit codes are the contract: 0 clean, 1 error, 2 something to do. Coverage Ten agents, six families. | Agent | Skills | Instructions | MCP | Commands | Subagents | Hooks | |---|---|---|---|---|---|---| | Claude Code | fan-out | import-line | key-merge | fan-out | fan-out | key-merge | | Codex | fan-out | 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 | | Gemini CLI | none | symlink | key-merge | render | none | key-merge | | Cursor | fan-out | 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 | none means that agent has no such config surface — not that agentstow skipped it. native means the agent reads the Store itself, so writing anything would only duplicate it. Safety Safe to run before you trust it. bash $ agentstow 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. - A second sync is a no-op - Run it twice and the second run reports Everything is up to date with the files byte-identical. - Every write is atomic - A private temp file, fsync, then an atomic rename — resolved through a symlinked destination, so dotfiles wiring survives. - Secrets stay out of the Store and out of your terminal ${env:VAR} is resolved at sync and redacted from every line of output, so the Store stays committable.- It reports to CI status --json and mcp list --json , with exit code 2 reserved for “there is something to do”. Install macOS and Linux. prebuilt binary — no toolchain, no postinstall script npm install -g agentstow or from source, needs Rust 1.97+ cargo install agentstow then, on a machine you have already been using agentstow init init creates the Store and then tells you what of your existing config it could take over — per family, with the command that would do it. Limits What it does not do. No cross-machine sync. The Store is an ordinary directory — version it with git or chezmoi. Building sync would mean building conflict resolution, and git already won that. No memory sync. Agent memory is not a defined artifact, and agentstow will not pretend otherwise. No Windows , no GUI, no daemon, no file watcher. It does not install skills — it fans out whatever is in the Store, whoever put it there. There is no mcp add , because adding a server is editing a documented standard file.