# CLI: Releases

Cut, ship, announce and roll back releases.

## bumpkit analyze

Write the changelog and suggest the next version together.

```text
bumpkit analyze [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--format` | `markdown` | Changelog format: `markdown`, `keepachangelog`, `slack` or `json` |
| `--from` | The latest tag | Tag or ref the release starts from |
| `--to` | `HEAD` | Ref the release ends at |

## bumpkit bump

Suggest the next version from the commits since the last tag.

```text
bumpkit bump [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--from` | The latest tag | Tag or ref the release starts from |
| `--to` | `HEAD` | Ref the release ends at |

## bumpkit changelog

Write a changelog from the commits since the last tag.

```text
bumpkit changelog [flags]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--format` | `markdown` | `markdown`, `keepachangelog`, `slack` or `json` |
| `--from` | The latest tag | Tag or ref the release starts from |
| `--to` | `HEAD` | Ref the release ends at |

## bumpkit release

Grouped releases, and how a deployed release is doing in production.

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `prepare` | `bumpkit release prepare [--repo owner/name]` | Group everything merged to the default branch since the last release tag into one draft release |
| `list` | `bumpkit release list [--repo owner/name] [--status draft\|approved\|published\|denied] [--limit N]` | List grouped releases, newest first (`--limit` up to 100, default 20) |
| `show` | `bumpkit release show RELEASE_ID [--audience customer]` | Show a release's version, pull requests, commits, verdict, publish status and one audience's notes (`customer` by default) |
| `notes` | `bumpkit release notes RELEASE_ID --audience customer (--file notes.md \| --regenerate)` | Replace one audience's notes from a file or stdin, or write them again. Approved releases: owners, admins, policy admins and approvers only |
| `correct` | `bumpkit release correct RELEASE_ID --audience customer --file notes.md --reason "..."`, or `bumpkit release correct --version v1.2.0 [--repo owner/name] --file entry.md --reason "..."` | Correct the notes of a published release everywhere they were published, or an older changelog entry by its version. Owners and admins only; `--reason` (at least 10 characters) is required |
| `approve`, `deny` | `bumpkit release approve RELEASE_ID [--no-browser] [--timeout 10m]` | Vote on a draft after you confirm in the browser |
| `publish` | `bumpkit release publish RELEASE_ID` | Publish an approved release |
| `health` | `bumpkit release health VERSION [flags]` | Compare errors after a deploy with before, and name the top suspect commit |
| `health-settings` | `bumpkit release health-settings view`, `set [--window 15-1440] [--min-events 1-100000] [--posthog-repository owner/name] [--posthog-environment ENV]` | Read or change release health settings (`set`: owners and admins) |

### Grouped releases

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

`release prepare` finds the last release tag (or the first commit when there is none), lists the merged pull requests and commits, runs one check over the whole range, and suggests the version and notes. Preparing again refreshes the open draft. Approving is a person's call, so an API key can't do it on its own: `release approve` and `release deny` print a link and a one-time code, and the vote counts once you confirm it signed in to Bumpkit. `release show --audience` prints the notes that audience gets, and `release notes` replaces or regenerates them before you publish. `release publish` creates the tag and GitHub Release and updates the public changelog with the customer notes, posts the engineering notes to Slack, and updates any connected Notion or Confluence page with the engineering notes; `settings set --publish-audience` changes that. Each target is tried on its own: run it again to retry only the ones that failed. It exits `1` while a target still fails. Once a release is published, `release correct` fixes its notes: it updates the stored notes, the public changelog entry and RSS feed, the GitHub Release and any Notion or Confluence page that got them, and reports each target on its own. Slack messages aren't edited. Run it again to retry a target that failed; it exits `1` while one still fails. See [Grouped releases](/docs/release-trains#grouped-releases) and [Correct published notes](/docs/release-notes#correct-published-notes).

### Release health

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

See [Release Health & Forensics](/docs/release-health).

`release health` compares the production error rate after `VERSION` went live with the window before it. It flags new and spiking errors, and names the commits most likely behind them. It exits `1` when the release regressed.

| Flag | Default | Description |
|------|---------|-------------|
| `--environment` | `production`, else the latest deploy | The environment |
| `--min-events` | The workspace setting | Errors needed after the deploy to call a regression |
| `--repository` | The origin remote | `owner/name` |
| `--window` | The workspace setting | Minutes before and after the deploy to compare |

