plugin-registry
Claude Code plugin registry structure, install scopes, and version lag. Use when troubleshooting plugin problems, a stale plugin version in one project, or fixing registry entries.
- License 许可
- MIT
- 最近更新
- 2026-11-13
- Stars
- ★ 59
- Forks
- 6
01 前言 Front Matter
- name
- plugin-registry
- created
- 1770163200000
- modified
- 1794268800000
- reviewed
- 1794268800000
- description
- Claude Code plugin registry structure, install scopes, and version lag. Use when troubleshooting plugin problems, a stale plugin version in one project, or fixing registry entries.
- allowed-tools
- Bash(jq *), Bash(cp ~/.claude/plugins/installed_plugins.json *), Bash(claude plugin list *), Bash(bash ${CLAUDE_SKILL_DIR}/../health-plugins/scripts/check-registry.sh *), Bash(bash ${CLAUDE_SKILL_DIR}/../health-plugins/scripts/fix-registry.sh *), Read, Edit, Glob, Grep, TodoWrite
- compatibility
- claude-code
- user-invocable
- false
02 资源文件 1
- 参考文档REFERENCE.md12.3 KB
03 SKILL.md 正文
Claude Code Plugin Registry
When to Use This Skill
| Use this skill when... | Use something else when... |
|---|---|
| Plugin shows "installed" but isn't working | Setting up new plugins (configure-plugin:configure-claude-plugins) |
| Need to understand plugin scopes | Configuring plugin permissions (health-plugin:settings-configuration) |
| Fixing orphaned registry entries | Running the registry diagnostic and fix (health-plugin:health-plugins; for the user, /health:check --scope=registry) |
| Debugging installation failures | |
| A declared capability (LSP server, hook, command) silently never loads — see REFERENCE.md § A capability declared in a registry is not proof it reached the installed copy |
Registry Location
~/.claude/plugins/installed_plugins.json (the root moves with CLAUDE_CODE_PLUGIN_CACHE_DIR) records every install across all projects; plugin files live under cache/. Official reference: plugin loading, "Find plugins on disk".
Registry Structure (v2)
{
"version": 2,
"plugins": {
"plugin-name@marketplace-name": [
{
"scope": "project",
"projectPath": "/path/to/project",
"installPath": "~/.claude/plugins/cache/marketplace/plugin-name/1.0.0",
"version": "1.0.0",
"installedAt": "2024-01-15T10:30:00Z",
"lastUpdated": "2024-01-15T10:30:00Z",
"gitCommitSha": "abc123"
}
]
}
}
Each plugin key maps to an array of installations (supporting multiple scopes). Entries are version pointers into the shared cache, not plugin copies (REFERENCE.md § The registry holds version pointers, not plugin copies).
scope is user, project or local; project and local entries also carry projectPath. The per-field table, re-read from a live registry, is in REFERENCE.md § Field reference.
Installation Scopes
--scope names the settings file whose enabledPlugins the command writes:
| Scope | Command | Settings file | Reaches |
|---|---|---|---|
user (default) |
claude plugin install my-plugin@marketplace |
~/.claude/settings.json |
You, in every project |
project |
claude plugin install my-plugin@marketplace --scope project |
.claude/settings.json |
Everyone who clones the repo; each person also installs in their own clone |
local |
claude plugin install my-plugin@marketplace --scope local |
.claude/settings.local.json |
You, in this repo only |
When scopes disagree, local overrides project, which overrides user, and managed settings override everything (official plugin loading reference, "Find where a plugin is enabled").
A project entry can also appear with no install command run: a session-start sync was observed adding one per plugin the committed .claude/settings.json enables, recorded at the then-current version (REFERENCE.md § Session-start sync creates project entries).
Known Issue: #14202
anthropics/claude-code#14202 is open as of 2026-10-30: after a --scope project install in one project, other projects were reported (on 2.0.70) to show the plugin as "(installed)" and refuse to install it, while it does not load there. Recent comments name no version; details in REFERENCE.md § Known issue #14202.
An "already installed (scope: project)" message exits 0, so check claude plugin list --json for a row with your projectPath. Try --scope local (not verified to escape #14202) before § Last resort: edit the registry by hand.
Which Install Loads, and Why a Project Can Run an Old Version
When a plugin has both a project entry for the current directory and a user
entry, the project entry decides which cached version loads there, and it
does not follow the user install's updates, so a project can run a version
behind the rest of the machine. claude plugin details reports the user
version from inside such a project; claude plugin list --json reports each
row's scope but not which row wins. The reliable read is the debug log:
CLAUDECODE= claude -p "reply ok" --debug plugins --debug-file /tmp/p.log
Then read its skillsPath: lines for the version actually loaded.
/health:check runs check-plugin-scope-lag.sh, which lists every project-scope
entry below its user-scope version as a scope_lag WARN.
Removing a lagging row is a repair, not a fix: the next session in that project re-creates it. The measured evidence, the lag query, and the uninstall-rewrites-committed-settings hazard are in REFERENCE.md.
Fixing Registry Issues
Find orphaned entries (a projectPath whose directory is gone) with the diagnostic, not by testing each path by hand:
bash ${CLAUDE_SKILL_DIR}/../health-plugins/scripts/check-registry.sh --verbose
Prefer the CLI and the bundled fix script, and confirm with the user before any write.
| Task | Use |
|---|---|
| Remove orphaned entries | bash ${CLAUDE_SKILL_DIR}/../health-plugins/scripts/fix-registry.sh [--plugin <name>] [--dry-run] (timestamped backup, JSON validation, aborts on error) |
| Plugin needed in this project | claude plugin install <plugin>@<marketplace> --scope project (or --scope local), run from the project |
| Make a project-only plugin global | claude plugin install <plugin>@<marketplace>, then claude plugin uninstall <plugin>@<marketplace> --scope project from the project |
| Remove a lagging project row | claude plugin uninstall <plugin>@<marketplace> --scope project, with the snapshot-restore steps in REFERENCE.md § Removing a lagging row rewrites the project's committed settings |
A project-scope uninstall also rewrites the committed .claude/settings.json. Install and uninstall are not pre-approved here, so each goes through the normal permission flow. Verify by re-reading the registry or claude plugin list --json; an exit code alone does not prove the row changed.
Last resort: edit the registry by hand
Only when neither the CLI nor fix-registry.sh can make the change, such as a row whose projectPath no longer exists for a case the script does not cover, or the #14202 refusal with no other scope working:
-
Back up first, every time:
cp ~/.claude/plugins/installed_plugins.json ~/.claude/plugins/installed_plugins.json.backup -
Read the file, then make the smallest change with the Edit tool: drop one array element, or add one element copied from an existing entry with
scopeandprojectPathchanged. -
Validate:
jq empty ~/.claude/plugins/installed_plugins.jsonmust exit 0. If it does not, restore the backup. -
Run
/reload-pluginsor start a new session, then re-run the diagnostic.
Project Settings Integration
Project-scoped plugins also need a key in .claude/settings.json: enabledPlugins is an object mapping plugin@marketplace to a boolean ({"enabledPlugins": {"plugin-name@marketplace": true}}), not an array of names. claude plugin install --scope project writes this key itself. Without it, even a correctly registered project-scoped plugin won't load.
Troubleshooting Checklist
-
Plugin shows installed but doesn't work: check that
projectPathmatches the current directory and.claude/settings.jsonhas theenabledPluginskey, then run the registry diagnostic (health-plugin:health-plugins; for the user,/health:check --scope=registry) -
Can't install plugin (already installed): look for an existing entry with a different
projectPath; try--scope local, then § Last resort: edit the registry by hand -
Plugin works in one project but not another: likely project-scoped; install it in the other project, or at user scope
-
A skill or command is missing in one project only, or behaves as an older version
- Suspect a project entry lagging the user install — run the lag query in REFERENCE.md § Find rows that lag their user install
- Confirm with
--debug pluginsand read theskillsPath:version claude plugin detailsreports the user version here and will mislead you
-
Registry file is corrupted: Claude Code keeps a dated
installed_plugins.unreadable.*.keptcopy when it rebuilds an unreadable registry; restore a backup, or reinstall withclaude plugin install
Agentic Optimizations
| Context | Command |
|---|---|
| View registry | jq -c . ~/.claude/plugins/installed_plugins.json |
| List plugins | jq -r '.plugins | keys[]' ~/.claude/plugins/installed_plugins.json |
| Check specific | jq '.plugins."name@market"' ~/.claude/plugins/installed_plugins.json |
| Project-scoped rows | jq '.plugins | to_entries[] | .value[] | select(.scope=="project") | {projectPath, version}' ~/.claude/plugins/installed_plugins.json |
| Installs per scope | claude plugin list --json |
| Orphan diagnostic | bash ${CLAUDE_SKILL_DIR}/../health-plugins/scripts/check-registry.sh |
Keys are {plugin-name}@{marketplace-name}. After any registry change, run /reload-plugins or start a new session for it to load.
04 同仓库更多 Skills
kitty-show-image
Show the user an image with a note on what to judge, via a file send or a labelled kitty tab. Use when the user must see an image, or icat fails with no /dev/tty.
kitty-session-persistence
Snapshot and restore kitty terminal sessions on macOS. Use when surviving WindowServer hangs without losing tabs, configuring snapshots, or restoring after a force-reboot.
kitty-remote-control
Safe kitty remote control from an agent — read panes with kitty @ ls/get-text, notify, and never mutate the live terminal unasked. Use when running inside kitty.
docs-reference-check
Dangling doc-reference gate: flag markdown naming repo paths or relative links that no longer exist. Use when docs cite moved/deleted files, or wiring a doc-drift lint.
youtube-upload
Upload a video to YouTube via the Data API v3 and edit its title, description, tags or thumbnail afterwards. Use when publishing or retitling a YouTube video.
youtube-studio-share
Share a private YouTube video with a whole Google Workspace organization by scripting YouTube Studio in the browser. Use when a video must be org-only.