# How I manage 40+ skills across Claude Code, Codex, and .agents folders

> Source: <https://dev.to/bso_ba7259e2ef221ebb7166a/how-i-manage-40-skills-across-claude-code-codex-and-agents-folders-1aal>
> Published: 2026-05-26 04:14:15+00:00

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](https://github.com/boringstackoverflow/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.

``` bash
$ 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.

``` bash
$ skillmux profile create research
created profile: research (empty)
```

Or do it in one shot:

``` bash
$ 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.

``` bash
$ 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.

``` bash
$ 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](https://github.com/boringstackoverflow/skillmux)

Landing page: [https://boringstackoverflow.github.io/skillmux/](https://boringstackoverflow.github.io/skillmux/)

Docs: [https://boringstackoverflow.github.io/skillmux/docs.html](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.*
