# Claude Plugins validate-plugins GitHub Action: Validating Invariants I1-I11

> Discover how the validate-plugins GitHub Action enforces all 11 marketplace invariants I1-I11 for Claude Plugins. Learn about duplicate name detection I2 and description length I3.

- Repository: [Anthropic/claude-plugins-community](https://github.com/anthropics/claude-plugins-community)
- Tags: deep-dive
- Published: 2026-08-25

---

**The validate-plugins GitHub Action enforces all eleven marketplace invariants (I1-I11) in the anthropics/claude-plugins-community repository, including I2 (duplicate name detection) and I3 (minimum description length requirements), through automated bash scripts that parse marketplace.json and emit GitHub annotations.**

The anthropics/claude-plugins-community repository maintains a curated plugin marketplace using a custom GitHub Action to ensure data integrity. The validate-plugins action serves as the automated gatekeeper for the marketplace.json file, verifying that every plugin entry adheres to strict structural and semantic standards defined by invariants I1 through I11.

## I2 and I3: Core Invariants for Plugin Metadata

While the validate-plugins action verifies the complete suite of invariants I1-I11, invariants I2 and I3 specifically govern fundamental plugin identification and documentation standards. Note that historical documentation may reference these as II and III, which correspond directly to I2 and I3 in the current implementation.

### I2 – No Duplicate Plugin Names

Invariant I2 ensures unique identification across the marketplace. The validation logic in [`.github/actions/validate-plugins/scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/11-validate-invariants.sh) scans the entire `plugins` array and fails if any two entries share identical `name` values.

According to the source code at lines 9-10 of [`11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/11-validate-invariants.sh), this check prevents CLI and UI addressing conflicts. When duplicate names are detected, the action emits a `::error` annotation citing invariant I2. The test suite in [`.github/actions/validate-plugins/test-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/test-invariants.sh) explicitly asserts this failure condition at line 56.

### I3 – Minimum Description Length

Invariant I3 enforces documentation quality by requiring every plugin `description` to contain at least ten characters. This threshold is defined in [`.github/actions/validate-plugins/scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/11-validate-invariants.sh) at lines 28-30.

The validation fails with a `::error` annotation when descriptions fall below this limit. The [`test-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/test-invariants.sh) file contains a corresponding test case at line 61 that verifies the action correctly rejects descriptions shorter than ten characters.

## How the Validation Pipeline Works

The validate-plugins action operates through a multi-stage pipeline defined in [`.github/actions/validate-plugins/action.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/action.yml) and orchestrated by the workflow in [`.github/workflows/validate-plugins.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/workflows/validate-plugins.yml).

### Setup and Environment

The action initializes by copying the submitted [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) into a temporary directory (`VALIDATE_TMP`). This isolation prevents mutation of source files during validation. The environment setup occurs in [`action.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/action.yml) at lines 112-114, where the composite action prepares the validation workspace before executing the invariant checks.

### Invariant Evaluation Logic

The core validation logic resides in [`scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/11-validate-invariants.sh). This bash script iterates over the JSON array and applies each invariant check in sequence. The script parses marketplace metadata using **jq** and applies length comparisons and uniqueness validations to verify compliance with all eleven invariants.

### Scoping and Error Severity

The action supports differential validation through the `SCOPE_ERRORS_TO_CHANGED` environment variable. When set to `true`, per-entry invariants (I3-I11) downgrade to **warnings** if the offending entry was not modified by the current PR. However, whole-marketplace invariants including **I1, I2, and I7** never downgrade and always produce errors regardless of PR scope, as documented in the action's README.md.

### GitHub Annotations

Validation results surface directly in pull request checks through GitHub's workflow command syntax. The action emits `::error` and `::warning` annotations that pinpoint exact line numbers and invariant violations for rapid developer feedback.

## Code Examples

### Valid Plugin Structure

The following [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) entry passes both I2 and I3 validation:

```json
{
  "plugins": [
    {
      "name": "awesome-plugin",
      "description": "A helpful plugin that does something useful.",
      "source": {
        "source": "url",
        "url": "https://github.com/example/awesome-plugin",
        "sha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
      }
    }
  ]
}

```

This structure contains a unique name (satisfying I2) and a description exceeding ten characters (satisfying I3).

### I2 Violation: Duplicate Names

The following configuration triggers invariant I2:

```json
{
  "plugins": [
    { "name": "dup-plugin", "description": "First instance.", "source": "./a" },
    { "name": "dup-plugin", "description": "Second instance.", "source": "./b" }
  ]
}

```

The action emits `::error file=marketplace.json::invariant I2: duplicate plugin names` because both entries share the identifier `dup-plugin`.

### I3 Violation: Short Description

This entry fails invariant I3:

```json
{
  "plugins": [
    {
      "name": "short-desc",
      "description": "tiny",
      "source": "./x"
    }
  ]
}

```

The description `tiny` contains only four characters, falling below the ten-character minimum enforced by [`scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/11-validate-invariants.sh) lines 28-30.

## Summary

- The validate-plugins GitHub Action validates all eleven marketplace invariants (I1-I11) defined in the anthropics/claude-plugins-community repository.
- **I2 (No duplicate names)** prevents CLI addressing conflicts by enforcing unique identifiers across the `plugins` array, as implemented at lines 9-10 of [`11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/11-validate-invariants.sh).
- **I3 (Description length)** guarantees minimum documentation standards with a ten-character requirement defined at lines 28-30 of the same script.
- The validation pipeline uses [`scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/11-validate-invariants.sh) for logic and [`test-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/test-invariants.sh) for regression testing at lines 56 and 61.
- Scoping rules allow per-entry invariants (I3-I11) to downgrade to warnings for unchanged entries, while whole-marketplace invariants (I1, I2, I7) always trigger errors.
- Violations surface as GitHub annotations using `::error` and `::warning` workflow commands.

## Frequently Asked Questions

### What happens if a plugin fails invariant I2 or I3 during a pull request?

The validate-plugins action emits a GitHub `::error` annotation that appears directly in the PR checks panel. For I2 (duplicate names) and other whole-marketplace invariants, this error always blocks merge regardless of which files the PR modified. The annotation includes the specific invariant identifier and the location in [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json).

### Can I bypass validation warnings for invariants I3-I11 if I'm not changing specific plugins?

Yes. When the `SCOPE_ERRORS_TO_CHANGED` environment variable is set to `true`, the action downgrades per-entry invariant violations (I3-I11) to warnings if the offending plugin entry was not modified by the current pull request. However, this scoping does not apply to I2, I1, or I7, which always produce blocking errors.

### Where is the ten-character minimum for descriptions defined?

The description length requirement is implemented in [`.github/actions/validate-plugins/scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/11-validate-invariants.sh) at lines 28-30. This script contains the specific character count validation logic, while the corresponding test case in [`test-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/test-invariants.sh) at line 61 verifies that descriptions shorter than ten characters trigger the appropriate error annotation.

### How does the validate-plugins action handle the marketplace.json file?

The [`action.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/action.yml) file defines a composite action that copies [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) into a temporary directory (`VALIDATE_TMP`) during the setup phase at lines 112-114. The [`scripts/11-validate-invariants.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/scripts/11-validate-invariants.sh) script then parses this temporary copy using **jq** to evaluate all eleven invariants without risking modification of the original source file in the repository.