I started with three skills. A year later I had forty-something. Every Claude Code session loaded all of them. Every Codex run loaded all of them. Every .agents
-based tool I tried loaded all of them. The folders are global. The work isn't.
This post is about how skill accumulation became the quiet tax on every session, what I tried to fix it (most of which broke), and the small Go CLI I ended up writing because the right answer wasn't a script — it was a model.
I didn't sit down one day and install forty skills. They arrived in trickles:
By the time I noticed the problem, the count was somewhere north of forty. Some of them I genuinely used every day. Some of them I'd used once. All of them were visible to my agents at startup.
The cost of seeing every skill at every session isn't just startup latency, though that's real. It's the wrong skill suggested at the wrong moment.
A few specific friction moments that made me start caring:
None of these are catastrophic. But they're a constant low-grade friction, and they get worse as you accumulate more skills. The honest version is: the agent is doing what you told it to do. You told it about all of these skills, so all of them are fair game.
The fix has to be: tell the agent about fewer skills.
The naive first attempt: move skills out of ~/.claude/skills
when I didn't need them. Drag-and-drop, basically.
This broke immediately. Skill installers — and there are a lot of them now — write to the global path. So a week later ~/.claude/skills
had grown back to its original size, plus or minus whatever new things I'd installed. Manual moves don't survive contact with installers.
Next attempt: an alias for each context.
alias claude-work='CLAUDE_SKILLS_DIR=~/.claude/work-skills claude'
alias claude-personal='CLAUDE_SKILLS_DIR=~/.claude/personal-skills claude'
The problem: not every agent respects an env var override for the skills path. Some do, some don't, some half-do. And even when they do, the third-party installers still write to the global location, so the directories drift apart immediately.
This is the kind of solution that works on Tuesday and breaks on Thursday.
Closer. I wrote a script that:
~/.claude/skills
~/.claude/skills
as a symlink to ~/.claude/profiles/<name>/skills
~/.codex/skills
and ~/.agents/skills
It worked. For a while. Then it broke when I noticed my agents were already in a shared symlink topology — ~/.claude/skills -> ~/.agents/skills
— because at some point in the past I'd set that up to dedupe the shared subset. My script saw two paths and treated them as two roots, when really they were one. Bash got confused. Symlinks got circular. I spent a Saturday morning unraveling it.
The breaking point wasn't the script. It was realizing that the problem isn't which operations to run on the filesystem. The problem is the absence of a model for what these folders mean.
The model I landed on: a profile is a named set of skills for a purpose. work
. personal
. research
. frontend
. Whatever fits your contexts.
Each profile stores its own copy of skills under ~/.skillmux/profiles/<name>/
. Activating a profile relinks ~/.claude/skills
, ~/.codex/skills
, and ~/.agents/skills
to that profile's contents. All your agents update at once.
This beats tag-based approaches because there's no resolution ambiguity. A skill is in one profile or another (or both — copies are cheap). It beats per-project skill configs because profiles are reusable: my frontend
profile is the same whether I'm in this React app or that one.
It also stops fighting installers. When a profile is active, installers write into the active profile's directory. The global path still exists, still works, still gets written to — but "global" now means "global within the current profile," which is what I wanted all along.
I called the CLI Skillmux. It's written in Go, MIT licensed, ships as a single binary for macOS and Linux (arm64 + x86_64).
Install with curl:
curl -fsSL https://raw.githubusercontent.com/boringstackoverflow/skillmux/main/install.sh | sh
Or Homebrew:
brew install boringstackoverflow/tap/skillmux
Or go install
if you have a Go toolchain:
go install github.com/boringstackoverflow/skillmux/cmd/skillmux@latest
Once installed, the entire daily workflow is four commands.
$ skillmux init --profile work --yes
discovered roots:
~/.claude/skills
~/.codex/skills
~/.agents/skills (shared: ~/.claude/skills -> ~/.agents/skills)
backed up to ~/.skillmux/backups/20260524-194523-pre-init/
linked roots to profile: work
done.
init
discovers your existing agent skill folders, resolves their symlink topology, writes a backup manifest, and relinks them through the active profile. The first profile gets seeded with whatever skills were already there, so nothing disappears on you.
$ skillmux profile create research
created profile: research (empty)
Or do it in one shot:
$ skillmux use research --create
bash
$ skillmux use research
switched: work → research
relinked: ~/.claude/skills, ~/.codex/skills, ~/.agents/skills
All your agents now see only the research
profile. Skills you've installed for work
stay in the work
profile, invisible until you switch back.
$ skillmux current
research
That's the loop. init
once per machine, profile create
whenever you want a new context, use
to switch, current
when you forget where you are.
For repos I cd into often, I drop a .skillmux.toml
at the root:
profile = "frontend"
agents = ["claude", "codex"]
Then I run:
skillmux enter
That's it. The project tells skillmux what profile to use. Wire it into your shell's chpwd
hook or a cd
wrapper if you want it to be automatic.
Honest scope notes, because tools that pretend to solve more than they do are how you waste a Saturday morning.
~/.skillmux/
.Most of these are deliberate. The tool is small because the model is small. Profiles, native folders, reversible operations. That's it.
The thing I cared most about getting right: nothing destructive happens without a backup manifest.
Every operation that touches a managed folder writes a TOML manifest under ~/.skillmux/backups/<timestamp>-<reason>/
. You can list backups, restore from any of them by ID, and uninstall in a way that returns your folders to their exact original state.
$ skillmux backup list
20260524-194523-pre-init init: profile work
20260524-211002-pre-create profile create: research
20260524-211230-pre-use use: research
$ skillmux restore 20260524-194523-pre-init --yes
restored backup 20260524-194523-pre-init
uninstall
does the same thing automatically and keeps ~/.skillmux/
for audit. The escape hatch is always available. I didn't want this tool to be one of those things where you adopt it and then can't get out.
If any of this resonates — if your agent has been suggesting the wrong skill at the wrong moment, or if your ~/.claude/skills
has quietly grown past the point you can keep in your head — give it a try.
curl -fsSL https://raw.githubusercontent.com/boringstackoverflow/skillmux/main/install.sh | sh
skillmux init --profile work --yes
Repo: https://github.com/boringstackoverflow/skillmux
Landing page: https://boringstackoverflow.github.io/skillmux/
Docs: https://boringstackoverflow.github.io/skillmux/docs.html
Issues, PRs, and design feedback all welcome. I'm particularly interested in hearing from people with topologies more complex than mine, because that's where my assumptions are weakest.
Skillmux is MIT licensed, written in Go, and ships as a single binary for macOS and Linux (arm64 + x86_64). Built by boringstackoverflow.