Plugin Marketplaces and Portable Path Variables
CoreIdentify Claude Code's core component types · Difficulty 3/5
Explanation
Plugins: One Installable Unit
A plugin packages skills, hooks, subagents, and MCP Server configs together as one thing you install in a single step. Rather than a teammate rebuilding your setup by hand -- writing the same skill, wiring up the same hooks, pointing at the same MCP Server -- a plugin turns all of that into one versioned, auditable install command that leaves the recipient with an exact copy of what you built.
Marketplaces: Where Plugins Come From
Plugins are distributed through a marketplace -- a catalog of plugins someone has created and shared. Anthropic's own official marketplace is available automatically the moment Claude Code starts; nothing has to be added to reach it. A third-party marketplace, by contrast, has to be added explicitly, typically hosted in a GitHub repository and registered with a command like /plugin marketplace add <owner/repo>.
The Enterprise Layer: Allowlists and Auto-Registration
At the enterprise tier, two managed-settings controls govern where plugins can come from and how widely they're pushed:
| Control | What it does |
|---|---|
| Managed marketplace allowlist | Controls which marketplace *sources* a user is even permitted to add -- it's a permission gate, not an auto-install mechanism |
extraKnownMarketplaces (managed settings) | Registers a marketplace on every user's behalf, so nobody has to manually run /plugin marketplace add |
They solve two different halves of the same rollout problem: the allowlist decides *whether a source can be added at all*, while extraKnownMarketplaces decides *whether a human has to be the one to add it*. An org that wants a specific internal marketplace live for every developer on day one, with no manual steps, pairs both settings together. And because managed settings outrank user- and project-level settings in the configuration hierarchy, anything pushed at the managed tier -- a marketplace, a plugin -- can't be overridden by an individual's local config or a project's own settings file.
The Portable-Path Problem
A plugin that installs cleanly everywhere can still fail for everyone except its author, and the failure mode is specific: a script path or an environment variable that only resolves correctly on the machine the plugin was built on.
Picture a plugin's SKILL.md containing a command that points at /Users/alexmorgan/projects/deploy-utils/validate.sh. That absolute path exists on Alex's laptop and nowhere else. The plugin's manifest copies correctly onto every teammate's machine -- installation succeeds for everyone -- but the moment any teammate actually runs the skill, the script can't be found, because *execution* resolves that path against the machine it's running on, not the machine it was authored on. A second, quieter version of the same problem: a skill that silently depends on an environment variable (e.g., DEPLOY_TOKEN) the author happened to have set in their own shell profile, with the dependency never documented anywhere in the plugin. The skill runs fine right up to the step that needs the variable, then fails -- and because nothing announced the dependency, tracking it down can burn hours.
The Fix: Two Portable Variables
| Variable | Resolves to | Use for |
|---|---|---|
$CLAUDE_PROJECT_DIR | The root of the project the session is running in | Scripts that live in the project itself, referenced relative to its root |
${CLAUDE_PLUGIN_ROOT} | The plugin's own installed location | Scripts bundled inside the plugin, so they resolve no matter whose machine installed it or what directory the session started in |
Using $CLAUDE_PROJECT_DIR/scripts/validate.sh or ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh instead of a hard-coded absolute path means the reference resolves correctly regardless of who cloned the project or where the plugin landed. The same discipline applies to environment variables the plugin depends on: document every one of them explicitly, and validate their presence at install time so a missing variable surfaces immediately -- not silently, mid-run, on a teammate's machine three weeks later.
Common exam traps
- Treating a plugin's successful install as proof it will run correctly. Installation just copies files into place; execution is what resolves paths and variables against the machine actually running them -- and that's exactly where an author's hard-coded absolute path breaks for everyone else.
- Confusing the marketplace allowlist with auto-registration. The allowlist only restricts what sources users are *permitted* to add -- it does not push a marketplace to anyone.
extraKnownMarketplacesis the setting that actually registers one automatically. - Forgetting that managed settings outrank user and project settings -- a plugin pushed at managed scope can't be locally overridden.
Key Takeaways
- A plugin packages skills, hooks, subagents, and MCP server configs into a single install, shipped through a marketplace
- Anthropic's official marketplace is available automatically; a third-party marketplace must be added explicitly via /plugin marketplace add <owner/repo>
- A managed marketplace allowlist restricts which sources users may add; extraKnownMarketplaces in managed settings auto-registers a marketplace without anyone running the add command
- Managed settings sit above user and project settings in precedence, so a managed-scope plugin/marketplace can't be overridden locally
- A plugin can install successfully everywhere and still fail everywhere but the author's machine if it hard-codes an absolute path or an undocumented required env var
- $CLAUDE_PROJECT_DIR resolves project-relative script paths; ${CLAUDE_PLUGIN_ROOT} resolves paths to scripts bundled inside the plugin itself -- both replace fragile absolute paths
Glossary Terms
The Claude Code settings file that configures tool permissions, hook scripts, environment variables, and behavioral settings. Project-scoped (.claude/settings.json) checked into version control, or user-scoped (~/.claude/settings.json) for personal preferences. Hooks are defined here.
A process that implements the MCP protocol and exposes tools, resources, and prompts to MCP clients. Built with official SDKs (Python, TypeScript). Deployed locally via stdio or remotely via StreamableHTTP. Claude Code auto-discovers servers configured in .mcp.json.
Reusable markdown instruction files with YAML frontmatter that define custom slash commands in Claude Code. Invoked with /skill-name. Frontmatter configures: description (for trigger matching), allowed-tools (tool restrictions), and context (fork for isolation). Stored in .claude/skills/.
Related Concepts
Claude Code's Five Core Component Types
The five core component types are Rules, Skills, Commands, Agents, and Agent Memory
Built-in vs. Custom Slash Commands
Built-in slash commands include /clear (reset context), /init (bootstrap CLAUDE.md), and /help
settings.json as the Deterministic Control Surface
settings.json (user: ~/.claude/settings.json, project: .claude/settings.json) configures tool permissions, hooks, env vars, model selection, and MCP servers