cd /news/developer-tools/re-use-your-skills-across-all-your-c… · home topics developer-tools article
[ARTICLE · art-107965] src=blog.herlein.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Re-use your skills across all your coding agents

Developer Greg Herlein released skills-mapper (sm), a Go binary that syncs a user's skill library from git into the per-agent directories used by Claude Code, Copilot, hax, pi, and oh-my-pi, eliminating the need to manually copy files. The tool addresses the fragmentation of skill storage across five agents, each with its own global and project-level skill directories, while preserving the portable SKILL.md format. Herlein, who maintains multiple coding agents to evaluate their harnesses, argues that packaging formats create walls between ecosystems, and sm provides a simple solution.

read10 min views1 publishedAug 23, 2026

I use more than one coding agent. Not because I’m indecisive — because I’m testing different agents - and learning how they work - and the field is moving fast. Seems like a new one every week! But every single one of them wants skills in its own directory, and I got tired of cp -r

and stale copies. So I wrote a tool.

It’s called sm — skills-mapper. It’s a small Go binary. It does exactly one thing: it takes your library of skills, keeps it fresh from git, and puts it where every agent you use expects to find it.

That’s it. That’s the whole tool. Let me explain why that’s worth writing.

The Problem: The Files Are Portable, The Location Isn’t #

A skill is not a complicated thing. It’s a directory with a SKILL.md

in it — YAML frontmatter with a required name

, an optional description

, then markdown. That’s the standard. Any agent that reads the format can use the file.

So the content is completely portable. Wonderfully so. You can hand a skill directory to Claude Code, to Copilot, to pi

, to a thing you wrote yourself last Tuesday, and they all understand it.

What is not portable is where it lives:

Agent Global directory
claude-code
~/.claude/skills
copilot
~/.copilot/skills
hax
~/.config/hax/skills
pi
~/.pi-go/skills
oh-my-pi
~/.config/agents/skills

Five agents, five directories, five slightly different opinions about where your stuff goes. And that’s just the global scope — each of them also has a project directory (.claude/skills

, .github/skills

, .agents/skills

, and so on) for repo-local skills.

Now layer packaging on top of that. If Claude Code is all you use, Claude Code plugins are genuinely a great answer — I’ve built and shipped one and I’d recommend them. But a Claude Code plugin does absolutely nothing for Copilot. Or hax

. Or the agent you’re writing yourself.

Every ecosystem grows its own packaging, and every packaging format is a wall.

Why I Suddenly Have Five Agents #

This wasn’t a hypothetical problem. I went looking for it.

Back in March I wrote that tooling is the new model — the models are good enough, the differentiator is the harness. If I actually believe that, then I should be trying harnesses. Which isn’t just the skills - it’s also the tool calling, and importanly, how the tools are called. So I set out to run new ones alongside Claude Code and pi

, and they are each interesting for completely different reasons:

** hax** — a terminal-native coding agent written in

C. A single native binary, small dependency set, starts instantly, uses almost no memory. It auto-discovers llama.cpp and other local servers without you configuring anything. It deliberately has

noplugin marketplace,

noIDE integration,

nopermission prompts. It streams markdown and tool results while respecting your terminal scrollback, and it gives you an inspectable transcript so you can see exactly what got sent to the model. It’s Unix philosophy applied to agents, and if you’re running local models on constrained hardware it’s a serious option.

** oh-my-pi** (

omp

) — a fork of Mario Zechner’s pi

, about 80,000 lines of Rust and TypeScript. This one goes the oppositedirection from hax: it’s “a coding agent with the IDE wired in.” Full LSP support so it actually understands code structure instead of grepping at it. Real DAP debugging — it drives

lldb

, dlv

, debugpy

rather than sprinkling print statements. 31 built-in tools, 60+ providers, subagent coordination with schema-validated results. It treats coding as an IDEproblem instead of a text problem, which is a thesis I find hard to argue with. It’s a “batteries included” version of pi.

** fx** — a tiny native agent written in

Zig. 6.39 MB. Cold start in 10 microseconds. Shell-like sparse output instead of a heavy TUI, minimal system prompts to keep token cost down, model and provider agnostic, and it compiles to WebAssembly so you can embed it in a browser with pluggable networking. It bills itself as being for research and for embedding in larger systems, and that’s the part I’m poking at.

C, Rust, Zig, TypeScript, and one I dabbled with in go. Nobody is converging on anything, and I think that’s healthy. Different constraints produce different tools. I want to run all of them against the same problems and see what actually holds up. Oh, and then compare it to Claude Code.

But here’s the thing — I can’t do a fair comparison if each agent has a different, drifted, hand-copied set of my skills. The agent is the variable I’m testing. The skills need to be the constant.

The Solution: Placement, Not Transformation #

The open standard for distributing skills already exists and it’s boring: a git repo of skill directories. Nothing agent-specific. Clone it, and the files are right there.

Which means the only real problem left is the last mile — getting one library into every agent’s expected location and keeping it current.

So that’s all sm

does. You write a manifest declaring your sources and your agents:

[skills]
gherlein = { git = "https://github.com/gherlein/skills", ref = "main" }

tools    = { git = "git@github.com:you/monorepo.git", ref = "v1.2.0", subdir = "skills" }

local    = { path = "~/dev/my-skills" }

[agents]
claude-code = true
copilot     = true
hax         = true
pi          = true
oh-my-pi    = true

[options]
prefix_on_collision = false

Then you run sm sync

and it does the boring, correct thing.

Three commands is the whole workflow:

