Composable, portable plugin bundles for Claude Code.
Claude Code enables plugins one at a time, per scope, across three separate
settings.json files. claude-modules lets you bundle them into
named modules and switch between them with a single command.
# A base layer every stack builds on
claude-modules create base-dev
claude-modules plugin install base-dev context7@claude-plugins
# A frontend-specific module
claude-modules create fe
claude-modules plugin install fe playwright@claude-plugins
# Compose them into one role, declared once
claude-modules create full-dev --compose base-dev --compose fe
claude-modules enable full-dev --scope project --save
A module is a named bundle of plugins — the way to manage Claude Code plugins as a set, with everything they need to work anywhere.
Instead of enabling plugins one by one, you group them into a module once. Every module is:
Self-sufficient
Carries its plugins and the marketplaces they come from, so it works on a machine that's never seen them.
Composable
fullstack = backend + frontend, declared once and resolved every time, not retyped.
Reusable
The same module applies to any repo, at any scope — write it once, enable it everywhere.
Transferable
export packs a module and its whole composition chain into one .tar.gz; import unpacks it elsewhere.
/plugin?
/plugin manages one plugin at a time. This lets you switch Claude Code plugin sets in one command.
Claude Code /plugin
manages one plugin at a time
|
claude-modules manages bundles you compose into roles | |
|---|---|---|
| Unit of work | one plugin at a time | a named bundle of plugins |
| Grouping | none — enabledPlugins is a flat map | modules, which compose into bigger modules |
| Reuse across repos | re-enable each plugin, per repo | enable backend |
| Another machine | re-add marketplaces, re-enable plugins | export → import, one file |
| Switching roles | hand-edit up to three settings.json files | enable backend --only |
| Auditing what's on | read three files and apply precedence in your head | status — exit-coded, --json |
| Sharing with a team | commit .claude/settings.json wholesale | commit .claude-modules, then reload |
There's a secondary benefit too: every enabled plugin adds tools Claude has to choose between on every turn, and Claude's own docs note that tool-selection accuracy degrades past 30–50 loaded tools. Scoping your tools to the role you're currently performing helps — see the caveat for MCP-heavy plugins in the docs.
Install it, then capture what you already have.
Node 20+ is the only requirement.
npm install -g claude-modules # global CLI
Or run it without installing: npx claude-modules --help
See Installation in the docs for building from source, and Configuration for CLAUDE_MODULES_HOME.
Build modules plugin by plugin, then compose them into the role you switch into.
This is the way to build a module: one plugin install at a time, one concern
per module, composed together deliberately. Starting from an empty module keeps each one
scoped to a single concern and easy to compose later — if you'd rather capture a scope
you've already configured by hand instead, that's a fallback, covered
below.
# A base layer every stack builds on
claude-modules create base-dev
claude-modules plugin install base-dev context7@claude-plugins
claude-modules plugin install base-dev code-simplifier@claude-plugins
# A Quarkus-specific module
claude-modules create quarkus
claude-modules plugin install quarkus jdtls-lsp@claude-plugins
claude-modules plugin install quarkus quarkus-agent@claude-plugins
# A frontend-specific module
claude-modules create fe
claude-modules plugin install fe modern-web-guidance@claude-plugins
claude-modules plugin install fe playwright@claude-plugins
claude-modules plugin install fe typescript-lsp@claude-plugins
claude-modules plugin install fe frontend-design@claude-plugins
# Compose them into one role, declared once
claude-modules create full-dev --compose base-dev --compose quarkus --compose fe
claude-modules enable full-dev --scope project --save # transitively pulls in all three, every time
Don't need full-dev as a permanent unit? Name the modules directly on one
enable call instead — an ad-hoc union, good for one-off combinations you won't
reuse:
claude-modules enable base-dev quarkus fe --save
And when you're switching roles rather than layering on top of what's active, add
--only to make the scope exactly the given modules:
claude-modules enable full-dev --scope user --only --save
claude-modules enable base-dev --scope user --only # Monday: quarkus/fe plugins go quiet
Already configured a repo by hand, or through /plugin? Capture it instead.
create --from-scope captures what's already enabled in one shot, without
retyping every plugin install. It's a shortcut, not the recommended way to
build a module — a scope tends to accumulate plugins for whatever you were doing at the
time, so it can just as easily capture a bundle mixing unrelated concerns as a clean one.
Reach for the recommended workflow above when you're starting fresh.
Capture what's already enabled
cd ~/projects/api-service
claude-modules create api-svc --from-scope local
Created module 'api-svc' from local scope (/repo/.claude/settings.local.json) with 3 plugin(s), 1 marketplace(s), and 0 composed module(s).
Check what it captured
claude-modules list
claude-modules info api-svc
api-svc (v1.0.0): 3 plugin(s):
typescript-lsp@claude-plugins (enabled)
postgres-mcp@claude-plugins (enabled)
code-review@claude-plugins (enabled)
Apply it — shared with the team
Here to project scope, so it's shared with the team, and --save
so you don't have to retype it:
claude-modules enable api-svc --scope project --save
Changes apply to the next session. Claude Code reads
enabledPlugins at session start. Run /reload-plugins in an
already-open session, or start a new one.
Audit it any time
claude-modules status checks the scope against Claude Code's own plugin
cache and the saved module list, and exits non-zero if something has drifted — see
the docs.
Twenty commands cover building, applying, auditing, and moving modules.
Full option tables and every caveat live in the docs — this is the map.
| Command | What it does |
|---|---|
list | List every module with its plugin and marketplace counts |
info <module> | Show one module's plugins, marketplaces, and composition |
create <module> | Create a module — empty, seeded from a scope, or composing others |
remove <module> | Delete a module |
compose add | Make a module build on others |
compose remove | Stop building on others |
plugin install | Enable a plugin inside a module |
plugin uninstall | Disable a plugin inside a module |
marketplace add | Register a marketplace, globally or on a module |
marketplace remove | Unregister a marketplace |
marketplace list | List registered marketplaces |
enable <module...> | Apply modules to a scope |
disable <module...> | Turn a scope's copy of those plugins off |
disable-all | Turn every plugin in a scope off |
reload | Re-apply a scope's saved module list |
update [module...] | Update modules' marketplaces then plugins to latest |
status | Audit a scope; exit-coded for CI |
export <module> | Pack a module and its composition chain into a .tar.gz |
import <archive> | Unpack one on another machine |
completions bash|zsh | Print a tab-completion script for your shell |
Stated honestly, not buried.
No token-cost preview. Modules report plugin counts, not tokens — Claude Code has no way to aggregate that per module yet.
No version pinning. A module records which plugins to enable, not which versions. Treat modules as portable role definitions, not lockfiles.
Marketplace sources are snapshots. Resolved sources are copied onto the module; later registry changes don't propagate.
Plugin configuration isn't captured. Per-plugin userConfig is deliberately excluded so a committed module can't become a secret-exfiltration path.
Composition overrides stop after one level. An explicit false beats a directly composed child, but not a grandchild.
See the docs for the full explanation of each.