```bash
bumpkit release health v2.3.0 --environment staging --window 30 --json
```

## bumpkit train

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

Group pull requests into a named release, see readiness across them, and cut it. Pull requests join a train when they carry its label (`train:<slug>` unless `train.label` in `bumpkit.yml` or `--label` says otherwise), belong to its `--milestone`, or are added with `bumpkit train add`. See [Release Trains](/docs/release-trains).

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `new` | `bumpkit train new NAME [--branch main] [--label L] [--milestone M]` | Start a release train |
| `list` | `bumpkit train list [--status open]` | List release trains |
| `sync` | `bumpkit train sync TRAIN` | Refresh batch membership, pull request states and Bumpkit status comments on GitHub; does not approve, merge or publish |
| `show` | `bumpkit train show TRAIN` | Show a train's readiness: every pull request's gate decision and health, and the verdict |
| `add` | `bumpkit train add TRAIN PR` | Add a pull request to a train |
| `remove` | `bumpkit train remove TRAIN PR` | Take a pull request off a train |
| `approve` | `bumpkit train approve TRAIN` | Explain how a person approves a release batch in the dashboard; a key is refused |
| `cut` | `bumpkit train cut TRAIN [--break-glass REASON] [--yes]` | Explain how a person cuts a release batch in the dashboard; a key is refused |
| `multi new` | `bumpkit train multi new NAME --repo OWNER/NAME --repo OWNER/OTHER [--milestone M]` | Start a multi-repo train with one step per repository |
| `multi list` | `bumpkit train multi list` | List multi-repo trains |
| `multi show` | `bumpkit train multi show TRAIN` | Show a multi-repo train: the order and why, and each repository's gate result and state |
| `multi sync` | `bumpkit train multi sync TRAIN` | Refresh every step's pull requests from GitHub; one repository failing doesn't stop the others |
| `multi order` | `bumpkit train multi order TRAIN REPOSITORY...` | Explain how a person sets a multi-repo train's order in the dashboard; a key is refused |
| `multi abandon` | `bumpkit train multi abandon TRAIN [--yes]` | Abandon a multi-repo train and every step that hasn't released; owners and admins only |
| `map` | `bumpkit train map` | Show the service map: each service's health, last release and dependencies |

Every subcommand takes `--repository` (`owner/name`, default: the origin remote).

