aagnostic-ai

One spec,
every AI CLI.

What your AI setup is for, why it drifts, and how to keep the workflow when you change the tool.

github.com/Chemaclass/agnostic-ai
One spec, every AI CLI · @Chemaclass
Part 1 · The workflow

What do you want
from an agent?

01It follows our conventions, not the internet's.
02It never does the dangerous thing. Not even once.
03It runs the boring checks. Every time.
04It repeats a workflow the same way we do.
05It reaches our systems: tickets, docs, databases.
One spec, every AI CLI · @Chemaclass
Part 1 · The workflow

Every outcome has a part.

Follow our conventionsinstructions · CLAUDE.md, AGENTS.md
Respect the guardrailsrules · scoped by path
Never the dangerous thingpermissions · allow and deny
Run the checks, alwayshooks · commands on events
Repeat a workflowskills · procedures on demand
Take a focused roleagents · their own context
Reach our systemsMCP servers · tools and data
One spec, every AI CLI · @Chemaclass
Part 1 · The workflow

Instructions and rules
are hints.

AGENTS.md always loaded We use conventional commits. Tests live next to the code.   rules/payments.md loaded in services/payments/ Money is integer cents. Never floats.

The model reads them. It follows them most of the time.

Keep them short. Every line competes for attention with the task itself.

One spec, every AI CLI · @Chemaclass
Part 1 · The workflow

Hooks and permissions
are not suggestions.

A hint
"Please run the formatter after editing."
"Do not read the .env file."
Followed most of the time.
A hook, a permission
After every edit, the formatter runs.
Reading .env is denied.
Every time. No model involved.

If it must happen, do not ask for it. Make it a hook.

One spec, every AI CLI · @Chemaclass
Part 1 · The workflow

Skills get things done.
Agents take a role.

skills
A procedure the agent loads when the task matches. Write the release notes. Add a migration.
agents
A role with its own context and tools. A reviewer that only reads. A researcher that only searches.
MCP
The door to your systems. Tickets, docs, the staging database.

The whole Claude version, explained: chemaclass.com/blog/inside-the-claude-folder

One spec, every AI CLI · @Chemaclass
Part 1 · The workflow

Yours, or the team's?

Global · your home folder
How you like your commits
Your personal skills
Follows you into every repo
Repo · committed
Team conventions and guardrails
Hooks everyone must run
Reviewed in PRs, like code

Anything the team depends on belongs in the repo.

One spec, every AI CLI · @Chemaclass
Part 2 · The drift

One file became a folder.

01Copilot first. One instructions file. Easy.
02Then Claude Code. Rules, skills, agents, hooks, MCP.
03Claude's layout. Claude's names. Claude's formats.
CLAUDE.md .mcp.json .claude/ ├── rules/ ├── skills/ ├── agents/ └── settings.json hooks, permissions
One spec, every AI CLI · @Chemaclass
Part 2 · The drift

Then Claude
gets expensive.

So you move to Gemini CLI. It ignores CLAUDE.md and your .claude/ folder. You start again with GEMINI.md.

One spec, every AI CLI · @Chemaclass
Part 2 · The drift

A colleague tries Codex.
So you port everything.

instructions CLAUDE.mdAGENTS.md
skills .claude/skills/.agents/skills/
agents .claude/agents/.codex/agents/*.toml
hooks settings.json.codex/hooks.json
MCP .mcp.json.codex/config.toml

Not a copy. A translation. Agents become TOML. Hooks change shape.

One spec, every AI CLI · @Chemaclass
Part 2 · A month later

Keep both copies.
Then they drift.

01Claude gets cheaper again. Half the team goes back.
02New skills land in .agents/skills/. Only there.
03A new formatter hook lands in .codex/hooks.json. Only there.
04Claude has never seen a month of skills, and never runs the hook.

No error. No warning. Same repo, different agents, different outcomes.

One spec, every AI CLI · @Chemaclass
Part 2 · Today

Nobody designed this.
It piled up.

CLAUDE.md AGENTS.md GEMINI.md .github/copilot-instructions.md .claude/ rules, skills, agents, hooks .agents/ skills .codex/ agents, hooks, MCP .gemini/ settings, commands

Four tools. Eight places. Every copy is one more place to forget an update.

And next month someone tries Cursor. Or whatever ships on Tuesday.

One spec, every AI CLI · @Chemaclass
Part 3 · One source

What if you kept
one directory
for every tool?

Written once. Owned by no tool. Each CLI still gets the files it expects.

One spec, every AI CLI · @Chemaclass
Part 3 · The obvious fix
ln -s AGENTS.md CLAUDE.md
ln -s ../.agents/skills .claude/skills
Works for
Instructions: same Markdown, other name
Skills: same SKILL.md
Nothing to install, nothing to run
Breaks on
Agents: Markdown for Claude, TOML for Codex
Hooks and MCP: other files, other schemas
Windows, where links check out as text

The hints link fine. The guarantees need translation.

One spec, every AI CLI · @Chemaclass
Part 3 · The trade-off
symlinks
sync
Same format in two tools
yes
yes
Agents, hooks, MCP per tool
no
translated
Drift check in CI
no
sync --check
Windows
plain text files
real files
Setup
nothing to install
one binary
Fresh clone
ready
needs sync, or a hook

If all your tools read the same format, use symlinks. Sync uses them too, where they are safe.

One spec, every AI CLI · @Chemaclass
Part 3 · How it works

One spec. One command. Native files.

.agnostic-ai/
AGNOSTIC_AI.md
rules/ · skills/ · agents/
hooks/ · settings/
mcps/
agnostic-ai
sync
okCLAUDE.md · .claude/
okAGENTS.md · .agents/ · .codex/
okGEMINI.md · .gemini/
ok.github/instructions/
25 targets in total

Left: the parts from part 1, written once. Right: what each tool reads, generated.

One spec, every AI CLI · @Chemaclass
Part 3 · Live

Demo

$agnostic-ai sync
init: claude, codex
sync, walk the tree
hand-edit, --check fails
One spec, every AI CLI · @Chemaclass
Part 3 · Should you use it

One tool, working alone?
You do not need this.

Pays off when
A second tool or person joins the repo
Hooks and agents must work in every tool
You review AI config in one place
The next switch is one line in targets:
Costs you
One more binary and one more step
Outputs are overwritten, edit the spec
Support varies by tool and part
Bad rules reach every tool just as fast
One spec, every AI CLI · @Chemaclass
Before Q&A

Questions for you.

01Which of your rules should be a hook?
02What belongs in your home folder, and what in the repo?
03Which of your skills would survive a tool switch?
04What should never be shared across tools?
One spec, every AI CLI · @Chemaclass
aagnostic-ai

Change the tool.
Keep the workflow.

github.com/Chemaclass/agnostic-ai
Q&A
One spec, every AI CLI · @Chemaclass
Backup

For the questions.

Import, scope, global, CI, git hooks, day to day.

One spec, every AI CLI · @Chemaclass
Backup · Demo recap

Two specs in. Ten native files out.

you write .agnostic-ai/ ├── AGNOSTIC_AI.md ├── rules/conventional-commits.md └── skills/write-tests.md agnostic-ai.yaml
sync writes CLAUDE.md · AGENTS.md · GEMINI.md .claude/rules/conventional-commits.md .claude/skills/write-tests/SKILL.md .agents/skills/write-tests/SKILL.md .gemini/skills/write-tests/SKILL.md .github/copilot-instructions.md .github/instructions/conventional-commits.instructions.md .github/skills/write-tests/SKILL.md

Codex and Gemini have no rules folder. The rule goes inside AGENTS.md and GEMINI.md instead.

One spec, every AI CLI · @Chemaclass
Backup · Best practices

Treat the spec like code.

01Commit the source. .agnostic-ai/ and agnostic-ai.yaml. Review specs in PRs.
02Edit the spec, never the output. The next sync overwrites it.
03Pick only the tools you use. The targets: list in agnostic-ai.yaml.
04Preview first. sync --dry-run before the first real sync.
05Choose where outputs live. Ignored by default, so a fresh clone runs sync.
One spec, every AI CLI · @Chemaclass
Backup · Already have .claude/?

Import it. Do not start over.

agnostic-ai init --from claude     # or codex, gemini, all
agnostic-ai sync --dry-run
agnostic-ai sync --backup          # .bak before overwriting
agnostic-ai revert                 # changed your mind

The Codex port from part 2, done in four commands. Your skills, agents and hooks move into .agnostic-ai/ once.

Review the imported specs before the first sync. Import from several tools, and the last one wins the shared instructions.

One spec, every AI CLI · @Chemaclass
Backup · Scope

Rules that live next to the code.

agnostic-ai new rule payments-context --scope services/payments
Claude Code.claude/rules/services/payments/payments-context.md
Codexservices/payments/AGENTS.md
Gemini CLIservices/payments/GEMINI.md
CopilotapplyTo: "services/payments/**"

Claude and Gemini load it when they touch those files. Codex loads it when launched there.

One spec, every AI CLI · @Chemaclass
Backup · Global

Your personal rules, on every project.

~/.agnostic-ai/ ├── AGNOSTIC_AI.md ├── rules/ ├── hooks/ └── skills/
agnostic-ai sync --global

User-level files for 22 of the 25 tools. Works from any directory.

Instructions, rules, hooks and skills only. Team conventions stay in the repo.

One spec, every AI CLI · @Chemaclass
Backup · CI

Drift fails the build.

Outputs committed
agnostic-ai sync --check
Non-zero exit on any missing or edited file.
Outputs ignored
agnostic-ai validate
agnostic-ai sync
A fresh checkout has nothing to compare.
- uses: chemaclass/agnostic-ai-action@v1
  with:
    command: check
One spec, every AI CLI · @Chemaclass
Backup · Git hooks

Sync on every branch switch.

agnostic-ai install-hook --shared   # pre-commit runs sync --check
#!/bin/sh
# .git/hooks/post-checkout
[ "$3" = "1" ] || exit 0   # branch switch, not a file checkout
agnostic-ai sync

post-checkout fires on checkout, clone and worktree add. A new worktree opens with its AI config ready.

One spec, every AI CLI · @Chemaclass
Backup · Day to day

Know where every file came from.

sync --watchre-syncs while you edit specs
statusspecs, targets, last sync
why <file>the spec and adapter behind any output
doctormissing and stale files, MCP binaries on PATH
packs addshare specs across repos, pinned by version
One spec, every AI CLI · @Chemaclass

0:30 · Name yourself, not the tool. The tool comes much later. Ask for hands: who used more than one AI coding tool this year? Keep your hand up if it was in the same repo. Do not comment, move on.

1:00 · Ask the question to the room before showing the list. Take two or three answers. Then reveal: most of what they said is here. This is the frame for the whole talk. We care about outcomes. The files come second.

1:00 · Read the left column, then the right. Seven parts, and every AI coding tool has some version of each. Names differ, the jobs do not. Next three slides: what each part is good at, in one sentence.

1:00 · Instructions are the always-on context. Rules are the same idea, loaded only where they matter, so the payments rules stay out of the frontend work. The key word is hints. The model can ignore them, and on a long session it sometimes does.

1:00 · The most important slide of part 1. Hooks are commands the tool runs on events: before a tool call, after an edit, at the end of a session. Permissions decide what the agent may touch at all. Neither depends on the model paying attention. Remember this, it comes back when we talk about drift.

1:00 · Skills are how the team's way of working becomes repeatable. Agents keep a side task out of the main context. MCP gives both of them reach. This is where most of the real investment goes: weeks of skills tuned to your codebase.

0:40 · Last piece of the map. Two levels. A hook that lives only in your home folder protects only you. Now we have the words. Let's see what happens to all of this when you change tools.

0:50 · Everyone in the room has lived this. Part 1's seven parts, now in one tool's folder. The point to land: all that value lives in a folder only one tool reads.

0:30 · No numbers. Everyone has their own pricing story, let them fill it in. Land the loss: weeks of skills and hooks, and the new tool reads none of it.

1:00 · Walk two rows, not five. Point at the labels: these are the parts from part 1. Instructions and skills copy over. Agents and hooks need translating. An afternoon of careful work, correct on the day you finish it.

1:00 · Nobody wants to throw away the work, so both copies stay. Read the beats as a timeline. Pause on 04 and call back to the hooks slide: a hook was the thing that must happen. On half the team it silently stopped happening. That is what drift costs. Not files. Outcomes.

0:50 · Let them scan the tree. Everyone recognises their own repo. No tool made a bad choice. Each picked its own layout, and your repo collected all of them.

0:30 · The question part 3 answers. Say it slowly, then stop for two seconds. Someone in the room is already thinking: symlinks.

0:50 · Take the idea seriously, most teams try it first, and it is half right. Notice which half breaks: agents and hooks, the parts that do the work. A link cannot translate. Windows: git with core.symlinks=false checks a link out as a text file holding the path.

1:00 · Be fair. Symlinks win the last two rows. They lose the moment a second format shows up, and a broken link never tells you. sync.shared-skills links skill folders whose bytes match.

0:50 · One sentence per column. The left side is the map from part 1. The right side is every folder from part 2. You edit the left. Then: let me show you, two minutes.

2:30 · Terminal font 20pt or larger. Prepare the repo before the talk: git init, agnostic-ai init (claude, codex), one rule, one skill already written. Live: agnostic-ai sync tree -a -I .git (point at .claude/ and .agents/, same skill, both tools) echo "hand edit" >> AGENTS.md agnostic-ai sync --check (exit 1, drift) agnostic-ai sync && agnostic-ai sync --check (green) If anything hangs past ten seconds, skip to the backup recap slide. The check is the beat that matters.

1:10 · Lead with the disqualifier, loudly. That is what makes the rest credible. Write CLAUDE.md and go home. Then both columns, quickly. The last con matters most: sync spreads a bad rule as fast as a good one. The spec still needs review.

1:00 · Read them, do not answer them. These are the questions I want back from the room. Every answer tells me what the spec should cover next. Leave this up for a few seconds before the closing slide.

0:20 · Call back to the first question: what do you want from an agent? That does not change when the tool does. Say the playground is linked from the repo, no install needed. Then ask for questions and leave this slide up. Backup slides follow for CI, monorepos, imports and hooks.

Only shown when a question needs it. Jump straight to the matching slide.

Fallback if the demo failed. The shared .agents/skills/ tree is the one Codex reads. Same folder from the story, now generated.

The last one is a real choice: ignored outputs keep the repo clean, committed outputs work for people without the CLI. The CI setup depends on it.

That afternoon of translation is now one import. Say the review warning out loud, it is the one people skip.

One spec, four scoping mechanisms. Be honest about Codex: it walks from the repo root down to the directory you launched it in, once per run. Start it at the root and the payments AGENTS.md never loads. Copilot applies applyTo in VS Code, JetBrains, the cloud agent and Copilot CLI, not in github.com chat. Aider, Zed, Junie, Crush, Jules and Antigravity skip scoped rules; their root rules still work. Worth it in monorepos, skip it in small repos.

The "yours or the team's" slide, as a command.

Committed outputs: check, never sync right before it, that would erase the evidence. Ignored outputs: validate and generate. The action installs the binary for you. Add --format=github for inline annotations.

Two hooks, two jobs. pre-commit catches drift before CI does. post-checkout matters when outputs are ignored: switch branches and the files follow. It saves agents running in fresh worktrees.

why is the favourite: point at any generated file and get the spec that wrote it.