sm init                 # write the starter manifest
$EDITOR ~/.config/skills-mapper/skills.toml
sm sync                 # fetch sources, place skills

What sync #

Actually Does

Five steps, in order:

flowchart LR
    F[freshen<br/>clone / git pull sources] --> D[discover<br/>find SKILL.md dirs]
    D --> R[resolve<br/>map source to target names]
    R --> L[link<br/>symlink into each agent]
    L --> C[reconcile<br/>remove stale links sm created]

freshen— clone each git source, orgit pull

if it’s already cached, and prune caches that aren’t in the manifest anymore. Skipped entirely on--dry-run

.discover— walk each source looking for directories that contain a standard-compliantSKILL.md

..git

,node_modules

,vendor

,dist

,build

and friends get ignored.resolve— compute thesource → target

name mapping.link— whole-directory symlinks into each enabled agent’s skills directory.** reconcile**— remove linkssm

previously made that nobody wants anymore.

Note the word symlink, repeatedly. sm

never copies and it never transforms. There is one canonical copy of every skill, in the clone cache, and every agent points at it. Update the source repo, run sync

, and all five agents get the new version simultaneously because they were all looking at the same file the whole time.

That’s the entire reason drift stops being possible.

The Opinionated Bits #

A tool this small only earns its keep if it’s opinionated about the right things. Three decisions I’d defend:

No plugin support. On purpose. This one surprises people. sm

will not consume a Claude Code plugin as a source. The reason is that the entire point of the tool is that skills follow one standard every agent reads. If I let you bridge Claude plugins in, Claude users get to consume skills Copilot users can’t — and I’ve just re-created the exact drift the tool exists to kill. Not doing it.

There’s a practical version of this trap too, and it bites people. Claude Code caches plugins under a versioned path: ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/skills/

. If you point a source at that path, it works great right up until Claude Code updates the plugin — at which point it installs into a new directory and your manifest keeps happily linking the stale one. Silently. Forever. Point at the plugin’s source repo instead and use subdir

.

Duplicate skill names fail loud. If two sources both ship a skill called debugging

, sm

stops and tells you. It does not pick a winner, and it does not quietly alphabetize its way into a decision you’ll discover three weeks later when the wrong skill fires. If you actually want both, set prefix_on_collision = true

and be explicit about it.

Silent success is the worst failure mode in tooling. A tool that guesses is a tool that lies to you.

It only ever touches links it made. There’s a state file at ~/.local/share/skills-mapper/state.json

tracking every link sm

created. If sm

finds a file in an agent’s skills directory that it didn’t put there, it skips it with a warning and never clobbers it. Your hand-written skills are safe. I have a healthy paranoia about tools that write into ~/.claude

unsupervised, and I wasn’t about to ship one.

Scope: Global and Project #

Two scopes. Global is the manifest at ~/.config/skills-mapper/skills.toml

, installing into each agent’s home directory. Project is a skills.toml

at your repo root, installing into the repo’s per-project agent directories.

Scope auto-detects — sm

walks up from your current directory looking for a skills.toml

, stopping before $HOME

. Find one, you’re in project scope. Don’t, you’re global. Force it with --global

or --project

when you need to.

The project scope is the one I’m most interested in long-term. A repo that ships its own skills.toml

teaches any agent that clones it how to work on that codebase. That’s a much better story than a README section titled “if you use Claude Code, do this.”

What Doesn’t Work Yet #

I built this over the last couple of days and the commit log says “interim commit” more often than I’d like. Being honest about the state of it:

add

, remove

, update

, and link

are stubs. They return a “not implemented” error. Right now you edit skills.toml

by hand and run sm sync

. That’s genuinely fine for how I use it — the manifest is six lines and I touch it maybe once a month — but it’s not done done.

What does work: init

, sync

(with --dry-run

and -v

), and list

. Which is the actual workflow. The rest is convenience.

The agent registry is also deliberately extensible — Codex, Amp, and OpenCode are the obvious next entries. Adding one is a table entry, not a refactor. That was the point.

Why Go, Again #

Because of course it’s Go. Single static binary, no runtime to install, no npm i -g

that fails E404 on some unpublished internal workspace package. (Ask me how I know. The prior-art tool in this space couldn’t be installed at all — unpublished scoped packages, a private registry token baked into its install script, and a TOML grammar living in a package that wasn’t checked out. Three separate installability failures before you get to whether the tool is any good.)

A tool whose entire job is “make setup easy across five agents” has no business being hard to install. make build

, one binary, done. I’ve made this argument before in a different context and I’ll keep making it.

Plus… I love go. ‘Nuff said.

Conclusion #

sm

is not clever. It’s a symlink manager with a manifest and a state file. The clever part — if there is one — is refusing to do more than that.

The bet underneath it is simple: skills as plain git repos of SKILL.md

directories is the standard that survives, because it’s the only one that doesn’t require every agent author to agree on anything beyond a file format they already agree on. Everything above that layer is packaging, and packaging is where lock-in lives.

I’ll report back once I’ve run hax, oh-my-pi, and fx against real work for a while — I have opinions forming about all three and they’re not the opinions I expected to have. But that’s a topic for another day.

If you’re running more than one coding agent, go grab it. It’s MIT, it’s small, and the whole thing is readable in an afternoon. Tell me what agent I should add to the registry.

If this is useful to you — or if you think the no-plugins stance is wrong and want to tell me why — drop me a note on LinkedIn: linkedin.com/in/gherlein.

── more in #developer-tools 4 stories · sorted by recency
── more on @greg herlein 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/re-use-your-skills-a…] indexed:0 read:10min 2026-08-23 ·