# CLI: Checks & gate

Check what changed, gate the release and manage the policy behind it.

## Check a connected GitHub pull request

```bash
bumpkit github check 7 --repository acme/shop
bumpkit github check 7 --repository acme/shop --json
```

Runs the same live pull request check as the dashboard using the workspace's GitHub App installation. Sign in with `bumpkit login`; machine keys cannot request this action. Your account needs a workspace role that can run checks, and the GitHub App must have access to the repository. If `--repository` is omitted, the command uses the checkout's origin remote.

Bumpkit fetches the current open PR and its exact commit, applies the base branch policy, verifies required CI and reviews, saves the decision and publishes a GitHub check. A manual check does not post a PR comment or trigger follow-up automation. The output links to the saved decision and GitHub check.

Exit codes: `0` passed, `1` blocked or needs approval, `2` could not complete, `3` waiting for required CI. After CI finishes, run the command again; a waiting result is not a passing decision.

## Read a saved release decision

```bash
bumpkit decisions view CHECK_OR_DECISION_ID
bumpkit decisions view CHECK_OR_DECISION_ID --json
```

Use the saved release check ID or gate decision ID from Bumpkit. This reads recorded evidence only: repository and exact commit, outcome, policy reasons including CI, approvals and their source, retained policy text, and findings. It does not run a check, generate new evidence, query GitHub, or change a decision. A release check with no saved gate decision is reported as such.

Workspace-scoped read access is sufficient. A foreign workspace's ID returns not found. `--json` preserves the complete recorded response for scripts. Reading a saved failing decision exits successfully; the saved outcome remains `fail`.

`bumpkit approvals` lists the releases waiting for a person's approval, and `bumpkit approvals show ID` shows what one waits on and the votes so far. To vote, run `bumpkit approvals approve ID`, `bumpkit approvals deny ID`, `bumpkit decisions approve CHECK_ID` or `bumpkit decisions deny CHECK_ID`. Each prints a link and a one-time code, opens your browser, and waits while you confirm the vote signed in to Bumpkit; the CLI's API key never votes on its own. The vote needs an active workspace role with write permission, a linked GitHub identity, and eligibility under the saved release's approval policy. The check must refer to the current PR commit; a new push makes an old check ineligible.

When you confirm, the vote is recorded against that exact commit and the shared gate runs again, as for any dashboard vote. Recording a vote does not promise a pass, merge, or deployment. Repeating a vote updates that reviewer's vote rather than creating duplicates. These votes differ from inbox approval actions, and there is no `--note` option.

## bumpkit check

Check a release and list what it proves. The output gives the verdict, the decided version, a summary, each finding above `info` with its location, and the affected areas. See [Release Checks & Blast Radius](/docs/release-checks).

```text
bumpkit check [--base REF] [--head REF|working-tree] [--json]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | The latest tag | Version or ref the release starts from |
| `--head` | `HEAD` | What is being released. `working-tree` includes uncommitted work. |
| `--json` | `false` | Print the full check as JSON |

```bash
bumpkit check --base v1.4.2 --head working-tree
```

### Beta: --comment

| Flag | Default | Description |
|------|---------|-------------|
| `--comment` | `false` | Post or update the check as a pull request comment |

## bumpkit checks

List and view release checks.

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `list` (alias `ls`) | `bumpkit checks list [flags]` | List recent release checks |
| `view` | `bumpkit checks view CHECK_ID` | Show a check's verdict, AI review coverage and findings |
| `queue` | `bumpkit checks queue [--repository OWNER/NAME]` | Show queued, running, retrying and failed pull request checks |

`checks list` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--limit` | `20` | How many to show (max 100) |
| `--repository` | | Only checks of this repository |
| `--recorded` | `false` | Match the Releases page: one row per release with its latest decision, no working-tree previews |

With `--recorded`, Bumpkit groups check runs into releases the way the Releases page does and shows each release's latest decision. Use `--limit 50` to match the page. The default list includes working-tree previews.

