How to Configure Sensitive userConfig Fields Like API Keys in plugin.json
Mark sensitive fields in your Claude plugin's plugin.json with "sensitive": true to ensure API keys and secrets are stored locally in the user's ~/.claude/ directory, masked in logs, and excluded from the public marketplace manifest.
Claude plugins from the anthropics/claude-plugins-community repository rely on the userConfig section in plugin.json to collect user-specific settings. When these settings include credentials like API keys, you must configure sensitive userConfig fields properly to prevent accidental exposure in version control or marketplace listings.
Understanding the userConfig Schema Structure
The userConfig object in plugin.json defines configuration fields as typed properties that Claude Code prompts for during installation. Each field supports standard JSON Schema attributes plus a security-critical sensitive boolean flag.
Required Properties for Sensitive Fields
When defining an API key or token, include these properties:
- type – Must be
"string"for text-based secrets - description – User-facing prompt text shown during installation
- sensitive – Boolean flag triggering secret handling behavior
- required – Ensures the installer prompts for the value before activation
Optional Properties
- default – Fallback value when the field is not required (omit for secrets to avoid hardcoding values)
The sensitive Flag Security Model
Setting "sensitive": true activates three protective mechanisms in the Claude plugin framework:
- Local Storage Only – Values are written to
~/.claude/<plugin-name>.jsonon the user's machine, never committed to the repository or marketplace manifest - UI Masking – Input is hidden during CLI prompts and redacted in log output
- Process Isolation – The secret is injected only into the plugin's runtime environment, unavailable to other agents or the marketplace listing
According to the source code in quickdesign/.claude-plugin/plugin.json, this pattern is explicitly used for the QuickDesign plugin's access token configuration.
Complete Configuration Example
The QuickDesign plugin demonstrates best practices for handling bearer tokens:
{
"name": "quickdesign",
"description": "AI-generated video design plugin.",
"version": "2.1.0",
"userConfig": {
"accessToken": {
"type": "string",
"description": "Bearer token for the QuickDesign service.",
"sensitive": true,
"required": true
}
}
}
In anthropics/claude-plugins-community, the validation script specifically checks this file to ensure accessToken carries the sensitive flag before allowing publication.
For plugins without secrets, such as TestDino, omit the userConfig section entirely:
{
"name": "testdino",
"description": "Inspect test runs via a remote MCP server.",
"version": "1.0.0"
}
This file is located at testdino/.claude-plugin/plugin.json and serves as the reference for non-sensitive configurations.
CI Validation and Leak Prevention
The repository enforces secret safety through .github/actions/validate-plugins/scripts/41-validate-aux-files.sh. This script validates that:
- Any field marked
sensitiveorsecret(legacy syntax) does not appear in.claude-plugin/marketplace.json - Credentials fields include the appropriate security flag
If validation fails, the plugin cannot be published to the community marketplace, ensuring that no secret values leak into the public repository.
Runtime Behavior and Installation Flow
When users install your plugin, Claude Code executes this sequence:
- Parse – Reads
userConfigfromplugin.json - Prompt – Requests missing required values, masking sensitive input with asterisks
- Persist – Writes secrets to the user's local config directory (
~/.claude/<plugin-name>.json) - Inject – Provides the value to the plugin's MCP server at runtime via environment variables or tool arguments
The framework guarantees these values never transit back to the repository or appear in telemetry logs.
Legacy Support for secret Fields
Older plugin manifests may use "secret": true instead of sensitive. The validation script in 41-validate-aux-files.sh accepts both flags for backward compatibility, but new plugins should standardize on sensitive for forward compatibility with future marketplace schema versions.
Summary
- Mark secrets with
sensitive: trueinuserConfigto protect API keys and tokens from exposure - Validation occurs in
.github/actions/validate-plugins/scripts/41-validate-aux-files.sh, blocking leaks before publication to the marketplace - Local storage isolates secrets in
~/.claude/<plugin-name>.json, keeping them out of version control and shared manifests - Runtime injection makes secrets available only to the specific plugin process through environment variables or tool arguments
- Reference implementations exist in
quickdesign/.claude-plugin/plugin.json(with secrets) andtestdino/.claude-plugin/plugin.json(without sensitive fields)
Frequently Asked Questions
What happens if I forget to mark an API key as sensitive?
The CI validator will reject your plugin during the marketplace submission process. If somehow bypassed, the unmarked value would appear in plain text within the public marketplace.json file and could be committed to the repository, exposing user credentials to anyone browsing the source.
Where exactly are sensitive values stored on the user's machine?
Claude Code writes sensitive configuration to ~/.claude/<plugin-name>.json in the user's home directory. This file has restrictive permissions and is automatically excluded from the plugin's git repository through .gitignore generation, ensuring secrets remain on the local filesystem only.
Can I use default values with sensitive fields?
No. The combination of "sensitive": true and "default" is invalid and will fail validation. Default values imply hardcoded secrets, which defeats the purpose of user-specific configuration. Always require user input for actual credentials by setting "required": true without a default.
How do I migrate from the legacy secret flag to sensitive?
Update your plugin.json to use "sensitive": true instead of "secret": true. The validation script at 41-validate-aux-files.sh recognizes both flags during the transition period, but future versions of the marketplace schema may deprecate secret in favor of the standardized sensitive property.
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 →