What Are the Validation Layers in the validate-plugins Action?
The validate-plugins composite action enforces three distinct validation layers—canonical schema compliance, security and policy invariants, and per-plugin quality checks—to ensure every Claude plugin meets upstream standards and organizational security requirements.
The anthropics/claude-plugins-community repository maintains a rigorous validation pipeline for community-contributed Claude plugins. Understanding the validation layers in the validate-plugins action is essential for contributors and DevOps teams who need to ensure their plugins pass automated checks before merging. Each layer is implemented as a numbered shell script in the .github/actions/validate-plugins/scripts/ directory, forming a comprehensive defense-in-depth strategy.
Layer 1: Security and Policy Invariants (Step 11)
The first layer to execute applies static organization-wide hardening rules that act as a policy floor independent of upstream requirements. Implemented in scripts/11-validate-invariants.sh, this layer enforces invariants I1 through I9, which include:
- Alphabetical ordering of marketplace entries
- Description length constraints
- URL format validation for repository sources
- SHA format verification for pinned commits
- Vendored path existence checks
- Shell metacharacter detection and rejection
These rules are not derived from the upstream @anthropic-ai/claude-code schema; rather, they represent organizational security boundaries. The script utilizes helper functions from lib/common.sh, including assert_safe_path and assert_safe_url, to sanitize inputs before they reach downstream validation stages.
Layer 2: Canonical Schema Validation (Step 20)
After security invariants pass, the action validates structural compliance against the official Claude plugin schema. Step 20, defined in scripts/20-validate-cli-marketplace.sh, executes the claude plugin validate CLI command against the marketplace manifest (typically .claude-plugin/marketplace.json) or individual plugin.json files.
This layer guarantees full compliance with the upstream Zod definition maintained by Anthropic. It catches schema mismatches such as missing required fields, incorrect data types, or invalid enum values that would cause runtime failures in Claude Code. Unlike the policy layer, this validation is strictly upstream-driven and changes automatically when the canonical schema evolves.
Layer 3: Per-Plugin Quality Checks (Steps 30, 40, and 41)
The final validation layer operates on individual plugin artifacts rather than the aggregate marketplace, splitting into three distinct execution paths:
External Plugin Validation (Step 30)
For plugins referencing external repositories, scripts/30-validate-cli-external.sh clones each changed plugin at its pinned SHA and runs CLI validation. When strict:false is configured, the script synthesizes a minimal manifest to accommodate legacy or experimental plugin structures without failing the pipeline.
Local Plugin Validation (Step 40)
For in-repo plugins, scripts/40-validate-cli-local.sh iterates over every changed plugin folder within the repository and executes the same claude plugin validate checks applied to external plugins, ensuring consistency between community contributions and first-party extensions.
Auxiliary File Validation (Step 41)
The final step parses runtime configuration files using scripts/41-validate-aux-files.sh. It validates auxiliary files such as .mcp.json, .lsp.json, and hooks/hooks.json to ensure they are well-formed JSON and contain valid configuration structures required for plugin execution.
Implementing the validate-plugins Action in Your Workflow
To integrate these three validation layers into your CI pipeline, reference the composite action in your workflow configuration:
# .github/workflows/validate-plugins.yml
name: Validate Plugins
on:
pull_request:
paths:
- '.claude-plugin/**'
- 'plugins/**'
- '*/.claude-plugin/**'
- '*/agents/**'
- '*/skills/**'
- '*/commands/**'
jobs:
validate:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: anthropics/claude-plugins-community/.github/actions/validate-plugins@<PINNED‑SHA>
with:
marketplace-path: .claude-plugin/marketplace.json
Running Validation Locally
You can execute the identical validation pipeline locally by setting the required environment variables and running the shell scripts sequentially:
export ACTION_PATH=.github/actions/validate-plugins
export VALIDATE_TMP=/tmp/validate-plugins
export BASE_REF=origin/main
export MARKETPLACE_PATH=.claude-plugin/marketplace.json
export ALLOWED_HOSTS="github.com gitlab.com bitbucket.org"
mkdir -p "$VALIDATE_TMP"
bash $ACTION_PATH/scripts/00-detect-changes.sh # Detect changed entries/folders
bash $ACTION_PATH/scripts/11-validate-invariants.sh # Layer 1 – policy invariants
bash $ACTION_PATH/scripts/20-validate-cli-marketplace.sh # Layer 2 – canonical schema
bash $ACTION_PATH/scripts/30-validate-cli-external.sh # Layer 3 – external plugins
bash $ACTION_PATH/scripts/40-validate-cli-local.sh # Layer 3 – local plugins
bash $ACTION_PATH/scripts/41-validate-aux-files.sh # Layer 3 – aux files
bash $ACTION_PATH/scripts/90-report.sh # Summarise results
Summary
- Security Layer (Step 11): Enforces organizational policy invariants (I1-I9) including path safety, URL validation, and formatting rules via
11-validate-invariants.sh. - Canonical Layer (Step 20): Validates upstream schema compliance using the Claude CLI against
marketplace.jsonvia20-validate-cli-marketplace.sh. - Quality Layer (Steps 30-41): Performs granular validation on external plugins, local plugins, and auxiliary configuration files to ensure runtime readiness.
Frequently Asked Questions
What is the execution order of the validation layers?
The pipeline executes in the following sequence: Step 11 (Security Invariants) runs first to filter out policy violations, followed by Step 20 (Canonical Schema), then Step 30 (External Plugins), Step 40 (Local Plugins), and finally Step 41 (Auxiliary Files). This order ensures that structural schema violations are caught only after security risks are eliminated.
How does the security layer differ from the canonical schema layer?
The security layer enforces organization-specific hardening rules (such as forbidding shell metacharacters and enforcing alphabetical ordering) that are not part of the upstream Claude plugin specification. The canonical schema layer strictly validates against the official Anthropic Zod schema and will fail if the plugin structure deviates from the claude plugin validate requirements.
Can I run the validate-plugins action locally without GitHub Actions?
Yes. By exporting the environment variables expected by the scripts—ACTION_PATH, VALIDATE_TMP, BASE_REF, MARKETPLACE_PATH, and ALLOWED_HOSTS—you can execute the shell scripts directly in any POSIX-compliant environment. This mirrors the GitHub Actions behavior exactly, including the three-layer validation sequence.
What are the I1-I9 invariants checked in the security layer?
The invariants cover alphabetical ordering of entries, description length limits, URL format validation for repository sources, SHA format verification, vendored path existence confirmation, and prohibition of shell metacharacters in sensitive fields. These nine rules form a static policy floor defined in scripts/11-validate-invariants.sh using helper functions from lib/common.sh.
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 →