`checks queue` lists the GitHub pull request checks that haven't finished yet, plus any whose **Bumpkit release gate** check failed after retries, with the same wording as the **Queued, running, retrying and failed pull request checks** panel on the Checks page:

| State | What it means |
|-------|---------------|
| Queued | Bumpkit received the pull request event and runs the check shortly. |
| Running | Bumpkit is checking the pull request now. |
| Retrying | Bumpkit hit an error and is retrying the check automatically. |
| Failed after retries | Bumpkit couldn't finish the check after several tries. Push a commit or re-run the check on GitHub to try again. |

The `checks_queue` MCP tool returns the same list.

## bumpkit gate

Decide whether a release ships under your policy. In GitHub Actions, `gate` finds the pull request, its base commit and its approving reviews by itself. A branch named `hotfix/`, `hotfixes/`, `release/` or `releases/` (or with `-` instead of `/`) is gated as a hotfix. See [Release Gate](/docs/release-gate).

```text
bumpkit gate [--base REF] [--policy FILE] [--comment] [--json]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | The pull request's base, else the latest tag | Version or ref the release starts from |
| `--comment` | `false` | Post or update the decision as a pull request comment |
| `--hotfix` | Detected from the branch name | Gate this as a hotfix: only fixes allowed, faster checks |
| `--json` | `false` | Print the decision as JSON |
| `--pr` | Detected in CI | Pull request number to gate when the CI isn't detected, for example in Argo Workflows; with the GitHub App, Bumpkit reads its approvals |
| `--output-dir` | | Write the outcome, decision ID, check ID, URL and version to files in this directory, for CI output parameters |
| `--policy` | `bumpkit.yml` as it is at the base | Policy file. With the Bumpkit GitHub App installed, Bumpkit ignores it and reads `bumpkit.yml` from the base itself, so a pull request can't loosen its own rules. Without the App, the decision is marked `policy_source: client`. |

With the GitHub App installed, `--base` only sets what the diff is compared against. Bumpkit reads the policy from the default branch, or from the base commit of a pull request into the default branch.

With Close the loop on (flag `close_the_loop`), `gate` also reports the fix tasks it found in the local checkout, such as callers still on a changed function's old signature, and its output gains a Close the loop section. See [bumpkit loop](#bumpkit-loop).

```bash
bumpkit gate --comment
```

`--comment` only comments from a CI job running for a pull request: GitHub Actions, GitLab CI, Bitbucket Pipelines, Azure Pipelines, Buildkite, CircleCI or Jenkins. Run from a laptop, `gate` can't tell which pull request the checkout belongs to, so it prints the decision and posts nothing. With the Bumpkit GitHub App installed, you don't need `--comment` at all: the App's automatic run on every push posts the single **bumpkit[bot]** comment on the pull request and edits it in place as the decision changes.

### Beta: --spec, --bench-base and --bench-head

> **Beta, early access.** Flags: `intent_check`, `performance_diff`.

| Flag | Default | Description |
|------|---------|-------------|
| `--spec` | | Comma-separated spec files whose acceptance criteria the intent rule maps to evidence. See [bumpkit criteria](#bumpkit-criteria). |
| `--bench-base` | | `go test -bench` output measured at the base, compared with `--bench-head` |
| `--bench-head` | | `go test -bench` output measured at the head |

### Other CI systems

Inside GitLab CI, Bitbucket Pipelines, Azure Pipelines, Buildkite, CircleCI or Jenkins, `gate` reads the merge or pull request, its base and its repository from that CI's variables. It uses the tokens listed under [CI variables](/docs/cli-flags#ci-variables) to read approvals and post `--comment`. See [Run it in CI](/docs/release-gate#run-it-in-ci) for the setup for each.

`bumpkit gate connections` connects GitLab, Bitbucket, Azure DevOps or GitHub Enterprise Server to the release gate (owners and admins). A connection lets Bumpkit run the gate on merge and pull requests there and verify approvals. The access token is stored encrypted. The webhook secret is shown only once, when you add the connection.

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `list` (alias `ls`) | `bumpkit gate connections list` | List connections |
| `add` | `bumpkit gate connections add --provider gitlab\|bitbucket\|azure_devops\|ghes --path PATH [--host URL] [--token TOKEN\|-]` | Add a connection and print its webhook URL and secret |
| `remove` (alias `rm`) | `bumpkit gate connections remove ID` | Remove a connection; its webhook stops working. Owners and admins do this signed in to the dashboard; a key gets a refusal saying where |

`gate connections add` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--provider` | | `gitlab`, `bitbucket`, `azure_devops` or `ghes` |
| `--path` | | `group/project`, `workspace/repository`, `project/repository` or `owner/repository` |
| `--host` | `gitlab.com`, or Bitbucket Cloud | GitLab address, Azure DevOps organization address or GitHub Enterprise Server address |
| `--token` | Prompt | Access token; `-` reads it from stdin |

