Local Development
How to develop and test Claude Code marketplace plugins (skills) without releasing new versions.
Quick Start
Section titled “Quick Start”This repo includes Makefile targets that automate the symlink workflow:
make dev-link # Link your working copy to the plugin cachemake dev-unlink # Restore the released versionRestart Claude Code after running either command.
How Plugin Loading Works
Section titled “How Plugin Loading Works”Claude Code loads plugins from a cache directory, not from your source code. Understanding this is key to the development workflow.
| Directory | Purpose |
|---|---|
~/.claude/plugins/marketplaces/<plugin>/ | Git clone managed by Claude Code (plugin source) |
~/.claude/plugins/cache/<plugin>/<name>/<version>/ | Installed snapshot (what the CLI actually loads) |
Your working copy (e.g. ~/projects/<plugin>/) | Where you develop (separate git clone) |
When you install a plugin, Claude Code clones the repo into marketplaces/ and copies a clean snapshot into cache/. The CLI reads from cache/ at session start. Edits to your working copy or the marketplace clone have no effect until the cache is updated.
Symlink Development Setup
Section titled “Symlink Development Setup”Symlink the cache directory to your working copy so edits are immediately available on CLI restart.
Step 1: Identify Your Paths
Section titled “Step 1: Identify Your Paths”Find your plugin’s cache path:
cat ~/.claude/plugins/installed_plugins.json | grep installPathThis returns something like:
"installPath": "/home/<user>/.claude/plugins/cache/<plugin>/<name>/<version>"Note the full path — you’ll symlink this directory.
Step 2: Back Up the Cached Version
Section titled “Step 2: Back Up the Cached Version”mv ~/.claude/plugins/cache/<plugin>/<name>/<version> \ ~/.claude/plugins/cache/<plugin>/<name>/<version>.bakStep 3: Create Symlink to Working Copy
Section titled “Step 3: Create Symlink to Working Copy”Point the cache path to your local development clone:
ln -s /path/to/your/working/copy \ ~/.claude/plugins/cache/<plugin>/<name>/<version>Important: Symlink to the directory where you actually edit code, not the marketplace clone that Claude Code manages.
Step 4: Verify
Section titled “Step 4: Verify”ls -la ~/.claude/plugins/cache/<plugin>/<name>/# Should show: <version> -> /path/to/your/working/copyDevelopment Workflow
Section titled “Development Workflow”Once the symlink is in place:
- Edit skills, commands, or references in your working copy
- Restart Claude Code — exit the current session and start a new one. Plugins load at session start; changes are not hot-reloaded.
- Test your changes — invoke the skill or command as a user would
- Iterate — repeat steps 1-3
No commits, pushes, or version bumps needed during development.
Reverting to the Released Version
Section titled “Reverting to the Released Version”# Remove the symlinkrm ~/.claude/plugins/cache/<plugin>/<name>/<version>
# Restore the backupmv ~/.claude/plugins/cache/<plugin>/<name>/<version>.bak \ ~/.claude/plugins/cache/<plugin>/<name>/<version>Caveats
Section titled “Caveats”Plugin auto-updates may break the symlink
Section titled “Plugin auto-updates may break the symlink”Claude Code periodically checks for plugin updates. An auto-update could:
- Replace the symlink with a fresh cache copy
- Write updated files into the symlinked directory (i.e. into your working copy)
If your symlink stops working after you didn’t touch it, check whether an auto-update ran and re-create the symlink.
Working copy differs from a clean cache
Section titled “Working copy differs from a clean cache”The cache is normally a clean snapshot — no .git/, no IDE files, no uncommitted work. Your symlinked working copy includes all of that. This is generally harmless — the plugin loader reads markdown files and ignores unknown entries — but be aware:
- New files that reference structures you haven’t created yet may cause confusing behavior
.git/,.DS_Store,node_modules/, and similar directories are exposed but ignored
Restart is required
Section titled “Restart is required”Claude Code loads plugins at session start. There is no hot-reload. After every change, exit and restart the CLI.
Testing a Specific Version or Branch
Section titled “Testing a Specific Version or Branch”cd /path/to/your/working/copygit checkout <branch-or-tag>
# Restart Claude Code — the symlink still points here,# so it will load whatever is checked outTo compare against the released version, temporarily revert the symlink (see above) and restart.
Quick Reference
Section titled “Quick Reference”# Setup (one-time)CACHE=~/.claude/plugins/cache/<plugin>/<name>/<version>WORKDIR=/path/to/your/working/copy
mv "$CACHE" "${CACHE}.bak"ln -s "$WORKDIR" "$CACHE"
# Develop (repeat)# 1. Edit files in $WORKDIR# 2. Restart Claude Code# 3. Test
# Teardown (when done)rm "$CACHE"mv "${CACHE}.bak" "$CACHE"