Common Pitfalls in Claude Plugin Development: 10 Critical Mistakes to Avoid
The most frequent pitfalls in Claude plugin development stem from malformed plugin.json manifests, unsynchronized marketplace metadata, missing user confirmation hooks for destructive operations, and unhandled exceptions in tool hooks that terminate Claude sessions.
Developing plugins for Claude requires strict adherence to a manifest-driven architecture maintained in the anthropics/claude-plugins-community repository. While reference implementations like quickdesign and tres-finance-plugin demonstrate best practices, developers often encounter automated validation failures or runtime crashes due to subtle configuration errors. Understanding these common pitfalls in Claude plugin development helps ensure your plugin passes the CI pipeline in .github/workflows/validate-plugins.yml and operates safely in production.
Configuration and Manifest Errors
The foundation of every Claude plugin rests in its .claude-plugin/plugin.json manifest. According to the source code analysis, the majority of validation failures occur when this file is incomplete or malformed.
Missing Required Fields in plugin.json
The manifest must contain every mandatory key: name, version, description, author, homepage, repository, license, and keywords. Missing any field causes the marketplace validator to reject the submission immediately. The quickdesign/.claude-plugin/plugin.json file serves as the canonical reference, containing all required fields in the correct JSON structure.
{
"name": "my-plugin",
"version": "0.1.0",
"description": "Brief description of what the plugin does.",
"icon": "./icon.svg",
"author": {
"name": "Your Name",
"url": "https://your-website.example"
},
"homepage": "https://github.com/your-org/your-plugin",
"repository": "https://github.com/your-org/your-plugin",
"license": "MIT",
"keywords": ["ai", "plugin", "example"]
}
Version Synchronization Failures
When submitting to the community marketplace, the name and version fields must match exactly between plugin.json and marketplace.json. The CI workflow defined in .github/workflows/validate-plugins.yml explicitly flags discrepancies between these files as errors. Maintain synchronization by updating both files simultaneously or using automated version bumping scripts.
Broken Asset References
The icon field requires a relative path to an SVG file stored alongside the manifest. If the file is missing or the path is incorrect—such as referencing icon.svg when the file is actually stored at quickdesign/.claude-plugin/icon.svg with a different case—the Claude UI displays a broken image. Always verify the relative path resolves correctly from the plugin root.
Undeclared Permissions and Version Mismatches
Plugins accessing the filesystem or external APIs must explicitly declare permissions in plugin.json. Additionally, version mismatches between the plugin manifest and individual skill files create confusion. The repository tracks skill-specific versions using files like quickdesign/skills/quickdesign/.version, which should always align with the root manifest.
Skill Definition Schema Violations
Each skill requires a properly formatted SKILL.md file following a strict markdown schema.
Invalid Markdown Structure
The skill definition must include specific sections: trigger commands, description, usage examples, and parameter definitions. Files like tres-finance-plugin/skills/tres-wallets-upload/SKILL.md demonstrate the required layout. Typos in section headers or missing fields cause runtime errors when Claude attempts to invoke the skill.
# Skill: /my-plugin:my-action
**Description**
Performs X operation on Y resource.
**Usage**
```bash
/my-plugin:my-action --param1 <value> --param2 <value>
Parameters
--param1– description (required)--param2– description (optional)
Confirmation
Writes are gated behind a confirmation step; the skill will ask:
"Do you want to proceed with X on Y?"
Error handling
All network calls are wrapped in try/catch; failures return a concise error message.
## Security and Compliance Failures
The `anthropics/claude-plugins-community` repository enforces strict security standards through automated scanning.
### Hardcoded Secrets and API Keys
The CI pipeline includes a security scan in [`.github/actions/validate-plugins/scripts/00-detect-changes.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/00-detect-changes.sh) that rejects any plugin containing hardcoded secrets. Never commit API keys, tokens, or credentials in your plugin code. Instead, access sensitive values through environment variables exclusively.
### Unpinned Dependencies
The validation workflow requires all external marketplace entries to pin specific commit SHAs rather than mutable branches. Failing to specify `"sha": "<commit SHA>"` in [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) causes the CI to reject your submission, as unversioned dependencies introduce breaking changes. Always update the SHA only after thorough testing.
## Runtime Safety and Error Handling
Beyond validation, plugins must handle execution safely to prevent session crashes.
### Missing User Confirmation for Write Operations
Write-heavy plugins, particularly those interfacing with financial systems like `tres-finance-plugin`, must implement explicit user confirmation before executing destructive operations. Skipping this guardrail leads to accidental data mutations and marketplace rejection. Implement a `/confirm` hook that prompts users before proceeding with mutations.
### Unhandled Exceptions in Hooks
Pre-tool and post-tool hooks that raise uncaught exceptions abort the entire Claude session. This frequently occurs when developers assume network requests always succeed. Wrap all I/O operations in try/catch blocks and return structured error messages rather than allowing raw exceptions to propagate.
```python
def call_external_api(payload):
# Prompt user for confirmation
if not confirm("Proceed with API call to https://api.example.com?"):
return {"error": "User cancelled operation"}
try:
response = requests.post("https://api.example.com", json=payload, timeout=10)
response.raise_for_status()
return response.json()
except requests.RequestException as exc:
return {"error": f"API request failed: {exc}"}
Summary
- Validate
plugin.jsonagainst thequickdesignreference to ensure all required fields are present and JSON syntax is correct. - Synchronize
nameandversionfields betweenplugin.jsonandmarketplace.jsonto pass CI validation in.github/workflows/validate-plugins.yml. - Store icons using relative paths from the plugin root and verify file existence before submission.
- Follow the strict markdown schema for
SKILL.mdfiles as demonstrated intres-finance-plugin/skills/tres-wallets-upload/SKILL.md. - Declare all required permissions explicitly and avoid hardcoded secrets to pass the security scan in
.github/actions/validate-plugins/scripts/00-detect-changes.sh. - Pin all external dependencies using specific commit SHAs in
marketplace.json. - Implement user confirmation hooks for write operations and wrap all external I/O in comprehensive error handling.
Frequently Asked Questions
Why does my plugin fail validation with a "malformed manifest" error?
The marketplace validator requires every mandatory field in plugin.json, including nested objects like author with name and url properties. Even minor JSON syntax errors, such as trailing commas, trigger rejection. Compare your manifest against quickdesign/.claude-plugin/plugin.json and run your JSON through a linter before committing.
How do I properly version my plugin and its individual skills?
Maintain a root plugin.json version and update corresponding entries in marketplace.json simultaneously. For plugins with multiple skills, track skill-specific versions using files like quickdesign/skills/quickdesign/.version and ensure these align with the root manifest version to prevent runtime mismatches.
What security checks does the Claude plugins repository enforce?
The CI pipeline scans for hardcoded secrets using 00-detect-changes.sh, validates that all permissions are explicitly declared in plugin.json, and verifies that external dependencies are pinned to specific commit SHAs. Write operations must include user confirmation hooks to prevent accidental data mutations.
Why does my plugin crash Claude instead of showing an error message?
Uncaught exceptions in tool hooks immediately terminate the Claude session. You must wrap all external API calls, file system operations, and network requests in try/catch blocks (or equivalent error handling) and return structured error objects rather than raising exceptions.
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 →