`gate connections remove` takes `-y`, `--yes` to skip the confirmation.

```bash
bumpkit gate connections add --provider gitlab --path acme/api
```

## bumpkit approvals

List the releases in this workspace that wait for a person's approval: repository, pull request, exact commit, how many votes are in and when it was requested. `bumpkit approvals` with no subcommand is the same as `bumpkit approvals list`.

```bash
bumpkit approvals
bumpkit approvals show APPROVAL_OR_CHECK_ID
bumpkit approvals approve APPROVAL_OR_CHECK_ID
bumpkit approvals deny APPROVAL_OR_CHECK_ID --no-browser
```

`show` prints the rules still asking for approval, from whom, and the votes so far. `approve` and `deny` start a browser confirmation with a one-time code and wait for it; nothing is recorded from the API key alone. `--no-browser` prints the link without opening a browser, and `--timeout` limits the wait. Add `--json` to any of them for the stored fields.

## bumpkit approvals commands list

Read stored agent command decisions for the current workspace without running or re-evaluating commands. Requires a person-bound API key and access to `agent_pause`; workspace viewers can read the list.

```bash
bumpkit approvals commands list --status recent --limit 20
bumpkit approvals commands list --status pending --limit 50
```

`recent` is the default and includes decided commands and expired requests, newest first. `pending` includes only unexpired requests awaiting a decision. Limits range from 1 to 500; omitting `--limit` uses 20 for recent or 50 for pending, matching the dashboard. Add `--json` for stored decision fields and the response time used to label expired requests.

## bumpkit override

A break-glass override needs a person signed in to the dashboard: an owner, admin or policy admin, on the commit's check page. This command sends the request, and the server refuses an API key with `403 HUMAN_APPROVAL_REQUIRED` and the link to the page. An override applies to that exact commit only, so a new push needs a fresh decision. It is kept in the gate decision, the audit log and the compliance evidence. A repository can forbid overrides with `break_glass: false` in `bumpkit.yml`. See [Hotfixes & Break Glass](/docs/hotfixes).

```text
bumpkit override --reason TEXT [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--pr` | The current branch's open pull request | Pull request number; overrides its head commit and re-runs its GitHub check |
| `--reason` | | Why this ships anyway (kept in the audit record) |
| `--repository` | The origin remote | `owner/name` |
| `--sha` | | Full commit SHA, for a commit without a pull request |
| `-y`, `--yes` | `false` | Don't ask for confirmation |

With neither `--pr` nor `--sha`, the command looks up the open pull request for your current branch; if there isn't one, it lists the pull requests waiting on the gate. With both flags, `--sha` must be the pull request's head.

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `list` (alias `ls`) | `bumpkit override list [flags]` | Overrides and whether each has had its post-hoc review |
| `review` | `bumpkit override review OVERRIDE_ID --note TEXT` | Record the post-hoc review of an override (owners, admins, policy admins and approvers; not the person who overrode) |

