Summary
A Claude Code plugin loaded into a project via extraKnownMarketplaces + enabledPlugins in .claude/settings.json (or ~/.claude/settings.json) shows as ✔ enabled in /plugin, and its skills load as Agent Skills (model can invoke via the Skill tool). But the plugin's skills do NOT appear in / slash-command autocomplete, regardless of whether the enablement is at project scope or user scope.
Adding a parallel commands/<name>.md directory at the plugin root makes the slash commands appear. So commands/ works; skills/ alone doesn't — exactly the inversion of what the docs describe.
This consolidates evidence from multiple related (some closed, some open) issues that have not been individually resolved.
Reproduction
.claude/plugins/my-plugin/
├── .claude-plugin/
│ ├── plugin.json # {"name":"my-plugin","version":"0.1.0","description":"..."}
│ └── marketplace.json # local marketplace pointing at ./.claude-plugin
└── skills/
└── hello/
└── SKILL.md # frontmatter has name: hello, description: ...
.claude/settings.json:
{
"extraKnownMarketplaces": {
"my-plugin-local": {
"source": {
"source": "file",
"path": "./.claude/plugins/my-plugin/.claude-plugin/marketplace.json"
}
}
},
"enabledPlugins": {
"my-plugin@my-plugin-local": true
}
}
Then in the CLI:
claude plugin list → Status: ✔ enabled
/reload-plugins → reports skill count that EXCLUDES this plugin's skills (verified by counting against other loaded plugins)
- Typing
/my-plugin:hello (or /hello) in autocomplete → no match
- Adding
commands/hello.md with frontmatter + body → autocomplete immediately finds it after /reload-plugins
Tested with both project-scope (.claude/settings.json) and user-scope (~/.claude/settings.json) enablement — same result either way. Scope is not the variable.
Documentation contradicting the observed behavior
From Skills:
Custom commands have been merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way.
From Plugins reference:
Plugins add skills to Claude Code, creating /name shortcuts that you or Claude can invoke.
Location: skills/ or commands/ directory in plugin root
Skills and commands are automatically discovered when the plugin is installed
Per docs, skills/ alone should produce slash commands. It doesn't, for project-local marketplace plugins.
Related closed issues (the underlying bug recurs)
Related open issues (different facets of the same problem space)
Ask
Either:
- Fix implementation to match docs — make
skills/<name>/SKILL.md register as /<plugin-name>:<skill-name> slash commands when the plugin is loaded via project-local extraKnownMarketplaces (and any other path where the plugin is currently enabled but its skills aren't surfacing).
- Update docs to clarify that for project-local marketplace plugins,
skills/ alone is insufficient and commands/<name>.md files are required for slash-command exposure.
Either resolves the contradiction. Option 1 is preferred — it matches the design direction implied by "custom commands have been merged into skills."
Workaround (currently)
Author a parallel commands/<name>.md for each skill, with frontmatter matching what the SKILL.md would have provided (description, allowed-tools, etc.) and a body that delegates to the corresponding SKILL.md. Maintainable but redundant — duplicates frontmatter and adds drift risk between SKILL.md and command.md.
Summary
A Claude Code plugin loaded into a project via
extraKnownMarketplaces+enabledPluginsin.claude/settings.json(or~/.claude/settings.json) shows as✔ enabledin/plugin, and its skills load as Agent Skills (model can invoke via theSkilltool). But the plugin's skills do NOT appear in/slash-command autocomplete, regardless of whether the enablement is at project scope or user scope.Adding a parallel
commands/<name>.mddirectory at the plugin root makes the slash commands appear. Socommands/works;skills/alone doesn't — exactly the inversion of what the docs describe.This consolidates evidence from multiple related (some closed, some open) issues that have not been individually resolved.
Reproduction
.claude/settings.json:{ "extraKnownMarketplaces": { "my-plugin-local": { "source": { "source": "file", "path": "./.claude/plugins/my-plugin/.claude-plugin/marketplace.json" } } }, "enabledPlugins": { "my-plugin@my-plugin-local": true } }Then in the CLI:
claude plugin list→Status: ✔ enabled/reload-plugins→ reports skill count that EXCLUDES this plugin's skills (verified by counting against other loaded plugins)/my-plugin:hello(or/hello) in autocomplete → no matchcommands/hello.mdwith frontmatter + body → autocomplete immediately finds it after/reload-pluginsTested with both project-scope (
.claude/settings.json) and user-scope (~/.claude/settings.json) enablement — same result either way. Scope is not the variable.Documentation contradicting the observed behavior
From Skills:
From Plugins reference:
Per docs,
skills/alone should produce slash commands. It doesn't, for project-local marketplace plugins.Related closed issues (the underlying bug recurs)
/reload-pluginsdoesn't surface skills mid-session, closed/slash command list #28555 — skills missing from initial/list, closedRelated open issues (different facets of the same problem space)
Ask
Either:
skills/<name>/SKILL.mdregister as/<plugin-name>:<skill-name>slash commands when the plugin is loaded via project-localextraKnownMarketplaces(and any other path where the plugin is currently enabled but its skills aren't surfacing).skills/alone is insufficient andcommands/<name>.mdfiles are required for slash-command exposure.Either resolves the contradiction. Option 1 is preferred — it matches the design direction implied by "custom commands have been merged into skills."
Workaround (currently)
Author a parallel
commands/<name>.mdfor each skill, with frontmatter matching what the SKILL.md would have provided (description, allowed-tools, etc.) and a body that delegates to the corresponding SKILL.md. Maintainable but redundant — duplicates frontmatter and adds drift risk between SKILL.md and command.md.