feat(plugins): auto-discover project-scope plugins from <cwd>/.claude/plugins/

Resolved 💬 3 comments Opened May 11, 2026 by cleitonpg Closed May 15, 2026

Summary

Claude Code 2.1.x requires every plugin to come from a registered marketplace.
Local-path installs (claude plugin install /abs/path/to/plugin) are rejected
with "not found in any configured marketplace". This forces consumers that
want to ship a project-scope plugin (one that lives inside the repo, version-
controlled with the project) to either:

(a) publish it to a remote marketplace just to install it locally, or
(b) build a wrapping marketplace at <repo>/.claude/<wrapping>/marketplace.json,
invoke claude plugin marketplace add/install/update on every apply, and
let CC own the materialized copy in its cache.

The wrapping-marketplace pattern is what claude-devkit (a Conventional Commits

  • pnpm-workspace ParisGroup tool) currently does — it works, but the indirection

is operator-visible: claude plugin list shows baseline-filtered@devkit-managed-<slug>,
not the conceptually-cleaner baseline-filtered.

Proposal

Add project-scope plugin auto-discovery: when Claude Code starts up in a
working directory, walk up from <cwd> (same walk-up that locates
<repo>/.claude/settings.json) and load every plugin found at
<repo>/.claude/plugins/<plugin-name>/.claude-plugin/plugin.json.

Plugins discovered this way are:

  • Implicit (no claude plugin marketplace add / install required)
  • Project-scoped (only loaded when CC's cwd is under that <repo>)
  • Lower-precedence than user-scope marketplace plugins (so an operator

can override a project plugin by installing the same name user-scope)

  • Visible in claude plugin list with a clear origin marker (e.g.

(project) suffix), distinct from user-scope or marketplace-scope plugins

This is functionally equivalent to how <repo>/.claude/settings.json is
already loaded — same discovery, same scope, same precedence story —
extended to plugin manifests.

Use case

claude-devkit ships a managed view of the upstream pg-baseline plugin to
<repo>/.claude/plugins/baseline-filtered/ based on the operator's
<repo>/devkit.config.yaml (asset allowlist + per-repo overrides). Today,
the only way CC sees that view is the wrapping-marketplace dance described
above. With auto-discovery, the wrapping marketplace would become
unnecessary: devkit apply would write the view to <repo>/.claude/plugins/
and the next CC session would pick it up.

We expect this to be useful for any project-scope tooling that wants to
ship project-specific skills/commands/agents without pulling in a remote
marketplace as a deployment dependency.

Compatibility

  • No breaking change. Existing marketplace-scope and user-scope plugins

continue to load identically. Auto-discovered project plugins only fill
the "no current way to ship a project plugin locally" gap.

  • No CLI-flag change required. The discovery is implicit; the operator

doesn't run any new command. (If preferred, the behavior could be gated
on <repo>/.claude/settings.json having a "plugins.auto_discover":
true
key, but the default-on case feels more aligned with how
settings.json is already discovered.)

  • Precedence is deterministic. User-scope > marketplace > project.

An operator who wants to override a project plugin installs the same name
user-scope.

Alternatives considered (and why they fall short)

  1. claude plugin install <local-path> accepting a directory path. Tried

in claude-devkit Plan 6 brainstorming; CC 2.1.138 rejects with
"not found in any configured marketplace". Would require new CLI surface
AND a runtime model that allows non-marketplace plugins to exist.

  1. Symlinking the project view into ~/.claude/plugins/cache/. Brittle —

CC re-resolves the cache on update and would overwrite the symlink.

  1. Wrapping marketplace (status quo). Works, but adds 1 marketplace per

project to claude marketplace list and introduces an
apply → marketplace add → install → update chain that has to handle
idempotency, error recovery, and version reconciliation on every run.
Auto-discovery removes the entire chain.

Acceptance criteria

  1. <repo>/.claude/plugins/<name>/.claude-plugin/plugin.json is loaded

without any claude plugin marketplace or claude plugin install call
when claude is run with cwd under <repo>.

  1. claude plugin list shows the plugin with a (project) or project://

origin marker.

  1. A plugin of the same name installed at user scope overrides the

project-scope one (deterministic precedence).

  1. The walk-up stops at the first .git/package.json ancestor (same

walk-up as settings.json discovery).

  1. No regression in existing marketplace or user-scope plugin loading.

Background / context

This FR originates from claude-devkit Plan 6 (wrapping-marketplace
shipping, 2026-05-10) — the design doc surfaced four viable architectural
paths during B3-safety investigation. Option 1 (wrapping marketplace)
shipped because it's the only fully-in-tooling-scope solution; Option 3
(this FR — <cwd>/.claude/plugins/ auto-discovery from CC) was identified
as the cleanest design but requires upstream CC change, hence this issue.

Plan 6 design doc: docs/architecture/plan-6-wrapping-marketplace.md in
parisgroup-ai/claude-devkit (private repo; happy to share excerpts if
useful).

Implementation notes (optional)

The walk-up is already implemented in CC for settings.json discovery
(see cwd → walk up until .git/package.json marker). Extending it to
plugins/ should be additive: the same walk, the same marker, a separate
loader path.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