Agentstow: Canonical configs, fanned out to all your AI coding agents

soulmachine1 pts0 comments

agentstow — Canonical configs, fanned out to all your AI coding agents

Skip to content

Canonical configs (skills, MCP, memory, etc.), fanned out to all your AI coding agents.

One Store at ~/.agents/ holds the single real<br>copy of every config you share — skills, instructions, MCP servers, slash<br>commands, subagents, hooks. agentstow sync fans it out to all ten agents<br>you have installed: symlinks where the bytes can be identical, a rendered key-merge<br>where they can't. There is no state file, and there never will be.

# the Store — one real copy of everything you share<br>~/.agents/<br>├── skills/ research/ tdd/ code-review/<br>├── commands/ ship.md triage.md<br>├── subagents/ reviewer.md<br>├── AGENTS.md your instructions, once<br>├── mcp.json standard mcpServers shape<br>└── hooks/ SessionStart.toml PreToolUse.toml

Read the docs<br>View on GitHub

Fan-out

Edit one file. Every agent sees it.

$ ls -l ~/.claude/skills/<br>research -> ../../.agents/skills/research<br>tdd -> ../../.agents/skills/tdd<br>code-review -> ../../.agents/skills/code-review

$ ls -l ~/.codex/skills/<br>research -> ../../.agents/skills/research<br>tdd -> ../../.agents/skills/tdd<br>code-review -> ../../.agents/skills/code-review

A skill added to the Store appears in Claude Code, Codex, Cursor and pi as a<br>relative symlink — computed, not hand-typed, so the tree survives being moved or<br>restored somewhere else.

opencode and oh-my-pi already read ~/.agents/ themselves, so<br>agentstow deliberately writes nothing for them. A link of ours that dangles gets<br>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<br>they are one file seen from ten places — drift is impossible by construction. MCP<br>servers and hooks live inside files the agent also owns, in formats no two agents<br>share, so those are rendered and key-merged: your other keys are preserved, and only<br>the entries named in the Store are rewritten.

# ~/.agents/mcp.json — you write this once<br>"mcpServers": {<br>"serena": {<br>"type": "stdio",<br>"command": "uvx",<br>"args": ["--from", "serena-agent", "serena"]<br># ~/.codex/config.toml — merged, not replaced<br>model = "gpt-5.3-codex" # untouched

[mcp_servers.serena]<br>command = "uvx"<br>args = ["--from", "serena-agent", "serena"]

[projects."/Users/you/work"] # untouched<br>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<br>beside your configs. When that record disagrees with the disk, your hand-edits lose.<br>agentstow keeps no record at all, because ownership is legible from the disk<br>itself.

Link identity<br>A symlink that resolves into the Store is ours. It gets canonicalised, and<br>pruned when it dangles.

Name identity<br>An MCP server, or a hook whose command appears in the Store, is ours. Every<br>other name in the same file is Foreign and survives untouched.

Marker identity<br>A wholly generated file carries one comment line saying so. Marked is ours;<br>unmarked was written by somebody else.

Restraint

Variants are a feature, not a conflict.

$ agentstow status<br>claude (.claude/skills) 12 linked<br>variant plannotator — left alone<br>variant-identical old-notes — identical to the<br>Store, could be re-linked<br>foreign vendor-thing — not ours

mcp (mcp.json)<br>managed serena → claude<br>foreign xapi → claude — not in the<br>Store — left alone

2 items need attention — run `agentstow sync`.

A real directory shadowing a Store entry is a Variant :<br>deliberate, preserved forever, and flagged only when its contents are identical<br>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<br>codes are the contract: 0 clean, 1 error,<br>2 something to do.

Coverage

Ten agents, six families.

AgentSkills<br>InstructionsMCP<br>CommandsSubagents<br>Hooks

Claude Codefan-outimport-linekey-mergefan-outfan-outkey-merge<br>Codexfan-outsymlinkkey-merge (TOML)fan-outnonekey-merge<br>opencodenativesymlinkkey-mergefan-outfan-outnone<br>pifan-outsymlinknonenonenonenone<br>oh-my-pinativesymlinknativenativenonenone<br>Gemini CLInonesymlinkkey-mergerendernonekey-merge<br>Cursorfan-outnonekey-mergefan-outnonenone<br>Windsurfnonesymlinkkey-mergefan-outnonenone<br>Roononerules-dir linknonefan-outnonenone<br>Clinenonenonekey-mergenonenonenone

What each agent supports, and by which mechanism. none means that<br>agent has no such config surface — not that agentstow skipped it. native<br>means the agent reads the Store itself, so writing anything would only duplicate<br>it.

Safety

Safe to run before you trust it.

$ agentstow sync --dry-run<br>dry run — no changes will be made

claude (.claude/skills)<br>missing research<br>missing tdd<br>mcp (mcp.json)<br>missing serena → codex — not in this agent's config yet

3 changes would be made.

A second sync is a no-op<br>Run it twice and the second run reports Everything is up to date<br>with the files byte-identical.

Every write is...

agents skills store agentstow claude agent

Related Articles