How the validate-plugins GitHub Action Validates Claude Marketplace Plugins
The validate-plugins GitHub Action is a composite action that enforces schema compliance, security invariants, and repository policy across the Claude Marketplace by orchestrating change detection, custom invariant checks, and CLI validation in a reproducible CI pipeline.
The validate-plugins GitHub Action serves as the mandatory quality gate for the anthropics/claude-plugins-community repository, ensuring every plugin submission meets Anthropic's strict standards before merging. This composite action executes a multi-step validation pipeline that checks everything from JSON schema conformance to external repository security. Whether you are maintaining the official marketplace or consuming the action in your own plugin registry, understanding its internals helps you debug failures and customize enforcement rules.
Core Validation Pipeline
The action runs nine distinct phases defined in .github/actions/validate-plugins/action.yml, executing shell scripts that progressively validate marketplace integrity.
Environment Setup and Tooling
The action begins by creating a temporary workspace and installing dependencies. It sets environment variables including VALIDATE_TMP and ACTION_PATH, then installs jq, Node.js 20, and the Claude CLI (@anthropic-ai/claude-code). The installation logic includes retry mechanisms (up to three attempts) and forces the optional native binary to be present, ensuring consistent tooling across runner environments.
Change Detection with Git Diff
The scripts/00-detect-changes.sh script computes the delta between the current commit and BASE_REF (defaults to the PR base or origin/main). It outputs three JSON arrays consumed by downstream steps:
- Changed marketplace entries
- Changed external plugin references
- Changed in-repo plugin folders
This selective validation ensures CI time is spent only on modified artifacts.
Custom Invariant Enforcement (I1-I11)
Before schema validation, scripts/11-validate-invariants.sh enforces repository-specific policy rules coded as invariant checks. These include alphabetical name sorting, duplicate name detection, and SHA exemption validations. The action accepts a warn-invariants input (default: "I1 I3 I5 I8") that downgrades specific invariant violations to warnings, while scope-errors-to-changed limits error reporting to modified entries only.
CLI Schema Validation
The scripts/20-validate-cli-marketplace.sh script invokes claude plugin validate against the assembled marketplace.json file. This official Claude CLI command verifies that the manifest conforms to the current marketplace schema, catching structural errors before they reach production.
External Plugin Security Scanning
When skip-external is false, scripts/30-validate-cli-external.sh clones each changed external repository listed in the marketplace, respecting the allowed-hosts whitelist (default: github.com gitlab.com bitbucket.org). It runs the Claude CLI validation against each external plugin with a configurable timeout (external-timeout-secs, default 120 seconds), preventing CI hangs from unresponsive third-party repositories.
Local Folder and Auxiliary File Validation
For in-repo plugins, scripts/40-validate-cli-local.sh validates changed folders within the repository when skip-local-folders is false. Subsequently, scripts/41-validate-aux-files.sh parses auxiliary JSON files accompanying plugin folders to ensure they are well-formed, catching metadata syntax errors that could break marketplace consumers.
Reporting and Exit Conditions
The final step executes scripts/90-report.sh, which aggregates results from all previous phases. It generates a markdown report at the path specified by report-path and sets the result output to "pass" or "fail". The workflow fails if any step returns an error, or if warnings are treated as errors when fail-on-warnings is set to "true".
Configuration Inputs and Outputs
Key Inputs
marketplace-path: Path to the assembledmarketplace.json(default:.claude-plugin/marketplace.json)entries-dir: Directory containing per-plugin JSON files when using per-file mode (default:"")base-ref: Git reference for change detection (default:${{ github.event.pull_request.base.sha || github.event.before || 'origin/main' }})warn-invariants: Space-separated invariant codes downgraded to warnings (default:"I1 I3 I5 I8")sha-exempt: Plugin names allowed to omitsource.sha(default:"")scope-errors-to-changed: When"true", downgrades invariant errors on unchanged entries to warnings (default:"false")skip-external: Bypass external repository validation (default:"false")skip-local-folders: Bypass in-repo folder validation (default:"false")fail-on-warnings: Treat any warning as a failure (default:"false")validate-all-external: Validate all external entries for nightly drift detection (default:"false")claude-cli-version: Specific Claude CLI version to install (default:latest)external-timeout-secs: Per-plugin clone and validation timeout (default:"120")allowed-hosts: Whitelisted git hosts for external URLs (default:"github.com gitlab.com bitbucket.org")npm-registry: Optional custom npm registry URL (default:"")
Outputs
changed-entries: JSON array of marketplace entry names modified in the PRchanged-external: JSON array of changed external entries containing name, source, and strictness objectschanged-folders: JSON array of modified in-repo plugin folder pathsresult: Final status string ("pass"or"fail")report-path: Path to the generated markdown summary
Implementation Examples
Basic Repository Workflow
The repository's own validation workflow at .github/workflows/validate-plugins.yml invokes the action with scoped error checking:
- uses: ./.github/actions/validate-plugins
with:
marketplace-path: .claude-plugin/marketplace.json
skip-local-folders: "true"
scope-errors-to-changed: "true"
Downstream Integration
Third-party repositories can pin to a specific version of the validate-plugins GitHub Action to enforce Claude Marketplace standards:
name: Validate Claude Plugins
on: pull_request
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: anthropics/claude-plugins-community/.github/actions/validate-plugins@v1
with:
marketplace-path: .claude-plugin/marketplace.json
entries-dir: .claude-plugin/plugins
fail-on-warnings: "true"
Accessing Validation Reports
Capture the markdown report for debugging or audit trails by referencing the output path:
- uses: anthropics/claude-plugins-community/.github/actions/validate-plugins@v1
id: validation
- name: Upload validation report
if: always()
uses: actions/upload-artifact@v4
with:
name: plugin-validation-report
path: ${{ steps.validation.outputs.report-path }}
Summary
- The validate-plugins GitHub Action is a composite action composed of sequential shell scripts located in
.github/actions/validate-plugins/scripts/. - It performs selective validation via
00-detect-changes.sh, only testing modified entries to optimize CI performance. - Policy invariants (I1-I11) are enforced by
11-validate-invariants.shbefore schema validation occurs. - The official Claude CLI (
claude plugin validate) provides the authoritative schema checks for both marketplace manifests and individual plugins. - External plugin validation includes security controls like host whitelisting (
allowed-hosts) and timeout enforcement (external-timeout-secs). - Configuration inputs allow flexible enforcement levels, from strict
fail-on-warningsmodes to scoped error reporting.
Frequently Asked Questions
How does the action determine which plugins to validate?
The scripts/00-detect-changes.sh script compares the current commit against base-ref using git diff, producing JSON arrays of changed marketplace entries, external references, and local folders. This ensures validation runs only against modified artifacts unless validate-all-external is set to "true".
What are the invariant codes (I1-I11) and how do I configure them?
Invariant codes represent repository-specific policy rules, such as alphabetical sorting requirements or SHA presence mandates. You can downgrade specific invariants to warnings using the warn-invariants input (e.g., "I1 I3 I5 I8"), or exempt specific plugins from SHA requirements using the sha-exempt parameter.
Can I use this action to validate plugins in my own repository?
Yes. Reference the action using the full repository path anthropics/claude-plugins-community/.github/actions/validate-plugins@v1 and provide your marketplace-path and optional entries-dir. Ensure you checkout code with fetch-depth: 0 to enable proper change detection.
How does the action handle external repository timeouts?
The 30-validate-cli-external.sh script enforces a per-plugin timeout defaulting to 120 seconds (external-timeout-secs). If cloning or validating an external plugin exceeds this limit, the action marks that plugin as failed and continues processing remaining entries.
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 →