Manage Claude Code skills from multiple sources with symlink-based deployment
Project description
Claude Skill Manager (csm)
Manage Claude Code skills across projects from a single place.
The Problem
Claude Code requires skills to live flat inside each project's .claude/skills/ directory. If you have a library of skills organized in subdirectories, or skills shared across multiple projects, you have to copy them manually into every project — and keep them in sync.
# What you have (organized by topic):
~/skills-library/
data-analysis/
backtest/SKILL.md
fetch-data/SKILL.md
productivity/
meeting-prep/SKILL.md
# What Claude Code needs (flat, per project):
~/project-a/.claude/skills/backtest/SKILL.md
~/project-a/.claude/skills/fetch-data/SKILL.md
~/project-b/.claude/skills/meeting-prep/SKILL.md
csm solves this by creating symlinks from your organized skill library into each project's .claude/skills/ directory. You maintain skills in one place, and deploy them anywhere.
Agent-Friendly by Design
csm is built to be used by both humans and LLM agents:
csm schemaoutputs a complete JSON document describing all commands, concepts, config format, and keybindings — designed to be injected into an agent's context--jsonflag on every query command for structured, parseable output- Errors are always JSON on stderr (even without
--json), following the same structured format as GWS - No interactive prompts in JSON mode — agents can script
csmsafely
An agent can bootstrap itself with:
csm schema | head -c 4000 # inject into system prompt
csm --json sources # discover what's available
csm --json targets # discover where to deploy
csm install my-skill --to my-project # deploy
Core Concept
csm connects sources (where skills live) to targets (where Claude Code looks for them):
| Description | Example | |
|---|---|---|
| Source | A directory containing skills (SKILL.md) or a Claude Code marketplace |
~/skills-library, ~/code/my-org/* |
| Target | A project with a .claude/ directory |
~, ~/code/my-project |
| Install | A skill deployed from a source into a target | symlink or claude plugin install |
Demo
Installation
With Homebrew (macOS)
brew install aclemen1/tap/claude-skill-manager
With uv (any platform)
uv tool install claude-skill-manager
With pip
pip install claude-skill-manager
Quick Start
# 1. Create a config file
csm init
# 2. Edit config to add your source and target paths
cat ~/.config/claude-skill-manager/csm.toml
Example csm.toml :
source_paths = ["~/code/my-org/*", "~/skills-library"]
target_paths = ["~", "~/code/my-org/*"]
Paths support glob patterns. For source_paths, the wildcard marks where skill directories are expected:
~/skills-library— exact path; skills are direct subdirs (~/skills-library/my-skill/SKILL.md)~/code/my-org/*— each matched dir may be a skill; source root = parent (~/code/my-org)~/code/my-org/*/*— two levels deep; source root = one level up from the match
For target_paths, each resolved directory is checked for a .claude/ subdirectory.
# 3. Explore what's available
csm sources # list all discovered skills
csm targets # list all projects with .claude/
csm list # unified inventory with install state
# 4. Install a skill
csm install my-skill --to my-project
# 5. Or use the interactive TUI (or just: csm)
csm
CLI Commands
| Command | Description |
|---|---|
csm |
Launch the interactive TUI (default when no subcommand) |
csm sources |
List all discovered sources (local skills, marketplace plugins) |
csm targets |
List all targets with install counts |
csm installs |
List all current installs (symlinks, plugins, orphans) |
csm install SKILL --to TARGET |
Install a local skill into a target via symlink |
csm uninstall TARGET |
Remove skill symlinks from a target |
csm adopt SKILL --from TARGET --to SOURCE |
Adopt an orphan: move it into a source library and replace it with a symlink |
csm list |
Unified inventory with install state per item |
csm diagnostics |
Detect per-target name collisions and issues |
csm updates |
Detect stale plugin cache |
csm init |
Create a default config file |
csm schema |
Output JSON schema for LLM/agent consumption |
JSON output
All query commands support --json for machine-readable output:
csm --json sources # JSON array of sources with items
csm --json targets # JSON array of targets with counts
csm --json installs # JSON array of all installs
csm --json list # JSON inventory with install state
csm --json diagnostics --all # JSON diagnostics
Errors are always returned as structured JSON on stderr:
{
"error": {
"code": 1,
"message": "No items matched 'nonexistent'.",
"reason": "notFound"
}
}
LLM/Agent integration
csm schema # outputs full JSON documentation for LLM consumption
The schema command outputs a structured JSON document with all commands, concepts, config format, diagnostic types, and TUI keybindings — designed to be injected into an LLM context for tool use.
TUI Keybindings
Navigation
| Key | Action |
|---|---|
j / k |
Move down / up |
Enter |
Expand / collapse (fold) |
l |
Expand |
h |
Collapse, or go to parent |
L |
Expand all under cursor |
H |
Collapse all under cursor |
Tab / Shift+Tab |
Cycle panels |
Selection and Install
| Key | Action |
|---|---|
Space |
Select (switch to toggle mode on other panel) |
x |
Toggle install / uninstall |
a |
Apply pending changes |
d |
Delete selected pending change |
Esc |
Cancel all pending changes |
Preview
| Key | Action |
|---|---|
p |
Preview SKILL.md (source panel: any skill; target panel: orphans) |
e |
Edit in $EDITOR (inside preview modal, local skills only) |
Modals and Actions
| Key | Action |
|---|---|
A |
Adopt orphan (move it into a source library, replace with symlink) |
s |
Settings editor |
D |
Diagnostics (conflicts + stale cache) |
? |
Help |
Ctrl+P |
Command palette (change theme, etc.) |
r |
Refresh (rescan all sources) |
q |
Quit |
Theme selection previews each theme in real time as you navigate the list. The chosen theme is persisted in csm.toml.
Diagnostics
csm detects issues per target — two skills with the same name only conflict if they're both active in the same project:
| Type | Severity | Description |
|---|---|---|
user-user |
ERROR | Two local skills with the same name in the same target |
user-plugin |
WARNING | A local skill shadows a Claude Code plugin |
orphan-plugin |
WARNING | An unmanaged skill copy coexists with a plugin |
cross-marketplace |
WARNING | Same skill name from different marketplaces |
mp-cache |
INFO | Normal: marketplace catalog and installed cache |
Configuration
Config file: ~/.config/claude-skill-manager/csm.toml
# Enable Claude Code marketplace plugin discovery (default: true)
plugins = true
# Glob patterns for skill source directories.
# Semantics depend on whether the pattern contains a glob wildcard:
# - Exact path "~/skills-library": the directory itself is the source root;
# skills are its direct subdirectories (~/skills-library/my-skill/SKILL.md).
# - Glob "~/code/my-org/*": each matched directory may be a skill;
# csm checks for SKILL.md directly inside it, and the source root is its
# parent (~/code/my-org/my-skill/SKILL.md → source = ~/code/my-org).
# - Glob "~/code/my-org/*/*": same, two levels deep
# (~/code/my-org/lib/my-skill/SKILL.md → source = ~/code/my-org/lib).
source_paths = [
"~/skills-library",
"~/code/my-org/*",
]
# Glob patterns for target directories
# Each resolved directory is checked for .claude/ presence
target_paths = [
"~",
"~/code/my-org/*",
]
# Theme preference (set via Ctrl+P in TUI)
# theme = "monokai"
How it works
The flat deployment problem
Claude Code scans .claude/skills/ for skill directories, each containing a SKILL.md. It expects a flat structure — no nesting:
my-project/.claude/skills/
backtest/SKILL.md ← Claude Code sees this
fetch-data/SKILL.md ← and this
But as a developer, you want to organize your skills by topic, team, or library:
~/skills-library/
data-analysis/backtest/SKILL.md
data-analysis/fetch-data/SKILL.md
productivity/meeting-prep/SKILL.md
Symlink-based deployment (managed by csm)
csm bridges the gap with symlinks. When you install a skill into a target, csm creates a symlink in the target's .claude/skills/ directory pointing back to the source:
~/project-a/.claude/skills/
backtest → ~/skills-library/data-analysis/backtest
fetch-data → ~/skills-library/data-analysis/fetch-data
The skill lives in one place (the source library), but is visible to Claude Code in every project where it's installed. Edit the skill once, every project picks it up.
Marketplace plugins (managed by Claude Code)
For Claude Code marketplace plugins, csm provides a unified view of all installed plugins across all your projects and scopes (user/project). Install and uninstall operations are delegated to the claude plugin CLI. The toggle operates at the plugin level (not individual skills), since Claude Code installs entire plugins.
Plugins that contain no skills (e.g. hook-only or agent-only plugins) are also shown — csm reads plugin.json metadata to display their name and description.
Orphans
Skills found in .claude/skills/ that are neither symlinks to known sources nor installed via plugins are flagged as orphans (shown with ? in the TUI). These are typically skills that were copied or created manually.
You can adopt an orphan to bring it under csm management: adoption moves the skill directory into a configured source library and replaces it with a symlink, so it becomes a proper managed skill. Use csm adopt from the CLI or press A on an orphan node in the TUI.
Development
# Clone and install
git clone https://github.com/aclemen1/claude-skill-manager.git
cd claude-skill-manager
uv sync
# Run tests
uv run pytest
# Run the TUI locally
uv run csm
# Run with coverage
uv run pytest --cov=skill_manager
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file claude_skill_manager-1.5.0.tar.gz.
File metadata
- Download URL: claude_skill_manager-1.5.0.tar.gz
- Upload date:
- Size: 680.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cdf6c963f33aad6ac0c9f6ba0111d10a4ab8f85118dac2243ec24aaee73f124
|
|
| MD5 |
648782c43051ce7f3599143e5bdefc58
|
|
| BLAKE2b-256 |
53e0c677e2fe9fb49650a09bfa20dabb319c86d3bccdee26aba920ad14080768
|
Provenance
The following attestation bundles were made for claude_skill_manager-1.5.0.tar.gz:
Publisher:
publish.yml on aclemen1/claude-skill-manager
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_skill_manager-1.5.0.tar.gz -
Subject digest:
6cdf6c963f33aad6ac0c9f6ba0111d10a4ab8f85118dac2243ec24aaee73f124 - Sigstore transparency entry: 1123270726
- Sigstore integration time:
-
Permalink:
aclemen1/claude-skill-manager@c3ee48736d7f942038bb0725dc330edc3c8982b3 -
Branch / Tag:
refs/tags/v1.5.0 - Owner: https://github.com/aclemen1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c3ee48736d7f942038bb0725dc330edc3c8982b3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file claude_skill_manager-1.5.0-py3-none-any.whl.
File metadata
- Download URL: claude_skill_manager-1.5.0-py3-none-any.whl
- Upload date:
- Size: 59.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d996d74c4ebeedfa7a183637a2a4fdf9982e038a2a1adf5f879e5d2a242a2b36
|
|
| MD5 |
e096b338f7edbf4b4b8d5d61369c25fd
|
|
| BLAKE2b-256 |
45579de11458803714b0a98b9501495299ecd45357ee4b459e907690d25d8a43
|
Provenance
The following attestation bundles were made for claude_skill_manager-1.5.0-py3-none-any.whl:
Publisher:
publish.yml on aclemen1/claude-skill-manager
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
claude_skill_manager-1.5.0-py3-none-any.whl -
Subject digest:
d996d74c4ebeedfa7a183637a2a4fdf9982e038a2a1adf5f879e5d2a242a2b36 - Sigstore transparency entry: 1123270728
- Sigstore integration time:
-
Permalink:
aclemen1/claude-skill-manager@c3ee48736d7f942038bb0725dc330edc3c8982b3 -
Branch / Tag:
refs/tags/v1.5.0 - Owner: https://github.com/aclemen1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c3ee48736d7f942038bb0725dc330edc3c8982b3 -
Trigger Event:
push
-
Statement type: