Five Layers of Checks in the Claude Plugins `validate‑plugins` GitHub Action
The validate‑plugins composite action enforces five sequential validation layers—policy invariants, canonical schema validation, external plugin verification, local plugin checks, and auxiliary file parsing—to ensure every Claude plugin submission meets security and structural standards.
The anthropics/claude-plugins-community repository uses a hardened CI pipeline to vet community contributions before they reach the marketplace. Understanding these five layers of checks in the validate‑plugins action helps contributors debug failures locally and allows maintainers to enforce quality gates consistently.
1. Policy Invariants (Layer 1)
The first layer hardens repository integrity through nine distinct policy invariants (I1‑I9). Implemented in .github/actions/validate-plugins/scripts/11-validate-invariants.sh, this script enforces rules including alphabetical sorting, duplicate name detection, description length limits, HTTPS‑only URLs, 40‑character SHA pins for dependencies, filename‑to‑plugin‑name matching, protections against direct marketplace.json edits, vendored path existence verification, and shell‑meta‑character safety checks.
Any violation of these hardening policies causes immediate CI failure before the remaining validation steps execute.
2. Canonical Schema Validation (Layer 2)
Layer 2 validates the central marketplace metadata against the official Claude CLI schema. The script .github/actions/validate-plugins/scripts/20-validate-cli-marketplace.sh executes:
claude plugin validate marketplace.json
This step ensures that marketplace.json conforms to the canonical structure required by the Claude plugin system, catching syntax errors, missing required fields, or type mismatches at the repository level before external dependencies are inspected.
3. External Plugin Verification (Layer 3)
External dependencies undergo rigorous pinning and validation in layer 3. The script .github/actions/validate-plugins/scripts/30-validate-cli-external.sh clones each external plugin repository at its exact pinned SHA commit, then synthesizes manifests (or uses existing ones) to run claude plugin validate.
For plugins marked with strict:false, the validation generates a minimal manifest to accommodate flexible configurations while still enforcing core security constraints. This prevents supply‑chain attacks by ensuring only cryptographically pinned code enters the marketplace.
4. Local Plugin Validation (Layer 4)
Layer 4 focuses on in‑repository plugins modified by the current pull request. The script .github/actions/validate-plugins/scripts/40-validate-cli-local.sh identifies changed plugin directories and runs the same claude plugin validate command against each local plugin folder.
This ensures that community contributions added directly to the repository meet the same structural standards as external references without requiring manual CLI invocation during development.
5. Auxiliary File Checks (Layer 5)
The final layer audits supplemental configuration files that extend plugin functionality. The script .github/actions/validate-plugins/scripts/41-validate-aux-files.sh parses auxiliary JSON files including .mcp.json, .lsp.json, and hooks/hooks.json present in plugin directories.
Malformed auxiliary metadata—such as invalid JSON syntax or schema violations in these configuration files—triggers a failure, ensuring that Model Context Protocol (MCP) and Language Server Protocol (LSP) integrations are syntactically sound.
How to Run the Validation Locally
Contributors can replicate the full CI pipeline locally before submitting a pull request. Set the required environment variables and execute the scripts sequentially:
export ACTION_PATH=.github/actions/validate-plugins
export VALIDATE_TMP=/tmp/validate-plugins
mkdir -p "$VALIDATE_TMP"
bash $ACTION_PATH/scripts/00-detect-changes.sh
bash $ACTION_PATH/scripts/11-validate-invariants.sh # Layer 1
bash $ACTION_PATH/scripts/20-validate-cli-marketplace.sh # Layer 2
bash $ACTION_PATH/scripts/30-validate-cli-external.sh # Layer 3
bash $ACTION_PATH/scripts/40-validate-cli-local.sh # Layer 4
bash $ACTION_PATH/scripts/41-validate-aux-files.sh # Layer 5
bash $ACTION_PATH/scripts/90-report.sh
Running these checks locally mirrors the exact sequence defined in .github/actions/validate-plugins/action.yml, catching errors before they reach the GitHub Actions runner.
Summary
- Policy Invariants enforce repository hardening rules (I1‑I9) such as SHA pinning and HTTPS requirements via
11-validate-invariants.sh. - Canonical Schema validates
marketplace.jsonagainst the official Claude CLI schema using20-validate-cli-marketplace.sh. - External Verification clones and checks pinned external plugins at specific SHAs with
30-validate-cli-external.sh. - Local Validation ensures in‑repo plugin folders touched by PRs pass CLI checks via
40-validate-cli-local.sh. - Auxiliary Files parses
.mcp.json,.lsp.json, andhooks/hooks.jsonfor JSON validity using41-validate-aux-files.sh.
Frequently Asked Questions
What triggers a failure in the invariants layer?
The invariants layer fails when marketplace.json violates any of the nine hardening policies (I1‑I9), such as containing duplicate plugin names, using non‑HTTPS URLs, missing 40‑character SHA pins, or editing the marketplace file directly rather than through the proper plugin submission process.
Can I validate only my local plugin without running all five layers?
While the CI runs all layers sequentially, you can run claude plugin validate <plugin-directory> locally against your specific folder. However, merging requires passing all five layers defined in the composite action to ensure repository‑wide consistency and security.
Why does the external plugin layer clone repositories at specific SHAs?
Layer 3 clones external plugins at cryptographically pinned SHA commits to prevent supply‑chain attacks. This guarantees that the exact code reviewed during submission is what gets validated, protecting users from upstream repository changes or malicious updates made after the PR creation.
What auxiliary files does Layer 5 check and why?
Layer 5 validates .mcp.json, .lsp.json, and hooks/hooks.json files. These configurations enable Model Context Protocol and Language Server Protocol integrations; malformed JSON in these files would break plugin functionality, so the validation ensures syntactic correctness before deployment.
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 →