# What Does the Validate Plugins GitHub Action Do? A Complete Technical Guide

> Discover the Validate Plugins GitHub Action. This guide details its role in automating schema validation, security checks, change detection, and reporting for Claude plugins.

- Repository: [Anthropic/claude-plugins-community](https://github.com/anthropics/claude-plugins-community)
- Tags: how-to-guide
- Published: 2026-09-05

---

**The Validate Plugins GitHub Action is a composite CI step in `anthropics/claude-plugins-community` that automates schema validation, security invariant checks, change detection, and reporting for Claude plugin entries.**

The `validate-plugins` action serves as the canonical validation pipeline for the Claude plugins marketplace. Located at `.github/actions/validate-plugins`, this composite GitHub Action orchestrates a multi-stage workflow that ensures every plugin entry meets strict quality and security standards before publication.

## Core Validation Pipeline

The action executes seven sequential stages, each implemented as a shell script in the `scripts/` directory.

### 1. Detect Changes (00-detect-changes.sh)

The **Detect changes** step compares the current PR or commit against a base reference to identify what actually changed. It produces three JSON arrays:

- `changed-entries` — marketplace entries modified in this PR
- `changed-external` — external plugin sources that need re-validation
- `changed-folders` — in-repo plugin folders with modifications

This selective approach avoids validating unchanged entries, significantly reducing CI runtime.

```bash

# The detection script runs automatically as step 1

bash .github/actions/validate-plugins/scripts/00-detect-changes.sh

```

The script assembles a temporary [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) from per-file entries and writes results to [`changes.json`](https://github.com/anthropics/claude-plugins-community/blob/main/changes.json) for downstream consumption.

### 2. Validate Invariants (11-validate-invariants.sh)

The **custom invariant checks** (I1-I11) enforce marketplace-specific policies beyond basic schema validation. These include:

- **Ordering invariants** — entries must follow alphabetical or semantic ordering rules
- **Naming conventions** — plugin IDs and display names must match approved patterns
- **SHA pinning** — external sources must reference specific commit SHAs, not floating branches
- **Host allow-lists** — all external URLs must resolve to approved hosting domains

Configure invariant behavior using action inputs:

- `warn-invariants` — comma-separated list of invariant IDs to treat as warnings
- `fail-on-warnings` — when `true`, warnings become hard failures
- `scope-errors-to-changed` — only report invariant violations on modified entries

### 3. CLI Marketplace Validation (20-validate-cli-marketplace.sh)

This step executes `claude plugin validate` against the assembled [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) — the upstream "source-of-truth" schema checker maintained by Anthropic. It catches:

- Missing required fields in plugin manifests
- Type mismatches against the official JSON Schema
- Invalid plugin capability declarations

### 4. External Plugin Validation (30-validate-cli-external.sh)

For each changed external entry (or all external entries when `validate-all-external: true`), the action:

1. Clones the external repository
2. Validates the host against `allowed-hosts`
3. Runs `claude plugin validate` with a **per-plugin timeout**

This prevents supply-chain attacks by verifying external plugins at their source before marketplace inclusion.

### 5. Local Folder Validation (40-validate-cli-local.sh)

For in-repo plugins with [`.claude-plugin/plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.claude-plugin/plugin.json) files, this step runs targeted CLI validation on each changed folder individually. Skip this with `skip-local-folders: "true"` when validating marketplace-only repositories.

### 6. Generate Report (90-report.sh)

The **Report** step aggregates all errors and warnings into a human-readable markdown file, exposed via the `report-path` output. The report includes:

- Per-entry validation status
- Invariant violation details with line references
- External plugin clone and validation logs

### 7. Export Results

Final outputs enable downstream workflow orchestration:

| Output | Description |
|--------|-------------|
| `changed-entries` | JSON array of modified marketplace entries |
| `changed-external` | JSON array of changed external sources |
| `changed-folders` | JSON array of modified local plugin folders |
| `result` | `"pass"` or `"fail"` overall status |
| `report-path` | Path to the generated markdown report |

## Action Configuration

The action is defined in [`.github/actions/validate-plugins/action.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/action.yml) with these key inputs:

```yaml

# Example: Using the action with custom configuration

- uses: ./.github/actions/validate-plugins
  with:
    marketplace-path: .claude-plugin/marketplace.json
    entries-dir: .claude-plugin/plugins
    allowed-hosts: "github.com,gitlab.com"
    validate-all-external: "false"
    skip-local-folders: "false"
    warn-invariants: "I3,I7"
    fail-on-warnings: "false"
    scope-errors-to-changed: "true"

```

## Complete Workflow Example

The canonical usage appears in [`.github/workflows/validate-plugins.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/workflows/validate-plugins.yml):

```yaml
name: Validate Plugins
on:
  pull_request:
    paths:
      - '.claude-plugin/**'
      - '.github/actions/**'
  push:
    branches: [main]
    paths:
      - '.claude-plugin/**'
      - '.github/actions/**'

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Required for accurate change detection

      # Optional: Run static invariant tests separately

      - name: Static invariant tests
        run: bash .github/actions/validate-plugins/test-invariants.sh

      # Dogfood: Run the shared Validate Plugins action

      - uses: ./.github/actions/validate-plugins
        id: validate
        with:
          marketplace-path: .claude-plugin/marketplace.json
          scope-errors-to-changed: "true"

      # Example: Use outputs in downstream steps

      - name: Process changed entries
        if: steps.validate.outputs.result == 'pass'
        run: |
          echo "Changed: ${{ steps.validate.outputs.changed-entries }}"

```

## Manual Debugging

Invoke individual validation scripts locally or in CI for targeted debugging:

```bash

# Validate invariants only

bash .github/actions/validate-plugins/scripts/11-validate-invariants.sh \
  MARKETPLACE_PATH=.claude-plugin/marketplace.json \
  ENTRIES_DIR=.claude-plugin/plugins \
  BASE_REF=origin/main \
  FAIL_ON_WARNINGS=false \
  WARN_INVARIANTS="I3,I7"

# Validate external plugins with full scope

VALIDATE_ALL_EXTERNAL=true \
MARKETPLACE_PATH=.claude-plugin/marketplace.json \
bash .github/actions/validate-plugins/scripts/30-validate-cli-external.sh

```

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`.github/actions/validate-plugins/action.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/action.yml) | Composite action metadata and step orchestration |
| [`scripts/00-detect-changes.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/00-detect-changes.sh) | Git diff parsing and change classification |
| [`scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/11-validate-invariants.sh) | Policy invariants I1-I11 enforcement |
| [`scripts/20-validate-cli-marketplace.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/20-validate-cli-marketplace.sh) | Schema validation via `claude plugin validate` |
| [`scripts/30-validate-cli-external.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/30-validate-cli-external.sh) | External repo cloning and validation |
| [`scripts/40-validate-cli-local.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/40-validate-cli-local.sh) | In-repo folder validation |
| [`scripts/90-report.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/90-report.sh) | Markdown report generation |

## Summary

- **The Validate Plugins GitHub Action** is a composite action that automates the complete Claude plugin validation lifecycle in `anthropics/claude-plugins-community`.
- **Change detection** ([`00-detect-changes.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/00-detect-changes.sh)) minimizes CI overhead by identifying only modified entries.
- **Invariant checks** ([`11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/11-validate-invariants.sh)) enforce marketplace policies beyond basic schema validation.
- **CLI validation** runs against marketplace JSON, external repositories, and local folders with configurable timeouts and host restrictions.
- **Flexible configuration** via `warn-invariants`, `fail-on-warnings`, and `scope-errors-to-changed` inputs lets repositories tune validation strictness.
- **Structured outputs** (`changed-entries`, `result`, `report-path`) enable downstream automation and human review.

## Frequently Asked Questions

### What is the difference between invariants and CLI validation?

**Invariants** are custom policy checks (I1-I11) defined in [`11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/11-validate-invariants.sh) that enforce marketplace-specific rules like SHA pinning and alphabetical ordering. **CLI validation** uses the official `claude plugin validate` command to verify conformance against Anthropic's published JSON Schema. Invariants catch policy violations; CLI validation catches structural and type errors.

### How does the action handle external plugin security?

The action validates external plugins in [`30-validate-cli-external.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/30-validate-cli-external.sh) by cloning each repository fresh, checking the host against an `allowed-hosts` allow-list, and running `claude plugin validate` with a per-plugin timeout. This prevents malicious modifications between marketplace review and user installation.

### Can I run validation locally without GitHub Actions?

Yes. Clone the repository and execute individual scripts directly. Set required environment variables like `MARKETPLACE_PATH` and `BASE_REF` as shown in the manual debugging examples. The `claude` CLI must be installed and authenticated for schema validation steps to function.

### What causes the action to fail versus warn?

By default, all invariant violations and schema errors fail the action. Use `warn-invariants` to downgrade specific invariant IDs to warnings, and `fail-on-warnings: "false"` to allow warnings without failing the workflow. The `scope-errors-to-changed` input further reduces noise by only reporting violations on entries modified in the current PR.