| Flag | Subcommand | Description |
|------|------------|-------------|
| `--branch` | `new` | The branch the train ships (default: the repository's default branch) |
| `--label` | `new` | The pull request label that joins it |
| `--milestone` | `new` | A milestone whose pull requests join it |
| `--status` | `list` | Only trains in this status: `open`, `ready`, `blocked`, `cut` or `abandoned` |
| `--head` | `add` | The pull request's head commit, when the Bumpkit GitHub App can't read it |
| `--break-glass` | `cut` | Sent with the request, which an API key has refused. Owners and admins give the reason on the batch page in the dashboard |
| `-y`, `--yes` | `cut` | Cut without asking |

`train multi` and `train map` are early access under the `multi_repo_trains` flag; see [Release across repositories](/docs/release-trains#release-across-repositories).

`train approve` and `train cut` need a person signed in to the dashboard, so with an API key they print a `HUMAN_APPROVAL_REQUIRED` refusal with the link to the batch page. On that page, an approval covers the batch as it is now: adding a pull request or pushing to one changes the members, and approvals of the old members stop counting. A cut versions every commit on the train's branch since the last release tag, writes one changelog entry named after the train, and creates the tag and GitHub Release through the Bumpkit GitHub App, or runs `train.release_workflow` from `bumpkit.yml` instead. Starting it again returns the same cut.

```text
bumpkit train new "Agent swarms"
bumpkit train add "Agent swarms" 482
bumpkit train show "Agent swarms"
```

## bumpkit deploy

> **Beta, early access.** Flag: `release_health` or `forensics`.

Record that a version went live, with the commits it shipped. The optional `record` word is accepted: `bumpkit deploy record` is the same command. See [Release Health & Forensics](/docs/release-health).

```text
bumpkit deploy [record] [--environment production] [--sha SHA] [--version V]
```

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | The tag before the commit | The previous release, to send the commits it shipped |
| `--environment` | `production` | The environment the commit was deployed to |
| `--finished-at` | Now | When the deploy finished (RFC 3339) |
| `--no-changes` | `false` | Don't send the commits and changed lines |
| `--repository` | The origin remote | `owner/name` |
| `--sha` | `HEAD` | The deployed commit |
| `--started-at` | | When the deploy started (RFC 3339) |
| `--status` | `success` | `success`, `failure` or `in_progress` |
| `--version` | A tag on the commit | The version that went live, e.g. `v2.3.0` |

```bash
bumpkit deploy --environment production --version v2.3.0
```

## bumpkit hotfix

Cut and track hotfix releases. See [Hotfixes & Break Glass](/docs/hotfixes).

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `version` | `bumpkit hotfix version [--from TAG]` | Print the next free patch version for a hotfix |

`hotfix version` prints the next patch version after the latest release tag reachable from `HEAD`, or after `--from`. Versions that already exist locally or on origin are skipped.

| Flag | Default | Description |
|------|---------|-------------|
| `--from` | The latest version tag reachable from `HEAD` | Release tag to patch |

## bumpkit backport

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

Open the cherry-pick pull request for a shipped hotfix that's missing from main or a release branch. Bumpkit fetches the repository through its GitHub App, cherry-picks the hotfix onto the tip of `--onto`, and opens the pull request on `bumpkit/backport/<sha7>-to-<branch>`. The commit keeps `(cherry picked from commit <sha>)`, so the missing back-port check clears once it merges. If the cherry-pick conflicts, Bumpkit opens nothing: the error names the conflicting files and the hotfix's author, and the release stays gated. There is one pull request per hotfix and branch, and Bumpkit never merges it. Members and above can open one. See [Hotfixes & Break Glass](/docs/hotfixes).

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `open` | `bumpkit backport open COMMIT [--onto BRANCH] [--repository OWNER/NAME] [--check CHECK_ID]` | Cherry-pick a shipped hotfix onto main or a release branch as a pull request |

| Flag | Default | Description |
|------|---------|-------------|
| `--onto` | The default branch | Branch the hotfix is missing from |
| `--repository` | The origin remote | `owner/name` |

```text
$ bumpkit backport open 5322103231 --onto main
Error: Bumpkit API error (HTTP 409): Cherry-picking 5322103 (fix: charge 8% sales tax) onto main conflicts in billing/tax.go, so Bumpkit opened nothing. Sam Rivera <sam@acme.test> shipped it and needs to back-port it by hand; the release stays gated until it lands.
```

Use `--check CHECK_ID` to associate a backport with a saved release check. Bumpkit uses that check’s repository and requires the commit to match its checked head or a recorded `missing_backport` finding. A conflicting `--repository` is refused. Without `--check`, `--repository` or the current origin selects the repository.

## bumpkit rollback

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

Plan the smallest revert that undoes a regression, and open it. See [Rollback & Time Machine](/docs/rollback).

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `plan` | `bumpkit rollback plan [--base REF] [--head REF] [--incident ID \| --error TEXT]` | Rank the commits behind a regression and dry-run the smallest revert |
| `open` | `bumpkit rollback open (PLAN_ID\|INCIDENT_ID\|RELEASE \| --to VERSION) [--branch main] [--yes]` | Open the revert pull request for a rollback plan, an incident, a release, or back to a version |

`rollback plan` ranks every commit between `--base` and `--head` by evidence that it caused the failure. It then reverts the smallest set of commits that explains the failure, plus later commits that depend on them, with `git revert --no-commit` in a temporary worktree. Nothing in your checkout changes. With `--incident`, the stack trace and the regressed release come from that incident.

| Flag | Default | Description |
|------|---------|-------------|
| `--base` | The incident's suspect release, else the tag before `--head` | The last good release |
| `--commit` | | A commit to revert regardless of evidence (repeatable) |
| `--error` | | The error message and stack trace |
| `--file` | | A file in the failure (repeatable) |
| `--head` | The incident's suspect release, else `HEAD` | The regressed release |
| `--incident` | | An incident Bumpkit recorded |

`rollback open` takes a plan id, an incident id, a check id or a release version like `v1.5.0`. Saved check and incident targets use their recorded repository even when your current checkout belongs to another repository. `--repository owner/name` must match that recorded repository; conflicting overrides are refused. For a release version, `--repository` selects the repository explicitly, otherwise the origin remote is used. With a plan id, it re-runs the revert in a temporary worktree and, if it still applies cleanly, Bumpkit opens the pull request through the Bumpkit GitHub App. With an incident, a check or a release (Beta, flag `close_the_loop`), Bumpkit plans and reverts on its side: it fetches the repository through the GitHub App, ranks the regressed release's commits by the incident's evidence, reverts them on the tip of `--branch`, and opens the pull request on `bumpkit/rollback/incident-<id>` or `bumpkit/rollback/<release>`. With no evidence pointing at specific commits, it reverts the whole release (up to 20 commits). If the revert conflicts, nothing opens and the error names the files.

With `--to v1.0.0` (Beta, flag `close_the_loop`), Bumpkit takes the branch back to that release: it reverts every non-merge commit in the releases it checked after `v1.0.0`, up to the newest checked release on `--branch`, as one pull request on `bumpkit/rollback/to-v1.0.0`. Commits after that release that no checked release shipped stay. It prints the releases and commits first and asks before it opens anything. At most 100 commits and 300 changed files; over that, or on a conflict, nothing opens and the error gives the `git revert` command.

There is one rollback pull request per incident, release or `--to` version: running it again returns the open one. The gate runs on it like any pull request, and Bumpkit never merges it. Only a workspace owner or admin can open a rollback, and it's in the audit log.

| Flag | Default | Description |
|------|---------|-------------|
| `--branch` | The origin's default branch | Branch the revert merges into |
| `--repository` | The origin remote | `owner/name`; must match a saved check's or incident's repository |
| `--to` | | Take the branch back to this release, like `v1.0.0` |
| `-y`, `--yes` | `false` | Approve without asking |

```bash
bumpkit rollback plan --base v1.4.0 --head v1.5.0 --error "$(cat trace.txt)"
bumpkit rollback open --to v1.0.0
```

## bumpkit notes

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

Generate, review and export saved release notes, or manage audiences, customer segments and feature tags. See [Release Notes & Digests](/docs/release-notes).

```bash
bumpkit notes list --repository acme/shop
bumpkit notes generate CHECK_ID --audience customer
bumpkit notes view CHECK_ID --output release-notes.md
```

Choose a check ID from `notes list`, which lists recorded checks and excludes working-tree checks. `notes generate` uses `POST /checks/{id}/notes` to generate and save a draft, or reuse an existing one. Add `--regenerate` only when you intend to replace that saved audience and segment draft.

`notes view` reads an existing saved draft without generating or replacing it. The dashboard's Markdown download also reads the saved draft only. Neither action publishes notes or sends messages.

Generating notes requires a writer identity: sign in with `bumpkit login`, or use an API key created by an active workspace member with write access. Legacy keys without an owning member cannot generate notes. Active workspace viewers and read-only users can view saved notes.

Both `generate` and `view` print the Markdown body to stdout by default. `--output FILE` atomically writes the exact saved body with owner-only permissions, and only after a successful API response; an API failure leaves an existing file unchanged and does not create a missing file. Use `--json` for the full response instead. Combining `--json` with `--output` is rejected before an API request.

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `list` | `bumpkit notes list [--repository REPOSITORY] [--limit 20]` | List recorded checks with their IDs |
| `generate` | `bumpkit notes generate CHECK_ID [flags]` | Generate and save a draft, or reuse an existing draft |
| `view` | `bumpkit notes view CHECK_ID [flags]` | Print or export a saved draft without generating it |
| `config` | `bumpkit notes config` | Show audiences, segments and feature tags |
| `audience set` | `bumpkit notes audience set KEY [flags]` | Create or change an audience |
| `audience delete` | `bumpkit notes audience delete KEY` | Delete an audience, or reset a built-in one |
| `segment set` | `bumpkit notes segment set KEY [flags]` | Create or change a customer segment |
| `segment delete` | `bumpkit notes segment delete KEY` | Delete a segment |
| `feature set` | `bumpkit notes feature set NAME [flags]` | Tag a product feature by path or keyword |
| `feature delete` | `bumpkit notes feature delete NAME` | Delete a feature tag |

`notes generate` and `notes view` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--audience` | `customer` | Audience key, such as `engineering`, `customer`, `leadership`, `support`, `security` or one you defined |
| `--segment` | | Customer segment key; omit for the audience's unsegmented draft |
| `--output` | | Write the exact saved Markdown body to a file |
| `--regenerate` | `false` | Generate only: explicitly replace the saved draft |

`notes audience set` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--exclude` | | Path globs to leave out, e.g. `vendor/**` |
| `--hide-paths` | `false` | Never show file paths to this audience |
| `--name` | | The audience's name |
| `--sections` | | Sections to include: `breaking`, `new`, `improved`, `fixed`, `security`, `database`, `config`, `dependencies`, `risk`, `internal` |
| `--tone` | | How the notes should read |

`notes segment set` flags: `--features` (features the segment uses), `--name` (the segment's name), `--plan` (the plan these customers are on). `notes feature set` flags: `--keywords` (words in changelog lines that belong to the feature), `--paths` (path globs that belong to the feature).

## bumpkit digest

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

Weekly digests: what shipped, what's risky and which agent did what. See [Release Notes & Digests](/docs/release-notes).

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `set` | `bumpkit digest set REPOSITORY --day mon --time 09:00 --to slack [flags]` | Create or change the digest for a repository |
| `list` | `bumpkit digest list` | List digest schedules |
| `preview` | `bumpkit digest preview ID\|REPOSITORY` | Print the digest as it would be sent now |
| `send` | `bumpkit digest send ID\|REPOSITORY` | Send the digest now |
| `delete` | `bumpkit digest delete ID [-y]` | Delete a digest schedule; `-y`, `--yes` skips the confirmation |

`digest set` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--day` | `mon` | Day of the week, `sun` to `sat` |
| `--email` | | Email addresses for the email target |
| `--paused` | `false` | Save the schedule without sending |
| `--time` | `09:00` | Time of day, `HH:MM` |
| `--timezone` | `UTC` | Timezone, for example `America/New_York` |
| `--to` | | `slack`, `discord`, `email` |

## bumpkit docs

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

Release docs: engineering notes, customer notes and a migration guide. See [Release Notes & Digests](/docs/release-notes).

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `view` | `bumpkit docs view CHECK_ID [flags]` | Print a release's docs |
| `publish` | `bumpkit docs publish CHECK_ID --to TARGET[,TARGET]` | Publish a release's docs to the changelog, GitHub Releases, Slack or Discord |

`docs view` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--part` | | Only `engineering`, `customer` or `migration` |
| `--regenerate` | `false` | Write the docs again from the latest evidence |

`docs publish` needs a key created by an owner, admin, policy admin, approver or member. Other roles and keys not tied to a person get `403 ROLE_REQUIRED`.

`docs publish` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--to` | | `changelog`, `github_release`, `slack`, `discord`; with the `notion_confluence` flag and a connection, also `notion` and `confluence` |

### Beta: docs notes, guide and Notion or Confluence

> **Beta, early access.** Flags: `audience_notes`, `consumer_migration_guide`, `notion_confluence`.

| Subcommand | Usage | Description |
|------------|-------|-------------|
| `notes` | `bumpkit docs notes CHECK_ID [flags]` | Generate or reuse a release's notes for one audience: engineering, customer, leadership, support, security or your own |
| `guide` | `bumpkit docs guide CHECK_ID` | Print what consumers of a breaking release must change |
| `connect` | `bumpkit docs connect notion\|confluence --token-env NAME --parent PAGE_OR_SPACE [flags]` | Connect Notion or Confluence with an integration token |
| `connections` | `bumpkit docs connections` | List Notion and Confluence connections |
| `disconnect` | `bumpkit docs disconnect notion\|confluence` | Disconnect Notion or Confluence |

`docs notes` generates or reuses a saved draft; it is not a cached-only read. Use `bumpkit notes view CHECK_ID` when you only want an existing draft.

`docs notes` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--audience` | `customer` | `engineering`, `customer`, `support`, `security` or an audience you defined |
| `--regenerate` | `false` | Write the notes again from the latest evidence |
| `--segment` | | A customer segment you defined |

`docs connect` flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--email` | | Atlassian account email, for Confluence Cloud API tokens |
| `--parent` | | Notion parent page link, or Confluence space key |
| `--parent-page` | | Confluence parent page id |
| `--site` | | Confluence site address, e.g. `https://acme.atlassian.net` |
| `--token-env` | | Read the Notion integration token, Confluence API token or personal access token from this environment variable |
| `--token-file` | | Read the token from a private file |
| `--token-stdin` | `false` | Read the token from stdin |
| `--token` | | Legacy; prefer the three above. `-` reads stdin |
