# How the Per‑Entry PR Model Works in the Claude Plugins Community Bump Workflow

> Learn how the per-entry PR model in Claude Plugins ensures plugin SHA updates are isolated, preventing one failure from blocking others in the bump workflow.

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

---

**The per‑entry PR model creates a dedicated Git branch and pull request for every plugin SHA update, guaranteeing that a validation or build failure in one plugin does not block or revert the bumping of any other plugin.**

The [`bump-plugin-shas.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/bump-plugin-shas.yml) workflow in the `anthropics/claude-plugins-community` repository automates the process of updating pinned Git SHAs for external Claude plugins. Unlike the default batch behavior, the **per‑entry PR model** generates isolated, single‑purpose pull requests that isolate failures and allow atomic merges. This article explains the exact implementation, referencing the Bash scripts and GraphQL mutations that power the process.

## Workflow Architecture Overview

The workflow consists of a GitHub Actions orchestration layer and a custom composite action that executes shell logic. In [`.github/workflows/bump-plugin-shas.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/workflows/bump-plugin-shas.yml), the workflow accepts a `pr-mode` input that defaults to `batch` but can be set to `per-entry` (lines 84‑88). When selected, this mode triggers a surgical update process defined in [`.github/actions/bump-plugin-shas/scripts/bump.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/actions/bump-plugin-shas/scripts/bump.sh).

The core design goal, explicitly stated in the workflow file header (lines 5‑8), is **isolation**: each plugin bump lives in its own Git branch, receives its own cryptographically signed commit, and opens its own pull request. If the [`validate-plugins.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/validate-plugins.yml) check fails on one branch, the remaining branches stay green and mergeable.

## Step‑by‑Step Execution in Per‑Entry Mode

### Configuration and Input Handling

The workflow forwards the `pr-mode` selection to the custom action at line 88 of [`bump-plugin-shas.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/bump-plugin-shas.yml). Inside [`bump.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/bump.sh), the script reads this value (lines 81‑86) and stores it in the `PR_MODE` environment variable, defaulting to `batch` if unspecified. This variable dictates the branching strategy for the remainder of the execution.

### Deduplication and Skip Logic

Before processing begins, the script calls `branch_for()` (lines 14‑20) to sanitize the plugin name into a Git‑safe branch suffix (e.g., `bump/<sanitized>`). This handles scoped npm‑style names such as `@scope/plugin`.

In per‑entry mode, the script queries GitHub for existing bump PRs using `gh pr list` (lines 27‑33). If a PR already exists for the plugin, the entry is added to a *skipped* list and the script proceeds to the next plugin, preventing redundant work.

### Validation and Branch Preparation

For every stale entry, the script performs upstream validation (lines 35‑46):

- Clones the upstream plugin repository.
- Runs `claude plugin validate` against the candidate SHA.
- Records failures in the *skipped* list, bypassing that plugin.

Only validated plugins proceed. The script then invokes `create_or_reset_branch` (lines 55‑61), which creates or force‑resets a branch named `bump/<sanitized>` to the current `main` HEAD. This guarantees a clean, mergeable base for every individual bump.

### Isolated Commit Construction

