·9 min read

How to Build a Private Claude Code Plugin Marketplace

Build a private Claude Code plugin marketplace with marketplace.json in a git repo: setup, authentication, versioning, and a hosted alternative.

A Claude Code plugin marketplace is just a git repository with a .claude-plugin/marketplace.json file that lists plugins. Teammates add it with /plugin marketplace add, browse what's inside, and install what they need. Make the repo private and you have a private plugin marketplace: only people with read access to the repo can add it or install from it.

This guide walks through building one from scratch — the marketplace.json format, repo layout, authentication for private repos, and how to version and deprecate plugins over time. At the end we'll cover when a hosted registry is the better call. If you're new to plugins entirely, start with our Claude Code plugins guide for the fundamentals.

Why build a private Claude Code plugin marketplace?

Copy-pasting .claude/ directories between repos doesn't scale past a couple of developers. The problems compound quickly:

  • Drift. Every copy of a slash command or skill diverges the moment someone edits their local version. There's no way to push a fix to everyone.
  • Discovery. New teammates don't know what exists. The senior engineer's excellent code-review agent lives in one repo's .claude/agents/ folder and nowhere else.
  • No update path. When you improve a prompt, everyone else keeps running the old one until they happen to re-copy it.
  • Internal context. Your best plugins encode internal conventions — service names, deploy commands, API patterns. That content can't go in a public marketplace.

A private Claude Code plugin marketplace fixes all four: one repo is the source of truth, teammates browse it with /plugin, updates flow through git, and access control is whatever your git host already enforces.

How marketplace.json works

The entire marketplace format is one JSON file at .claude-plugin/marketplace.json in the root of the repo. It names the marketplace and lists the plugins it offers:

{
  "name": "acme-plugins",
  "owner": {
    "name": "Acme Platform Team",
    "email": "platform@acme.dev"
  },
  "plugins": [
    {
      "name": "api-conventions",
      "source": "./plugins/api-conventions",
      "description": "REST API design rules and a review command",
      "version": "1.2.0"
    },
    {
      "name": "release-helper",
      "source": {
        "source": "github",
        "repo": "acme/release-helper-plugin"
      },
      "description": "Release checklist commands and pre-push hooks"
    }
  ]
}

Two things matter here:

  1. name is the marketplace identifier. Installs are addressed as plugin-name@marketplace-name, so keep it short and stable — renaming it breaks everyone's install references.
  2. source tells Claude Code where each plugin lives. A relative path (./plugins/api-conventions) points inside the same repo — the simplest setup. An object form can point at a separate GitHub repo or git URL, which lets one marketplace index plugins that live in many repos.

Each plugin is a directory with its own .claude-plugin/plugin.json manifest, plus whatever it ships: commands/ for slash commands, agents/ for subagents, skills/ for skills, hooks/ for hooks, and MCP server definitions.

Step by step: build a Claude Code plugin marketplace in a git repo

Here's the full path from empty repo to installed plugin.

Step 1: Create the repo and marketplace manifest

mkdir claude-plugins && cd claude-plugins
git init
mkdir -p .claude-plugin plugins

Add .claude-plugin/marketplace.json:

{
  "name": "acme-plugins",
  "owner": { "name": "Acme Platform Team" },
  "plugins": []
}

Step 2: Add your first plugin

Create the plugin directory with its manifest and content:

plugins/api-conventions/
├── .claude-plugin/
│   └── plugin.json
├── commands/
│   └── review-api.md
└── skills/
    └── api-design/
        └── SKILL.md

plugins/api-conventions/.claude-plugin/plugin.json:

{
  "name": "api-conventions",
  "description": "REST API design rules and a review command",
  "version": "1.0.0"
}

Then register it in marketplace.json by adding an entry to the plugins array with "source": "./plugins/api-conventions".

Step 3: Push to a private repo

git add -A && git commit -m "feat: add api-conventions plugin"
gh repo create acme/claude-plugins --private --source . --push

Any git host works — GitHub, GitLab, Bitbucket, or a self-hosted server. Claude Code clones marketplaces with plain git, so there's nothing GitHub-specific about the format.

Step 4: Add the marketplace in Claude Code

Each teammate runs, inside Claude Code:

/plugin marketplace add acme/claude-plugins

For non-GitHub hosts, pass a full git URL; for local testing, pass a filesystem path. The plugin marketplace add command clones the repo, reads marketplace.json, and makes every listed plugin browsable via /plugin.

Step 5: Install plugins

/plugin install api-conventions@acme-plugins

The plugin's commands, agents, skills, and hooks become available immediately in that session.

Step 6: Auto-enable for the whole team (optional)

To make a repo's checked-in configuration pull the marketplace and enable plugins for everyone who works in it, add both to the project's .claude/settings.json:

{
  "extraKnownMarketplaces": {
    "acme-plugins": {
      "source": {
        "source": "github",
        "repo": "acme/claude-plugins"
      }
    }
  },
  "enabledPlugins": {
    "api-conventions@acme-plugins": true
  }
}

Commit that file and new contributors get prompted to trust and enable the marketplace on their first session — no manual setup steps to document.

Authentication and private repo access

