Understanding the `.claude-plugin/plugin.json` Manifest Format for Claude Code Plugins
The .claude-plugin/plugin.json file is the canonical manifest that declares a Claude Code plugin's identity, metadata, and runtime configuration within a hidden .claude-plugin directory at the repository root.
This JSON file serves as the single source of truth consumed by the Claude CLI, the marketplace UI, and validation CI jobs. Located at /.claude-plugin/plugin.json (or optionally plugin.json at the repo root), it defines everything from the plugin's display name to sensitive user configuration variables.
Core Schema Fields
The manifest follows a declarative schema where only the name field is strictly required. All other fields provide optional metadata or advanced runtime capabilities.
Required Fields
name (string, required): The human-readable identifier used throughout the ecosystem. This value becomes the command prefix in the Claude CLI (e.g., /my-plugin:skill) and the display title in the marketplace catalog.
Metadata Fields
description (string): Short free-form text displayed in the plugin catalog to help users understand functionality.
version (string, semver): Follows MAJOR.MINOR.PATCH semantics (e.g., "1.12.1"). Displayed to users in the marketplace and CLI.
author (object): Contains name (string) and optionally email (string) for attribution.
homepage (string, URL): Link to public documentation or marketing pages.
repository (string, URL): Source repository URL used by the marketplace for "View source" functionality.
license (string): SPDX identifier such as "MIT" or "Apache-2.0".
keywords (array[string]): Discovery tags that improve searchability in the marketplace (e.g., ["blockchain", "accounting"]).
Configuration Fields
userConfig (object): Defines configuration variables that users set during installation. Each key maps to an object containing:
title– UI label shown to usersdescription– Help text explaining the variable's purposetype– JSON schema type (string,number,boolean)sensitive(boolean) – Whentrue, the value is masked in the UI and never logged, ensuring secrets like API keys remain encrypted in Claude's secret store
Advanced Features
mcpServers (array[object]): Declares hosted MCP (Model Context Protocol) servers the plugin calls. Each server object includes command, url, and auth properties. The marketplace parses this to generate runtime shims, validating that command values do not clash with internal commands to prevent namespace collisions.
Implementation directories: While not part of the JSON schema itself, the presence of commands/, skills/, agents/, or hooks/ directories alongside the manifest signals the plugin's surface area to the scanner.
Manifest Discovery and Validation
The Claude ecosystem uses specific validation logic to locate and verify manifests. In .github/actions/validate-plugins/lib/common.sh, the CI action looks for the manifest at lines 154-158, checking both /.claude-plugin/plugin.json and /plugin.json at the repository root.
When a plugin is configured with strict:false, the validation logic at lines 162-163 synthesizes a minimal manifest automatically, generating only { "name": "<plugin-name>" } to satisfy requirements without manual authoring.
The scanning workflow in .github/actions/scan-plugins/scripts/scan.sh reads the manifest alongside .mcp.json and implementation directories to build the complete marketplace descriptor. During CI, .github/actions/validate-plugins/scripts/40-validate-cli-local.sh executes claude plugin validate to reject unknown keys and enforce type constraints.
Practical Examples
Minimal Manifest
For simple plugins that require no configuration or metadata beyond the name:
{
"name": "hello-world",
"version": "0.1.0"
}
The CLI accepts this minimal definition, though the marketplace will display no description, keywords, or configuration options.
Full-Featured Manifest with User Configuration
This real-world example from the tres-finance-plugin demonstrates metadata richness and secure configuration handling:
{
"name": "tres-finance-plugin",
"description": "Blockchain accounting workflows, ledger management, and transaction analysis.",
"version": "1.12.1",
"author": {
"name": "Nadav Gilliam",
"email": "nadav@tres.finance"
},
"homepage": "https://tres.finance",
"repository": "https://github.com/Tres-Finance-Public/tres-claude-plugin",
"license": "MIT",
"keywords": [
"tres-finance",
"blockchain",
"accounting",
"ledger",
"crypto"
],
"userConfig": {
"DEBANK_API_KEY": {
"title": "DeBank API Key",
"description": "Your DeBank Pro API key for balance validation (from https://cloud.debank.com)",
"type": "string",
"sensitive": true
}
}
}
The sensitive: true flag ensures the DeBank API key remains encrypted and never appears in logs or CLI output.
Advanced MCP Server Declaration
For plugins requiring remote server integration:
{
"name": "my-mcp-plugin",
"mcpServers": [
{
"command": "my-mcp:run",
"url": "https://mcp.myservice.com",
"auth": {
"type": "bearer",
"envVar": "MY_MCP_TOKEN"
}
}
]
}
This instructs the marketplace to generate a shim that forwards my-mcp:run invocations to the specified endpoint, using the bearer token stored in the MY_MCP_TOKEN environment variable.
Summary
- The
.claude-plugin/plugin.jsonmanifest lives in a hidden.claude-plugindirectory and defines plugin identity, metadata, and runtime behavior. - Only the
namefield is strictly required; all other fields provide optional marketplace visibility or configuration capabilities. - The
userConfigobject supports sensitive values through thesensitiveboolean flag, which triggers encryption and log masking. - CI validation in
.github/actions/validate-plugins/lib/common.shlocates the manifest and synthesizes minimal versions whenstrict:falseis set. - The
mcpServersarray enables advanced integrations with hosted MCP endpoints while preventing command namespace collisions.
Frequently Asked Questions
Is the name field the only required field in .claude-plugin/plugin.json?
Yes. According to the validation logic in .github/actions/validate-plugins/lib/common.sh, only the name field is mandatory. If you omit optional fields, the plugin will still function, though the marketplace will display limited information and users cannot configure runtime variables.
How does the sensitive flag in userConfig protect my API keys?
When you set sensitive: true on a configuration variable, Claude's secret store encrypts the value and ensures it never appears in CLI logs, UI displays, or debug output. This is essential for storing API keys and authentication tokens securely while still making them available to your plugin's runtime environment.
Where should I place the .claude-plugin/plugin.json file in my repository?
Place it inside a hidden .claude-plugin directory at the repository root (i.e., /.claude-plugin/plugin.json). Alternatively, the validator accepts plugin.json directly at the root, but the hidden directory approach is preferred for cleaner repository organization and aligns with the scanner logic in .github/actions/scan-plugins/scripts/scan.sh.
What happens if my plugin doesn't have a manifest file?
If you enable strict:false mode, the CI validation logic at lines 162-163 of .github/actions/validate-plugins/lib/common.sh automatically synthesizes a minimal manifest containing only { "name": "<plugin-name>" }. However, without a full manifest, you cannot define userConfig, mcpServers, or marketplace metadata, significantly limiting discoverability and functionality.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →