Private Claude Code Plugin Distribution: Marketplace.json, Versioning, and Access Control
The question
How are teams distributing proprietary Claude Code plugins via private marketplaces (Bitbucket / self-hosted git) — versioning, access control, gated update flows?
What we already know (from the vault)
- [[2026-06-09-caf-restructure-proposal]] — Move 1 proposes packaging CAF as a private Claude Code plugin on phData Bitbucket (
caf-marketplace/repo with.claude-plugin/marketplace.json+plugins/caf/), replacinginstall.sh. The proposal documents the exact repo layout and before/after install-flow table. - [[project_rdco_plugin_marketplace]] — RDCO's
RayDataCo/ray-pluginsGitHub marketplace is the develop-first surface; skills/plugins are ported to phData Bitbucket once stable. Skills-only convention (no commands),plugin.jsonversionfield is the update signal,/plugin marketplace update ray-pluginsfor CLI refresh. - [[2026-05-27-claude-config-portability-across-runtimes]] — established that Claude Code config (including plugin/marketplace settings) is file-portable across runtimes.
- [[rdco-vault/08-tooling/2026-06-03-claude-api-sdk-capability-map-rdco-use-cases.md]] — documents Claude Code surface capabilities at the SDK/tooling layer; plugins/marketplaces are confirmed in scope.
- [[rdco-vault/01-projects/phdata/2026-06-08-1-1-andrew.md]] — confirms the porting pattern is understood at phData: "packaging a generic runbook and related assets" per the Copilot Studio plugin already deployed this way.
What the web says
marketplace.json schema (confirmed against docs.claude.com/en/plugin-marketplaces)
Top-level required fields:
name(string, kebab-case) — marketplace identifier users see in/plugin install my-tool@<name>ownerobject:name(required),email(optional)plugins(array of plugin entries)
Top-level optional fields:
$schema— JSON Schema URL for editor autocomplete (https://anthropic.com/claude-code/marketplace.schema.json)description,version— marketplace-level metadatametadata.pluginRoot— base directory prepended to relative plugin source paths (e.g."./plugins"lets entries use"source": "formatter"instead of"source": "./plugins/formatter")allowCrossMarketplaceDependenciesOn— array of other marketplace names whose plugins may be depended upon
Reserved marketplace names (cannot be used): claude-code-marketplace, claude-plugins-official, anthropic-marketplace, and ~12 others impersonating Anthropic.
Per-plugin entry fields (key ones):
name(required, kebab-case)source(required) — string path or source object (see source types below)version— if set, users only receive updates when this string changes; omit to use git commit SHA as versiondisplayName,description,author,homepage,repository,license,keywords,category,tagsstrict(boolean, defaulttrue) — iffalse, marketplace entry is the entire definition;plugin.jsonis ignored for component declarationsdefaultEnabled(boolean, defaulttrue) — iffalse, plugin installs disabled until user opts in (requires Claude Code ≥ v2.1.154)skills,commands,agents,hooks,mcpServers,lspServers— custom path overrides
Plugin source types:
| Source type | Key fields | Notes |
|---|---|---|
| Relative path | "./path" string |
Plugin lives in same repo as marketplace; resolves from marketplace root |
github |
repo (owner/repo), ref?, sha? |
GitHub shorthand or full URL |
url |
url (full git URL), ref?, sha? |
GitLab, Bitbucket, any git host |
git-subdir |
url, path, ref?, sha? |
Sparse-clone a subdirectory; bandwidth-efficient for monorepos |
npm |
package, version?, registry? |
Supports private npm registries |
When both ref and sha are set, sha is the effective pin — install succeeds even if the branch is deleted, as long as the commit is reachable.
Private / Bitbucket distribution (confirmed against docs)
- Any git hosting service works:
/plugin marketplace add https://bitbucket.org/company/plugins.git[1] - Private repo access reuses existing git credential helpers for manual install/update (HTTPS via
gh auth login, macOS Keychain,git-credential-store; SSH viaknown_hosts+ssh-agent) [1] - Background auto-updates require a token in the environment — interactive prompts are suppressed at startup: set
BITBUCKET_TOKEN(app password or repo access token) in.bashrc/.zshrcor as a CI secret [1] git cloneworking in your terminal is sufficient confirmation that Claude Code can reach a private repo
Version pinning and update flow (confirmed against docs)
Version resolution order (first match wins):
versioninplugin.jsonversionin marketplace entry- Git commit SHA of the plugin's source
Key rule: if version is set in plugin.json, pushing new commits without bumping that string does nothing for existing users — they keep the cached copy. Bump version on every release, or omit it to use commit SHA as auto-versioning. [1]
Avoid setting version in both plugin.json and the marketplace entry — plugin.json always wins silently; a stale marketplace-entry version can mask your intended pin. [1]
CLI update commands:
/plugin marketplace update <name>— pull latest marketplace catalog/plugin update <plugin-name>@<marketplace>— update a specific pluginclaude plugin marketplace update <name>— non-interactive equivalent for scripting
Release channels: two separate marketplaces pointing to ref: "stable" and ref: "latest" of the same repo, assigned to different user groups via managed settings. Each channel must resolve to a different version string (or omit version and rely on distinct commit SHAs). [1]
Team-enforced plugins and trust flow (confirmed against docs, with known bug)
extraKnownMarketplaces in .claude/settings.json auto-prompts teammates to install the marketplace when they trust the project folder:
{
"extraKnownMarketplaces": {
"company-tools": {
"source": {
"source": "url",
"url": "https://bitbucket.org/company/plugins.git"
}
}
},
"enabledPlugins": {
"caf@caf-marketplace": true
}
}
Known issue (GitHub issue #32606): extraKnownMarketplaces + enabledPlugins in project-level .claude/settings.json does not currently trigger the install prompt reliably — reported as a bug. Also does not work in headless/-p mode (issue #13096). Verify current behavior before relying on it for automated rollout. [2][3]
strictKnownMarketplaces in managed settings — enterprise lockdown:
- Empty array
[]= no new marketplaces allowed - Array of source objects = allowlist (exact match;
hostPatternregex is the recommended form for Bitbucket Server/self-hosted) - Example for internal Bitbucket Server:
{"source": "hostPattern", "hostPattern": "^bitbucket\\.phdata\\.io$"} - Cannot be overridden by user or project config; only managed settings [1]
Container / CI pre-population: CLAUDE_CODE_PLUGIN_SEED_DIR points at a pre-built ~/.claude/plugins directory baked into an image. Seed is read-only; auto-updates are disabled for seed marketplaces. Build via CLAUDE_CODE_PLUGIN_CACHE_DIR=/opt/claude-seed claude plugin install ... at image-build time. [1]
Org-managed plugins via Claude.ai admin console (separate surface from self-hosted)
For teams using Claude.ai enterprise (not self-hosted marketplace), admins set four distribution levels per plugin: Required (auto-deploy, no uninstall), Installed by default (auto-deploy, can uninstall), Available for install (self-service), Not available (hidden). Group-level overrides apply; most-permissive setting wins when a user is in multiple groups. Max 500 plugins per marketplace via GitHub sync (private/internal repos only). [4]
This is a separate surface from the self-hosted marketplace.json approach — applies when using the Claude.ai managed product, not to self-hosted Claude Code installations.
Convergences and contradictions
Convergences:
- All sources confirm Bitbucket works as a marketplace host — the git-credential-helper reuse means no special integration is needed
sha-pinning in the pluginsourceblock is the universally-recommended production freeze;ref-only is fine for development- The
versionfield inplugin.jsonis the canonical update signal; setting it in both places is a documented footgun - The "develop on GitHub, port to internal git" pattern RDCO already uses is the standard enterprise pattern
Contradictions / gaps:
extraKnownMarketplacestrust-flow auto-prompt has a documented bug (#32606) — does not reliably prompt teammates. The docs describe it as working; reality is it doesn't in the current Claude Code build. Manually distributing theclaude plugin marketplace add <url>command is the reliable fallback- The org-managed admin console (claude.ai) and self-hosted marketplace.json are distinct access-control surfaces and are often conflated in online discussion — they are NOT the same mechanism
strictKnownMarketplaces+extraKnownMarketplacestogether is the correct lockdown pattern per docs, but managed-settings docs require confirming where the managed-settings file actually lives for phData's Claude Code deployment (confirm: likely~/.claude/managed-settings.jsonor deployed via MDM/infra)
Synthesis for RDCO
CAF on phData Bitbucket — recommended setup:
Create a single Bitbucket repo caf-marketplace with the structure from [[2026-06-09-caf-restructure-proposal]] Move 1. The .claude-plugin/marketplace.json catalogs the caf plugin with a relative-path source ("./plugins/caf"). Version lives exclusively in plugins/caf/.claude-plugin/plugin.json — never set version in the marketplace entry to avoid the silent-wins footgun. Bump version (semver: 4.1.0, 4.2.0, etc.) on every meaningful release; commit-SHA auto-versioning works for internal rollout but gives worse UX in /plugin list output.
For access control: the Bitbucket repo's visibility and branch permissions ARE the access gate — restrict write access to the plugins engineering team, read access to all phData consultants who install Claude Code. For background auto-updates on consultant machines, have IT or onboarding docs set BITBUCKET_TOKEN (app password scoped to repository:read) in shell config. For CI/sandbox environments, use the CLAUDE_CODE_PLUGIN_SEED_DIR container pattern. Do NOT rely on extraKnownMarketplaces auto-prompting — use a documented onboarding step (claude plugin marketplace add <url>) until bug #32606 is confirmed fixed.
For gated updates: the recommended CAF update cadence is explicit version bumps with a changelog entry. Use a stable branch (pinned in the marketplace source.ref) for the production marketplace and a dev branch for a test marketplace consultants can optionally add. This gives a stable/latest channel split without requiring separate marketplace repos. Only promote to stable after a verified pilot engagement.
RDCO ray-plugins — recommended setup:
The existing RayDataCo/ray-plugins setup is already correctly structured. Reinforce two rules from vault memory: (1) only plugin.json version field triggers updates — marketplace.json plugin entries stay version-less; (2) sha-pin any plugin entries pointing to external repos if stability matters. For the phData port, strip any RDCO-internal path references and confirm all plugin sources are self-contained (relative paths within the plugin dir, no ../ escapes). The monorepo git-subdir source type is worth adopting as ray-plugins grows — it enables sparse-clone fetches so consultants don't pull the full repo when installing a single plugin.
For ray-plugins specifically, add a .claude/settings.json at repo root with extraKnownMarketplaces pointing back to RayDataCo/ray-plugins once bug #32606 is confirmed resolved — this closes the "clone the repo and trust the folder" auto-registration loop for contributors.
Schema validation gate: run claude plugin validate . in CI (GitHub Actions for ray-plugins, Bitbucket Pipelines for phData) on every PR that touches marketplace.json or plugin.json. This is a one-line gate that catches structural errors before consultants encounter broken installs.
Open follow-ups
- Confirm
extraKnownMarketplacesbug status (GitHub issue #32606) against the Claude Code version phData will standardize on — if fixed, the project-level.claude/settings.jsontrust-flow is the cleanest onboarding path - Verify managed-settings file location for phData's Claude Code deployment — is
~/.claude/managed-settings.jsondeployed via MDM, or does phData rely on per-user config? This determines whetherstrictKnownMarketplaceslockdown is achievable without IT infra work - Bitbucket Server vs Bitbucket Cloud distinction — phData uses Bitbucket (cloud vs server not confirmed in vault);
hostPatternregex instrictKnownMarketplacesdepends on the actual hostname; verify before writing the managed-settings config git-subdir+ Bitbucket compatibility — docs sayurlaccepts "Azure DevOps and AWS CodeCommit URLs without the.gitsuffix"; confirm Bitbucket's URL format works forgit-subdirsparse-clone (standard git protocol, should work, but worth one test)- Release channel for CAF: decide whether a two-branch (
stable/dev) single-repo approach or two separate marketplaces is cleaner for phData — the single-repo approach has less overhead but requires branch discipline; two marketplaces gives explicit separation in/plugin listoutput - Unresolved from memory: which marketplace is canonical for phData porting —
RayDataCo/ray-pluginsorbwilson668/rdco-skills(last pushed 2026-03-07)? Founder hadn't answered as of 2026-06-08; this gates which repo gets the Copilot Studio plugin verification
Related
- [[2026-06-09-caf-restructure-proposal]]
- [[project_rdco_plugin_marketplace]]
- [[2026-05-27-claude-config-portability-across-runtimes]]
- [[rdco-vault/01-projects/phdata/2026-06-08-1-1-andrew.md]]
Sources
Vault:
rdco-vault/01-projects/phdata/2026-06-09-caf-restructure-proposal.mdrdco-vault/.claude/projects/-Users-ray/memory/project_rdco_plugin_marketplace.md
Web (confirmed against docs.claude.com):
- Create and distribute a plugin marketplace — Claude Code Docs — primary source; all marketplace.json schema, source types, versioning, private repo auth, strictKnownMarketplaces
- extraKnownMarketplaces + enabledPlugins never prompts user to install — GitHub Issue #32606
- Support extraKnownMarketplaces in headless/print mode — GitHub Issue #13096
- Manage plugins for your organization — Claude Help Center — org-managed admin console (separate claude.ai surface)
- claude-plugins-official marketplace.json — GitHub — reference schema from Anthropic's official marketplace
- Build a Private Claude Code Plugin Marketplace in 90 Minutes — Automation Labs / Medium
- Building a Private Claude Code Plugin Marketplace for Your Team — Dominic Böttger