`override list` flags: `--limit` (default `100`, max 500) and `--overdue` (only overrides whose review is past due). `override review` takes `--note`, what the review found (kept in the audit record).

## bumpkit rules

Write a release rule in plain English. Bumpkit turns it into `bumpkit.yml` gate policy, shows the change as a diff and dry-runs it on recent gate decisions. Nothing takes effect until an owner, admin or policy admin approves it and the pull request that adds it to `bumpkit.yml` is merged, because the gate reads the policy from the base branch.

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `view` | `bumpkit rules view RULE_ID` | Read a saved rule and its proposed policy changes without approving it |
| `compile` | `bumpkit rules compile "RULE" [--dry-run] [--open-pr]` | Compile a plain-English rule into a reviewed policy change |
| `approve` | `bumpkit rules approve RULE_ID [--open-pr]` | Approve a compiled rule (owners, admins and policy admins) |
| `list` (alias `ls`) | `bumpkit rules list [flags]` | Compiled rules, who wrote and approved them, and their pull requests |

`rules compile` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--dry-run` | `false` | Show which recent gate decisions the rule would have changed |
| `--limit` | `50` | How many recent gate decisions the dry run replays (max 200) |
| `--open-pr` | `false` | Approve the rule and open a pull request that adds it (owners, admins and policy admins) |
| `--policy` | `bumpkit.yml` or `.bumpkit.yml` here, else the repository's default branch | The current policy file |
| `--remote-policy` | `false` | Read the default-branch policy through the App; never read a local policy file |
| `--policy-content` | | Use this exact YAML instead of a local or remote policy; mutually exclusive with `--policy` and `--remote-policy` |
| `--repository` | The origin remote | `owner/name` |
| `-y`, `--yes` | `false` | Don't ask for confirmation |

`rules approve` takes `--open-pr` (open a pull request through the Bumpkit GitHub App) and `-y`, `--yes`. `rules list` takes `--limit` (default `50`, max 200).

```bash
bumpkit rules compile "Changes to the payments folder need approval from @acme/payments" --dry-run
```

## bumpkit criteria

> **Beta, early access.** Flag: `intent_check`.

Map a ticket's acceptance criteria to the evidence in a change. Criteria come from the pull request description, the GitHub, Jira or Linear issues it links, and any `--spec` files: Markdown checklists, Acceptance criteria sections and Given/When/Then lines. With `--llm`, Bumpkit's AI extracts them from free-form text instead. Each criterion is mapped to the changed files, the tests touching them and the behavioral verification results for the head, and reported as covered or not evidenced.

This is never a pass or fail on its own. `gate.require_approval: [intent]` asks for an approval when a criterion lacks evidence. Jira needs `JIRA_BASE_URL`, `JIRA_EMAIL` and `JIRA_API_TOKEN`; Linear needs `LINEAR_API_KEY`.

```text
bumpkit criteria [--base REF] [--spec FILE]... [--llm] [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | The pull request's base, else the latest tag | Version or ref the change starts from |
| `--head` | `HEAD` | Commit being released |
| `--llm` | `false` | Extract criteria from free-form text with Bumpkit's AI instead of reading checklists |
| `--spec` | | Spec or ticket text file to read criteria from (repeatable) |

```bash
bumpkit criteria --spec docs/specs/export.md
```

## bumpkit policy

> **Beta, early access.** Flag: `org_policies`.

Show and change the org-wide gate policy. An org policy is a `bumpkit.yml` with an optional top-level `locked:` list of gate keys that repositories may only tighten. See [Org Policies & Freezes](/docs/org-policies).

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `show` | `bumpkit policy show [--effective] [flags]` | Print the org policy, or with `--effective` the policy the gate applies here |
| `set` | `bumpkit policy set [FILE] [flags]` | Save a new org policy version. Owners and admins do this signed in to the dashboard; a key gets a refusal saying where |
| `history` | `bumpkit policy history [flags]` | List the org policy's versions |
| `diff` | `bumpkit policy diff FROM [TO]` | Show what changed between two versions (`TO` defaults to the latest) |

`policy show --effective` merges the org policy with this repository's `bumpkit.yml` (as it is at `--base`, as the gate reads it). It shows each key's value and where it came from: `default`, `org`, `repo` or `org+repo`. A loosened value of a locked key is ignored and explained.

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | `HEAD` | Ref to read `bumpkit.yml` at |
| `--effective` | `false` | Merge the org policy with this repository's `bumpkit.yml` and show where each value came from |
| `--file` | | Read the repository policy from this file instead |
| `--repository` | The origin remote | `owner/name` |

`policy set` saves a new version from `FILE` or exact YAML passed with `--content`, points the org policy at a config repository with `--repository` (its `bumpkit.yml` on the default branch is read at gate time), or removes it with `--clear`. Every version is kept and audited. `--content` is mutually exclusive with `FILE`, `--repository` and `--clear`; parsing and confirmation still apply.

| Flag | Default | Description |
|------|---------|-------------|
| `--clear` | `false` | Remove the org policy (a new, empty version) |
| `-m`, `--message` | | Why it changed (kept with the version and in the audit log) |
| `--repository` | | Read the org policy from this config repository, e.g. `acme/.github` |
| `-y`, `--yes` | `false` | Don't ask for confirmation |

`policy history` takes `--limit` (default `20`).

```bash
bumpkit policy set org-policy.yml --message "Require CI everywhere"
```

## bumpkit freeze

> **Beta, early access.** Flag: `change_freezes`.

Declare, list and end change freezes. While a freeze is on, the gate fails every pull request (with `--mode approve`, it asks for an approval instead). Hotfixes need an approval by default. A break-glass override still lets a specific commit through when the repository allows overrides. Freezes are audited. Owners, admins and policy admins can declare one or end it early. See [Org Policies & Freezes](/docs/org-policies).

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `start` | `bumpkit freeze start --reason TEXT [flags]` | Freeze releases now (or from `--starts`), for every repository or one |
| `list` (alias `ls`) | `bumpkit freeze list` | List current, upcoming and recent freezes |
| `end` | `bumpkit freeze end ID` | End a freeze early. Owners, admins and policy admins do this signed in to the dashboard; a key gets a refusal saying where |

`freeze start` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--for` | | How long it lasts, e.g. `4h` |
| `--hotfix` | `approve` | What hotfixes get: `allow`, `approve` or `block` |
| `--mode` | `block` | `block`, or `approve` to ask for an approval instead |
| `--reason` | | Why releases are frozen (shown on gated pull requests) |
| `--repository` | Every repository | `owner/name` to freeze |
| `--starts` | Now | When it starts, RFC 3339 |
| `--until` | Until ended | When it ends, RFC 3339 |

```bash
bumpkit freeze start --reason "Incident 42: payments degraded" --for 4h
```

## bumpkit blast-radius

> **Beta, early access.** Flag: `blast_radius`.

Show which areas of the product a change reaches, call by call, in any of the [supported languages](/docs/supported-languages). Each area comes with its call path and the file and line of every call.

Areas come from `gate.blast_radius.approve_areas`, the areas in `require_approval`, CODEOWNERS, and otherwise the top-level directory. `gate.blast_radius.max_depth` limits how far callers are followed. See [Release Checks & Blast Radius](/docs/release-checks).

Under the summary line, the report lists any files it didn't analyze, like `4 files over 1 MB not analyzed`. With `--json`, the same lines are in `notes`, the counts are in `skipped`, and `cache` says how many files were reused from earlier runs and how many were read again. See [Files Bumpkit doesn't analyze](/docs/supported-languages#files-bumpkit-doesn-t-analyze).

```text
bumpkit blast-radius [--base REF] [--head REF] [--json] [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | The latest tag | Version or ref the change starts from |
| `--head` | `HEAD` | Commit being released |
| `--policy` | `bumpkit.yml` as it is at the base | Policy file |

```bash
bumpkit blast-radius --base v1.4.0 --head HEAD --json
```

## bumpkit contains

Find a commit by ref or by text in its message, then list every release tag and remote branch that contains it, directly or as a cherry-pick. See [Hotfixes & Break Glass](/docs/hotfixes).

```text
bumpkit contains REF_OR_TEXT
```

```bash
bumpkit contains "null pointer in checkout"
```

## bumpkit predict

> **Beta, early access.** Flag: `regression_predictor`.

Rank the existing functionality a change can break, with a likelihood. Each area the change reaches is ranked against the repository's history: production incidents in that code, releases that changed the same files before an incident, and proven findings. A percentage shows only where Bumpkit has measured one from your releases; otherwise you get the evidence and no percentage.

```text
bumpkit predict [--base REF] [--head REF] [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | The latest tag | Version or ref the change starts from |
| `--head` | `HEAD` | The change's head |

## bumpkit when

> **Beta, early access.** Flag: `release_time_machine`.

Find the first release where a symbol, file, finding or dependency appeared, the commit that introduced it, and what changed it after. `--symbol`, `--file` and `--edge` read this checkout at every release tag. `--kind` and `--text` search the findings of every release Bumpkit checked. See [Rollback & Time Machine](/docs/rollback).

```text
bumpkit when (--symbol NAME | --file PATH | --edge FROM->TO | --kind KIND | --text TEXT) [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--edge` | | A dependency between two areas, `FROM->TO` |
| `--file` | | A file in the repository |
| `--kind` | | A finding kind, like `secret` or `breaking_api` |
| `--path` | | Only findings under this path (with `--kind` or `--text`) |
| `--symbol` | | A function, method or type, like `ParseConfig` or `config.ParseConfig` |
| `--text` | | Text in a finding's title, detail or snippet |

```bash
bumpkit when --edge 'services/api->services/db'
```

## bumpkit quality

> **Beta, early access.** Flags: `architecture_drift`, `slop_tracker`, `performance_diff`.

Show architecture drift, code quality and performance changes between two versions of a codebase in any of the [supported languages](/docs/supported-languages). Each analysis runs when its feature is on for your workspace. `bumpkit gate` sends the same findings with the release, and `gate.quality` decides whether they hold it. See [Code Quality & Architecture](/docs/quality).

| Analysis | What it reports |
|----------|-----------------|
| Architecture | New module dependency cycles, dependencies that break `architecture.layers` and `architecture.forbidden` or reverse the direction seen at the base, fan-out growth, functions above `gate.quality.max_complexity` |
| Code quality | New code copied from elsewhere, interfaces with one implementation, functions that only forward their arguments, new symbols nothing uses, functions above `gate.quality.max_function_lines`, comment-heavy files. The low-value code score sums these up, split by agent. |
| Performance | Queries inside loops, blocking IO and complexity growth on code reached from HTTP handlers, loops and allocations sized by request input, and `go test -bench` regressions between base and head |

```text
bumpkit quality [--base REF] [--head REF] [--bench-base FILE --bench-head FILE] [--json] [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | The latest tag | Version or ref the change starts from |
| `--bench-base` | | `go test -bench` output (or JSON) measured at the base |
| `--bench-head` | | `go test -bench` output (or JSON) measured at the head |
| `--head` | `HEAD` | Commit being released |
| `--policy` | `bumpkit.yml` as it is at the base | Policy file |

```bash
bumpkit quality --base v1.4.0
```

## bumpkit tests

> **Beta, early access.** Flag: `test_evolution`.

List new behavior no test reaches, suggest tests, and find obsolete ones. It lists each new function or method, and each changed one that gained branches, that no test reaches, with its file and lines. With `--coverage`, a function counts as tested only when the profile shows its lines run; otherwise a test must refer to it by name.

Obsolete tests are tests that refer to symbols this release removes and, with `--results`, tests that never failed and never touched changed code in the last `--releases` releases.

```text
bumpkit tests [--base REF] [--head REF] [--coverage FILE] [--results FILE] [--patch FILE] [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | The pull request's base, else the latest tag | Version or ref the release starts from |
| `--coverage` | | Go coverage profile from the head (`go test -coverprofile`) |
| `--head` | `HEAD` | Commit being released |
| `--llm` | `false` | Have Bumpkit's AI write the test bodies (sends each function's source) |
| `--no-upload` | `false` | Don't save the untested and obsolete lists to Bumpkit for the release page |
| `--patch` | | Write the suggested test skeletons to this patch file |
| `--releases` | `10` | How many releases a test must stay quiet to count as obsolete |
| `--results` | | Test results (JUnit XML or `go test -json`) to record, so tests that never fail can be found |

```bash
go test -coverprofile=cover.out -json ./... > results.json
bumpkit tests --coverage cover.out --results results.json --patch tests.patch
```

## bumpkit verify

> **Beta, early access.** Flag: `behavioral_verification`.

Run the base and head side by side in your CI, never on Bumpkit's servers, and compare how they behave. `verify` checks out both versions into separate worktrees and runs:

- the project's test command at both versions (`verify.test`, or detected from `go.mod`, `package.json` or `pyproject.toml`)
- for Go, each changed exported function called with the same generated inputs at both versions
- for HTTP services (`verify.http.start`), recorded requests (`verify.http.requests`) and requests derived from the OpenAPI spec, replayed against both versions on separate localhost ports
- with Playwright, `verify.browser.pages` compared by text, DOM structure and screenshot

Commands run with a time limit (`verify.timeout`), CPU and memory limits where the operating system supports them, and a safe set of environment variables. Unless `verify.network` is `allow`, they get no network beyond localhost: in a network namespace on Linux when `unshare` is available, and otherwise through proxy settings that point nowhere and offline package managers. The report records which isolation ran. The report is uploaded signed with the API key. In GitHub Actions with `id-token: write`, it is also attested by the job's OIDC token. `gate.require_checks: [behavior]` requires the report and, by default, accepts only an attested one: the gate uses the latest attested report for the commit, so a later report signed only with a key neither replaces nor blocks it. With the GitHub App installed, a report doesn't count if the pull request changes what that CI run executes (anything under `.github/`, or a local action or script the default branch's workflow names), or if it comes from a merge commit that isn't that pull request's current one. The workflow still runs the pull request's own code and tests. `verify.require_ci_attestation: false` in your repository's policy opts out and trusts anyone with a key. A regression or a failing test fails; a changed response or return value needs a person's approval.

```text
bumpkit verify [--base REF] [--head REF] [--no-upload] [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | The pull request's base, else the latest tag | Version or ref to compare against |
| `--config` | `bumpkit.yml` as it is at the base | File with the verify settings |
| `--head` | The pull request's head, else `HEAD` | Commit being released |
| `--no-upload` | `false` | Compare locally without sending the report to Bumpkit |

## bumpkit history

List releases that changed the repository or a path. With `--tree`, print the version tree instead.

```text
bumpkit history [PATH] [--tree] [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--limit` | `20` | How many to show (max 100) |
| `--repository` | The origin remote | Repository URL |
| `--tree` | `false` | Print the version lineage with deploys, incidents and rollbacks |

`--tree` shows every release Bumpkit checked, newest first: its commit range, verdict and gate outcome, the environments it's live in (`●`) or was live in, the incidents traced to it, and the rollback pull requests that undo it.

```text
acme/shop
Live now: production v1.0.0 since 2026-10-23, staging v1.2.0 since 2026-10-23
● v1.2.0  live in staging  was live in production
│ 2026-10-23  v1.1.0…3c9e1f2  1 commit  Looks safe, gate: Ready to ship
│ ↩ Roll back to v1.0.0 (fix_opened) https://github.com/acme/shop/pull/12
│
○ v1.1.0  was live in production
│ 2026-10-22  v1.0.0…8d1a4b7  2 commits  Looks safe, gate: Ready to ship
│ ! Checkout totals are 10% short
│
● v1.0.0  live in production
  2026-10-21  v0.9.0…5f2e0c1  1 commit  Looks safe
```

## bumpkit loop

> **Beta, early access.** Flag: `close_the_loop`.

Show what Bumpkit found, who it routed it to, the fix it opened, and what proved it done. Every rollback, back-port and fix task has a lifecycle: found, routed (to whom), fix opened (the pull request), and verified (by which gate decision, at which commit), or still open. Open items are listed by default.

A fix task comes from a gate run that left callers on an old contract: it lists each caller by file and line, the symbol change and the expected edit. When the change is mechanical (a rename, or one removed parameter, with every caller in the repository), Bumpkit opens the edit as a pull request into the author's branch; otherwise it routes the task to the authoring agent and the pull request. Only a later gate run marks a task verified, once it proves every listed place clean. Go code is analyzed today. `gate.fix_tasks` (`block`, `approve` or `off`) decides what open tasks do to the gate; see the [bumpkit.yml Reference](/docs/bumpkit-yml).

```text
bumpkit loop [--branch BRANCH | --mine] [--check ID] [--kind rollback|backport|fix_task] [--all] [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--all` | `false` | Include verified items |
| `--branch` | | Only fix tasks on this branch |
| `--check` | | Only items for this release check |
| `--kind` | | `rollback`, `backport` or `fix_task` |
| `--mine` | `false` | This checkout's repository and branch |
| `--repository` | | Only this `owner/name` |

```bash
bumpkit loop --all
```

```text
rollback Roll back v1.1.0 for Checkout total is 10% short  acme/shop (fix_opened)
  Pull request: https://github.com/acme/shop/pull/1
  Routed to: reviewers of https://github.com/acme/shop/pull/1
  d464ec7 feat: launch 10% discount on every price
  2026-10-23 14:45  found      Regression in v1.1.0 (incident f6fb0ef)
  2026-10-23 14:45  fix_opened Opened https://github.com/acme/shop/pull/1 reverting d464ec7 onto main
```

## Playground previews

Run the same built-in sample and edited policy as the dashboard Playground, from any directory. A connected repository is not required. The hosted preview uses your signed-in user's workspace and feature access, applies the same usage and rate limits, and does not save a release decision or post to a code host.

```sh
bumpkit playground examples
bumpkit playground run --example session-token
bumpkit playground run --example agent-breaking --policy bumpkit.yml --json
bumpkit playground run --example drop-column --policy-stdin <<'BUMPKIT_POLICY'
gate:
  block_on: [secret, data_loss]
BUMPKIT_POLICY
```

Available example IDs are `session-token`, `drop-column`, `stripe-key`, and `agent-breaking`. Omit the policy flags to use the dashboard's default Playground policy. An explicitly supplied empty policy stays empty.

For a custom diff, pipe the diff to `--diff-stdin` and supply the policy as a file:

```sh
git diff main..HEAD | bumpkit playground run --diff-stdin --policy bumpkit.yml --message 'fix: update validation' --previous 1.2.3
```

When both the diff and edited YAML must come through stdin, use `--request-stdin` with one JSON object containing `diff`, `message`, `policy`, and `previous`, or `example`, `policy`, and `previous`. This mode cannot be combined with the other input flags. Stdin and policy text are treated as data; Bumpkit does not execute pasted scripts or repository commands.

`--json` prints the gate decision, findings, version, report preview, optional blast radar, checked diff, and explicit `preview`, `saved`, and `posted` flags. Exit codes are **0** for pass, **1** for fail or needs approval, and **2** when the preview cannot run. Built-in examples use the sample's previous version unless `--previous` overrides it. Limits are 1 MiB for diff, 32 KiB for policy, 16 KiB for commit message, and 64 bytes for previous version.