There's no separate auth system to configure: Claude Code uses your existing git credentials when it clones and updates marketplaces. That means:

  • SSH keys — if git clone git@github.com:acme/claude-plugins.git works in your terminal, the marketplace add works too.
  • HTTPS + credential helper — a personal access token stored in your git credential manager covers HTTPS remotes.
  • Access control = repo permissions. Whoever can read the repo can use the marketplace. Revoke repo access and the person can no longer fetch updates. Use your git host's teams to manage this rather than inventing anything new.

Two gotchas worth knowing:

  1. External plugin sources need access too. If marketplace.json points at plugins in other private repos, every consumer needs read access to those repos as well — not just the marketplace repo. Keeping all plugins inside the marketplace repo avoids this entirely.
  2. CI and containers need credentials. Headless environments that add the marketplace need a token with repo read scope injected the same way you'd authorize any private git dependency.

The trade-off to notice: access is binary and per-repo. Everyone with access sees every plugin, and there's no per-plugin permissioning, no audit trail of who installed what, and no SSO integration beyond what your git host provides. For most teams that's fine; for regulated environments it often isn't.

Maintenance: versioning and deprecating plugins

A marketplace is a living artifact. A few practices keep it healthy:

Version explicitly. Bump the version field in each plugin's plugin.json (and its marketplace entry) whenever behavior changes, and keep a short changelog in the plugin's README. Git history is your audit trail, so make commits meaningful.

Ship updates through the update command. Teammates refresh their copy with:

/plugin marketplace update acme-plugins

Don't assume everyone is current — there's no forced-update mechanism, so announce breaking changes in whatever channel your team actually reads.

Review changes like code. Put the marketplace repo behind branch protection and require PR review. A bad hook or an over-broad agent prompt affects every developer who installs it, so treat plugin changes with the same care as shared CI config. Add CODEOWNERS for high-blast-radius plugins.

Deprecate loudly, then remove. To retire a plugin, first mark it in the description field ("DEPRECATED — use release-helper-v2") and leave it listed for a grace period. Installed copies don't vanish when you delist a plugin, so removal from marketplace.json stops new installs but existing users must uninstall themselves.

Know what git can't tell you. There's no built-in rollback (you revert commits), no download analytics (you won't know if anyone actually uses a plugin), and no per-folder access control. These gaps are usually what pushes teams to a hosted registry.

The hosted-registry alternative

A git-based marketplace is the right starting point: zero infrastructure, familiar workflow, free. But it's Claude Code-only, and the maintenance gaps above are real. If your team also runs Cursor, Windsurf, or Copilot, a marketplace.json file does nothing for them — you'd maintain parallel distribution for every tool.

A hosted skill registry like localskills.sh approaches the same problem — distribute skills to your team from one source of truth — from the other direction. You publish each skill once as a versioned package (a folder with a root SKILL.md, plus docs, scripts, and templates up to 100 MB per version), and the CLI writes each tool's native format on install: .claude/skills/ for Claude Code, .cursor/rules .mdc files for Cursor, .windsurf/rules/ for Windsurf, and so on.

localskills install acme/api-conventions --target claude cursor windsurf

What you get over a DIY marketplace, concretely: private and unlisted visibility, versioning with rollback, download analytics so you can see what's actually adopted, organizations with folders, teams, member roles, and folder-level access restrictions — plus SAML SSO, SCIM sync, and audit logs when compliance asks. And if you like the git workflow, GitHub sync mirrors your org's skill library to a repo bidirectionally, so edits in the repo import back as new skill versions. We compare the approaches in more depth in our guide to running a private skill registry, and cover team workflows in how to share Claude skills with your team.

The honest summary: use a git marketplace for a small, Claude Code-only team distributing a handful of plugins. Reach for a registry when you need multi-tool output, real access control, or visibility into adoption.

FAQ

Can I use a private GitHub repo as a Claude Code plugin marketplace?

Yes. Any git repo with a .claude-plugin/marketplace.json at its root works, private or public. Access control is inherited from the repo: anyone who can clone it can run /plugin marketplace add against it, and nobody else can.

What's the difference between a plugin and a skill?

A skill is a folder with a SKILL.md file that Claude loads when relevant. A plugin is a distribution bundle that can contain skills plus slash commands, subagents, hooks, and MCP server config. A marketplace distributes plugins; a skill registry distributes skills across many tools.

How do teammates get plugin updates?

They run /plugin marketplace update <name> to pull the latest commit of the marketplace repo. Updates aren't pushed automatically, so announce breaking changes — or check in extraKnownMarketplaces and enabledPlugins via project settings so at least new sessions in that repo converge on the right versions.

Does a marketplace.json marketplace work with Cursor or Windsurf?

No. The plugin marketplace format is specific to Claude Code. To distribute the same rules and skills across Cursor, Windsurf, Copilot, and Claude Code from one source, publish them to a registry that generates each tool's native format — that's exactly the multi-tool case localskills.sh is built for.


Ready to distribute skills to your team without maintaining marketplace plumbing? Create a free org on localskills.sh and publish your first private skill in minutes.

npm install -g @localskills/cli
localskills login
localskills publish