Rather than modifying the entire [`marketplace.json`](https://github.com/anthropics/claude-plugins-community/blob/main/marketplace.json), the per‑entry model builds a temporary file containing only the target plugin’s update. The script uses `jq` to substitute the new SHA into the original marketplace content (lines 103‑108):

```bash
entry_file=$(mktemp)
jq --arg n "$name" --arg s "$new_sha" \
   '(.plugins[] | select(.name==$n) | .source.sha) = $s' \
   <<<"$base_marketplace_content" > "$entry_file"

```

This isolated change is then committed via the `create_signed_commit` function (lines 65‑78). This function executes the `createCommitOnBranch` GraphQL mutation, which signs the commit using GitHub’s internal GPG key. This signing is mandatory to satisfy the repository’s organization‑level `required_signatures` branch protection rule.

### Pull Request Generation and Tracking

After committing, the script generates a descriptive title and body containing a table of old and new SHAs. It opens the pull request using `gh pr create` (or updates an existing one with `gh pr edit`), posting a concise description that notes the SHA was pre‑validated.

Each successfully created PR URL is appended to a JSON array (`pr_urls`) that is later emitted as the workflow’s `pr-urls` output (lines 45‑48).

### Post‑Creation Validation

With all per‑entry PRs opened, the workflow dispatches [`validate-plugins.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/validate-plugins.yml) against **each** bump branch (lines 102‑108 of [`bump-plugin-shas.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/bump-plugin-shas.yml)). Because the PRs were created using the default `GITHUB_TOKEN`, the validation check runs on the branch tip without triggering GitHub’s pull‑request recursion guard. If any individual check fails, that specific PR remains open for human triage while others stay green and mergeable.

## Operational Isolation Guarantees

The per‑entry PR model provides three critical safety properties:

- **Failure containment**: A build or validation error in one plugin affects only its dedicated branch, leaving other bumps untouched.
- **Atomic merges**: Maintainers can merge successful bumps immediately without waiting for flaky or broken upstream repositories.
- **Auditability**: Each SHA update exists as a discrete, signed Git commit with a dedicated PR history, making rollbacks and forensic analysis straightforward.

## Running the Workflow Manually

Trigger the per‑entry mode manually via the GitHub CLI:

```bash
gh workflow run bump-plugin-shas.yml \
  -f max_bumps=30 \
  -f pr-mode=per-entry

```

## Summary

- The **per‑entry PR model** is activated by setting `pr-mode: per-entry` in the workflow dispatch inputs defined in [`.github/workflows/bump-plugin-shas.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/.github/workflows/bump-plugin-shas.yml).
- Each plugin update is validated with `claude plugin validate` before any branch is created.
- The [`bump.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/bump.sh) script sanitizes plugin names into Git‑safe branch names using `branch_for()` and creates isolated branches via `create_or_reset_branch()`.
- Commits are signed via the `createCommitOnBranch` GraphQL mutation to satisfy branch protection rules.
- The workflow dispatches [`validate-plugins.yml`](https://github.com/anthropics/claude-plugins-community/blob/main/validate-plugins.yml) to each bump branch, ensuring failures in one plugin do not block others.

## Frequently Asked Questions

### What is the difference between batch mode and per‑entry PR mode?

**Batch mode** aggregates all SHA updates into a single pull request, which risks blocking every update if one plugin fails validation. **Per‑entry PR mode** creates a separate branch and PR for each plugin, isolating failures so that healthy updates can merge immediately without waiting for problematic upstreams to fix their builds.

### How does the workflow prevent duplicate pull requests?

Before processing a plugin, the script queries open PRs using `gh pr list` (lines 27‑33 of [`bump.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/bump.sh)). If a bump PR already exists for that plugin, the script adds the entry to a *skipped* list and proceeds to the next candidate, ensuring no redundant branches are created while the workflow runs.

### Why does the workflow use GraphQL to create commits instead of standard Git commands?

The repository enforces an organization‑level `required_signatures` branch protection rule. The `createCommitOnBranch` GraphQL mutation (lines 65‑78 of [`bump.sh`](https://github.com/anthropics/claude-plugins-community/blob/main/bump.sh)) leverages GitHub’s internal GPG key to sign commits automatically. Standard `git commit` commands would fail this requirement in the GitHub Actions environment because the runner does not possess a trusted signing key.

### Can I limit the number of plugins processed in a single run?

Yes. The workflow accepts a `max_bumps` input that the script respects when iterating through the plugin list. When running manually, pass `-f max_bumps=N` to the GitHub CLI, or specify the value in the workflow dispatch UI, to cap the number of per‑entry PRs generated in a single execution and prevent notification spam.