{"slug": "how-i-manage-40-skills-across-claude-code-codex-and-agents-folders", "title": "How I manage 40+ skills across Claude Code, Codex, and .agents folders", "summary": "A developer built Skillmux, a Go-based CLI tool, to manage over 40 skills across Claude Code, Codex, and .agents folders after skill accumulation created latency and incorrect suggestions in every session. The tool introduces named profiles that store separate skill sets and relinks agent directories to the active profile, preventing conflicts with third-party installers and symlink issues. Skillmux is available on GitHub under an MIT license.", "body_md": "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`\n\n-based tool I tried loaded all of them. The folders are global. The work isn't.\n\nThis 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.\n\nI didn't sit down one day and install forty skills. They arrived in trickles:\n\nBy 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.\n\nThe 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.\n\nA few specific friction moments that made me start caring:\n\nNone 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.\n\nThe fix has to be: tell the agent about fewer skills.\n\nThe naive first attempt: move skills out of `~/.claude/skills`\n\nwhen I didn't need them. Drag-and-drop, basically.\n\nThis broke immediately. Skill installers — and there are a lot of them now — write to the global path. So a week later `~/.claude/skills`\n\nhad grown back to its original size, plus or minus whatever new things I'd installed. Manual moves don't survive contact with installers.\n\nNext attempt: an alias for each context.\n\n```\nalias claude-work='CLAUDE_SKILLS_DIR=~/.claude/work-skills claude'\nalias claude-personal='CLAUDE_SKILLS_DIR=~/.claude/personal-skills claude'\n```\n\nThe 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.\n\nThis is the kind of solution that works on Tuesday and breaks on Thursday.\n\nCloser. I wrote a script that:\n\n`~/.claude/skills`\n\n`~/.claude/skills`\n\nas a symlink to `~/.claude/profiles/<name>/skills`\n\n`~/.codex/skills`\n\nand `~/.agents/skills`\n\nIt worked. For a while. Then it broke when I noticed my agents were already in a shared symlink topology — `~/.claude/skills -> ~/.agents/skills`\n\n— 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.\n\nThe 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.\n\nThe model I landed on: a **profile** is a named set of skills for a purpose. `work`\n\n. `personal`\n\n. `research`\n\n. `frontend`\n\n. Whatever fits your contexts.\n\nEach profile stores its own copy of skills under `~/.skillmux/profiles/<name>/`\n\n. Activating a profile relinks `~/.claude/skills`\n\n, `~/.codex/skills`\n\n, and `~/.agents/skills`\n\nto that profile's contents. All your agents update at once.\n\nThis 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`\n\nprofile is the same whether I'm in this React app or that one.\n\nIt 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.\n\nI 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).\n\nInstall with curl:\n\n```\ncurl -fsSL https://raw.githubusercontent.com/boringstackoverflow/skillmux/main/install.sh | sh\n```\n\nOr Homebrew:\n\n```\nbrew install boringstackoverflow/tap/skillmux\n```\n\nOr `go install`\n\nif you have a Go toolchain:\n\n```\ngo install github.com/boringstackoverflow/skillmux/cmd/skillmux@latest\n```\n\nOnce installed, the entire daily workflow is four commands.\n\n``` bash\n$ skillmux init --profile work --yes\ndiscovered roots:\n  ~/.claude/skills\n  ~/.codex/skills\n  ~/.agents/skills (shared: ~/.claude/skills -> ~/.agents/skills)\nbacked up to ~/.skillmux/backups/20260524-194523-pre-init/\nlinked roots to profile: work\ndone.\n```\n\n`init`\n\ndiscovers 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.\n\n``` bash\n$ skillmux profile create research\ncreated profile: research (empty)\n```\n\nOr do it in one shot:\n\n``` bash\n$ skillmux use research --create\nbash\n$ skillmux use research\nswitched: work → research\nrelinked: ~/.claude/skills, ~/.codex/skills, ~/.agents/skills\n```\n\nAll your agents now see only the `research`\n\nprofile. Skills you've installed for `work`\n\nstay in the `work`\n\nprofile, invisible until you switch back.\n\n``` bash\n$ skillmux current\nresearch\n```\n\nThat's the loop. `init`\n\nonce per machine, `profile create`\n\nwhenever you want a new context, `use`\n\nto switch, `current`\n\nwhen you forget where you are.\n\nFor repos I cd into often, I drop a `.skillmux.toml`\n\nat the root:\n\n```\nprofile = \"frontend\"\nagents  = [\"claude\", \"codex\"]\n```\n\nThen I run:\n\n```\nskillmux enter\n```\n\nThat's it. The project tells skillmux what profile to use. Wire it into your shell's `chpwd`\n\nhook or a `cd`\n\nwrapper if you want it to be automatic.\n\nHonest scope notes, because tools that pretend to solve more than they do are how you waste a Saturday morning.\n\n`~/.skillmux/`\n\n.Most of these are deliberate. The tool is small because the model is small. Profiles, native folders, reversible operations. That's it.\n\nThe thing I cared most about getting right: nothing destructive happens without a backup manifest.\n\nEvery operation that touches a managed folder writes a TOML manifest under `~/.skillmux/backups/<timestamp>-<reason>/`\n\n. 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.\n\n``` bash\n$ skillmux backup list\n20260524-194523-pre-init      init: profile work\n20260524-211002-pre-create    profile create: research\n20260524-211230-pre-use       use: research\n\n$ skillmux restore 20260524-194523-pre-init --yes\nrestored backup 20260524-194523-pre-init\n```\n\n`uninstall`\n\ndoes the same thing automatically and keeps `~/.skillmux/`\n\nfor 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.\n\nIf any of this resonates — if your agent has been suggesting the wrong skill at the wrong moment, or if your `~/.claude/skills`\n\nhas quietly grown past the point you can keep in your head — give it a try.\n\n```\ncurl -fsSL https://raw.githubusercontent.com/boringstackoverflow/skillmux/main/install.sh | sh\nskillmux init --profile work --yes\n```\n\nRepo: [https://github.com/boringstackoverflow/skillmux](https://github.com/boringstackoverflow/skillmux)\n\nLanding page: [https://boringstackoverflow.github.io/skillmux/](https://boringstackoverflow.github.io/skillmux/)\n\nDocs: [https://boringstackoverflow.github.io/skillmux/docs.html](https://boringstackoverflow.github.io/skillmux/docs.html)\n\nIssues, 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.\n\n*Skillmux is MIT licensed, written in Go, and ships as a single binary for macOS and Linux (arm64 + x86_64). Built by boringstackoverflow.*", "url": "https://wpnews.pro/news/how-i-manage-40-skills-across-claude-code-codex-and-agents-folders", "canonical_source": "https://dev.to/bso_ba7259e2ef221ebb7166a/how-i-manage-40-skills-across-claude-code-codex-and-agents-folders-1aal", "published_at": "2026-05-26 04:14:15+00:00", "updated_at": "2026-05-26 04:33:28.406318+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "ai-products", "large-language-models", "generative-ai"], "entities": ["Claude Code", "Codex", ".agents", "Go CLI"], "alternates": {"html": "https://wpnews.pro/news/how-i-manage-40-skills-across-claude-code-codex-and-agents-folders", "markdown": "https://wpnews.pro/news/how-i-manage-40-skills-across-claude-code-codex-and-agents-folders.md", "text": "https://wpnews.pro/news/how-i-manage-40-skills-across-claude-code-codex-and-agents-folders.txt", "jsonld": "https://wpnews.pro/news/how-i-manage-40-skills-across-claude-code-codex-and-agents-folders.jsonld"}}