# How the Marketplace Manifest Works in Claude Plugins: Architecture and Validation

> Understand the Claude plugins marketplace manifest system. Discover how it uses a two-tier validation architecture for efficient plugin discovery and uniform validation with claude plugin validate.

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

---

**The Claude plugins marketplace manifest system uses a two-tier validation architecture where a central [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) enumerates plugins and a resolution function either discovers existing [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json) files or synthesizes minimal manifests for skills-only plugins, enabling uniform validation via the `claude plugin validate` CLI command.**

The marketplace manifest system in the `anthropics/claude-plugins-community` repository orchestrates how external tools are discovered, indexed, and validated. This mechanism relies on a hierarchical manifest structure that balances strict validation requirements with flexibility for lightweight, skills-only integrations.

## The Two-Tier Manifest Architecture

The marketplace manifest system operates at two distinct levels: a centralized marketplace registry and individual plugin declarations. This separation allows the community repository to index hundreds of plugins while delegating capability definitions to individual repositories.

### Marketplace-Level Definition ([`.claude-plugin/marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.claude-plugin/marketplace.json))

The top-level [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) file serves as the source of truth for the Claude Marketplace UI and CI validation workflows. Each entry contains the plugin's metadata and a `source` block that pins the plugin code to a specific URL and SHA commit hash.

According to the source code at `/.claude-plugin/marketplace.json#L14-L20`, a typical entry follows this structure:

```json
{
  "name": "0x",
  "source": {
    "source": "url",
    "url": "https://github.com/0xProject/0x-ai.git",
    "sha": "0167bbb..."
  }
}

```

This centralized registry enables the marketplace to display plugin information without cloning every repository, while the SHA pinning ensures reproducible builds and security.

### Per-Plugin Manifest Resolution

Individual plugins declare their capabilities through **plugin manifest** files located in one of two canonical paths. The validator function `resolve_external_manifest` in `/.github/actions/validate-plugins/lib/common.sh#L54-L59` checks for:

1. [`.claude-plugin/plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.claude-plugin/plugin.json) (preferred location)
2. [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json) at the repository root

If neither file exists, the system evaluates whether the plugin is **strict** or **skills-only**.

## Resolving Manifests with `resolve_external_manifest`

The core logic for manifest discovery and synthesis resides in the `resolve_external_manifest` bash function. This utility determines whether to use an existing manifest or generate a synthetic one based on the plugin's `strict` flag.

### Standard Discovery Logic

When validating a plugin, the function first probes the filesystem for standard manifest locations. As implemented in `/.github/actions/validate-plugins/lib/common.sh#L152-L165`, the function returns exit code `0` and prints the file path when it locates a valid [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json):

```bash
resolve_external_manifest() {
  local target=$1 name=$2 strict=${3:-true}
  
  if [[ -f "$target/.claude-plugin/plugin.json" ]]; then
    printf '%s' "$target/.claude-plugin/plugin.json"
    return 0
  fi
  
  if [[ -f "$target/plugin.json" ]]; then
    printf '%s' "$target/plugin.json"
    return 0
  fi
  
  # Skills-only logic follows...

}

```

### Synthetic Manifest Generation for Skills-Only Plugins

Some plugins are intentionally **skills-only**, shipping no [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json) file. Their marketplace entries set `strict:false`. For these entries, the marketplace synthesizes a minimal manifest on-the-fly so that `claude plugin validate` can still execute.

As documented in `/.github/actions/validate-plugins/lib/common.sh#L60-L64`, when `strict:false` is detected and no manifest file exists, the function:

1. Creates a temporary directory structure
2. Writes a minimal JSON file containing only the plugin name: `{ "name": "<plugin-name>" }`
3. Returns exit code `2` to indicate synthesis occurred

This synthesis mechanism ensures uniform validation across all marketplace entries, regardless of whether the original repository contains a full manifest.

## CI Validation Flow

The validation pipeline executes in `/.github/actions/validate-plugins/scripts/30-validate-cli-external.sh#L11-L27`, which orchestrates the end-to-end verification process:

1. **Clone**: Retrieves the external plugin repository at the pinned SHA specified in [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json)
2. **Resolve**: Invokes `resolve_external_manifest` to locate or synthesize the manifest
3. **Validate**: Executes `claude plugin validate` against the resolved path

The script handles three distinct exit states from `resolve_external_manifest`:

- **Exit code 0**: Manifest found at standard location, proceed with validation
- **Exit code 2**: Synthetic manifest created for skills-only plugin, proceed with validation
- **Exit code 1**: No manifest found and `strict:true`, mark as failing

## Working with the Manifest System

When developing plugins for the Claude marketplace, you can replicate the CI validation logic locally using the same bash patterns found in the community repository.

### Validating Plugins Locally

The following bash snippet mirrors the production validation workflow, handling both strict plugins and skills-only integrations:

```bash
#!/bin/bash

resolve_external_manifest() {
  local target=$1 name=$2 strict=${3:-true}
  
  if [[ -f "$target/.claude-plugin/plugin.json" ]]; then
    printf '%s' "$target/.claude-plugin/plugin.json"
    return 0
  fi
  
  if [[ -f "$target/plugin.json" ]]; then
    printf '%s' "$target/plugin.json"
    return 0
  fi
  
  if [[ "$strict" == "false" ]]; then
    mkdir -p "$target/.claude-plugin"
    jq -n --arg name "$name" '{name: $name}' > "$target/.claude-plugin/plugin.json"
    printf '%s' "$target/.claude-plugin/plugin.json"
    return 2
  fi
  
  return 1
}

# Usage example for a skills-only plugin:

manifest_path=$(resolve_external_manifest "/tmp/my-plugin" "my-skill" "false")
exit_code=$?

if [[ $exit_code -eq 0 ]]; then
  echo "Found existing manifest at: $manifest_path"
elif [[ $exit_code -eq 2 ]]; then
  echo "Created synthetic manifest at: $manifest_path"
fi

# Validate using Claude CLI:

claude plugin validate "$manifest_path"

```

This implementation matches the production logic in [`/.github/actions/validate-plugins/lib/common.sh`](https://github.com/anthropics/claude-plugins-community/blob/main//.github/actions/validate-plugins/lib/common.sh), ensuring your local testing aligns with CI requirements.

### Key Files in the Repository

- **[`.claude-plugin/marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.claude-plugin/marketplace.json)**: Central registry enumerating every plugin with source metadata and SHA pins
- **[`.github/actions/validate-plugins/lib/common.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/lib/common.sh)**: Contains `resolve_external_manifest` and helper functions for manifest discovery
- **[`.github/actions/validate-plugins/scripts/30-validate-cli-external.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/30-validate-cli-external.sh)**: CI script that clones external plugins and orchestrates validation
- **[`.github/actions/validate-plugins/scripts/00-detect-changes.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/validate-plugins/scripts/00-detect-changes.sh)**: Detects modified marketplace entries to determine validation scope

## Summary

- The marketplace manifest system uses a centralized [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) to index plugins while delegating capability definitions to individual repositories.
- The `resolve_external_manifest` function in [`common.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/common.sh) implements a three-tier resolution strategy: check [`.claude-plugin/plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.claude-plugin/plugin.json), check root [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json), or synthesize a minimal manifest for skills-only plugins.
- Exit code `2` from `resolve_external_manifest` indicates synthetic manifest generation, allowing skills-only plugins to pass validation without shipping a full [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json).
- All marketplace entries, whether strict or skills-only, undergo uniform validation via `claude plugin validate` against either real or synthesized manifests.
- SHA pinning in the marketplace manifest ensures reproducible builds and security validation across the plugin ecosystem.

## Frequently Asked Questions

### What is the difference between a strict plugin and a skills-only plugin?

A **strict plugin** ships with a full [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json) manifest file containing detailed capability definitions, tool schemas, and metadata. A **skills-only plugin** intentionally omits this file and relies on the marketplace to generate a synthetic manifest containing only the plugin name. According to the source code, skills-only entries must set `strict:false` in [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) to trigger the synthesis logic in `resolve_external_manifest`.

### Where should I place the [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json) file in my plugin repository?

The validator checks two canonical locations in order of preference: first [`.claude-plugin/plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/.claude-plugin/plugin.json) (the recommended location), then [`plugin.json`](https://github.com/anthropics/claude-plugins-community/blob/main/plugin.json) at the repository root. As implemented in `/.github/actions/validate-plugins/lib/common.sh#L54-L59`, the function returns the path unchanged upon finding either file, with the `.claude-plugin/` subdirectory taking precedence.

### How does the CI system handle plugins that don't have a manifest file?

When the validator encounters a plugin without a manifest, it checks the `strict` flag from the marketplace entry. If `strict:false`, the `resolve_external_manifest` function creates a temporary directory and writes a minimal JSON file containing only the plugin name, then returns exit code `2` to signal synthesis. The validation script at `/.github/actions/validate-plugins/scripts/30-validate-cli-external.sh#L11-L27` recognizes this code and proceeds with `claude plugin validate` using the temporary file.

### Why does the marketplace use SHA pinning in the source definition?

The [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json) file specifies each plugin's code location using both a URL and a SHA commit hash. This pinning ensures that the CI validation pipeline and end users load exactly the same code version, preventing supply chain attacks where a repository owner might modify code after listing. The validation script clones the repository at the specific SHA before attempting manifest resolution or validation.