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. 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 https://github.com/gherlein/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 https://blog.herlein.com/post/unifi-fixed-hosts-skill/ 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 https://blog.herlein.com/post/dot-agents/ — 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 no plugin marketplace, no IDE integration, no permission 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 opposite direction 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 IDE problem 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 A git repo of SKILL.md directories gherlein = { git = "https://github.com/gherlein/skills", ref = "main" } Only a subdirectory of a repo tools = { git = "git@github.com:you/monorepo.git", ref = "v1.2.0", subdir = "skills" } A local dev checkout — symlinked, never cloned 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: php flowchart LR F freshen