Configuration
bumpkit.yml Reference
Every key in bumpkit.yml, the policy file the release gate, agent hooks and checks read, with types, defaults and allowed values.
Release rules that live in people's heads aren't applied the same way twice; bumpkit.yml writes them down as policy, for whoever owns how a repository ships.
bumpkit.yml is the policy file for your repository. The Release Gate reads its gate: section to decide whether a release passes, needs approval or fails. Other top-level sections configure Agent Controls, Code Quality & Architecture and behavioral verification.
This page lists every key. Feature guides show the snippets you need and link back here.
Example
The Run a check tab on the dashboard's Checks page has a YAML editor and an expandable guide to the main policy fields. This is an editor for the actual policy, not a second rule format: indentation, YAML structure and rule names are validated when you run the check. Editing the trial policy does not save a repository policy or change the base branch.
This file uses every key. You won't need most of them: start from the default policy and add what your team asks for. Keys marked # Beta are covered by their own Beta sections below.
gate:
block_on: [secret, data_loss]
on_error: fail
require_approval:
- breaking
- area: [billing, authentication]
when: agent
approvers: ["@acme/payments", alice]
count: 2
- untested: true
when: agent_or_unknown
codeowners: true
- contract_breaking # Beta
- intent # Beta
- agent_track_record_below: 0.8 # Beta
min_releases: 3
work_types: [migrations]
require_checks: [test, lint]
security_alerts: high
vulnerabilities: high
break_glass: true
hotfix:
block_on: [breaking, data_loss, migration]
max_files: 20
review_within: 72h
backports: approve
blast_radius: # Beta
approve_areas: [billing, "@acme/payments"]
max_depth: 4
deploy: # Beta
environments: [production]
require: approved
timezone: America/New_York # Beta
windows: # Beta
- days: [mon-thu]
from: "09:00"
to: "16:00"
outside_windows: approve # Beta
freezes: # Beta
- name: Year-end freeze
start: 2026-12-20
end: 2027-01-02
mode: block
hotfix: approve
exports: # Beta
severity: high
ignore_paths: [generated/**]
max_findings: 100
behavior: # Beta
changes: approve
hotspots: approve
severity: medium
hotspots_min: medium
quality: # Beta
architecture_drift: block
code_quality:
action: approve
severity: medium
when: agent
performance: warn
max_function_lines: 80
max_complexity: 15
clone_tokens: 40
hot_path_depth: 4
bench_threshold: 5
cross_repo: # Beta
block_on_consumer_break: false
require_approval: true
fix_tasks: block # Beta
require_regression_evidence: true # Beta
regression_evidence_action: block # Beta
stacks: # Beta
require_parent_merged: false
architecture: # Beta
layers:
- name: api
paths: [services/api]
- name: store
paths: [services/db]
forbidden:
- from: store
to: api
agents: # Beta
claude-*:
max_open_prs: 2
max_changed_lines: 400
paths_allow: [services/notify/**]
paths_deny: [services/billing/**]
areas_deny: [billing]
spend_limit: 10
on_violation: block
agent: # Beta
ask: [rm_rf, "npm publish *"]
deny: [force_push]
allow: ["rm -rf ./dist*"]
protected_branches: [main, "release/*"]
remote: true
timeout: 30s
memory: # Beta
require_approval: true
verify: # Beta
test: go test ./...
timeout: 10m
network: localhost
http:
start: ./bin/server
ready: /healthz
require_ci_attestation: true
train: # Beta
label: "train:{slug}"
require_approval:
teams: ["@acme/release-managers"]
count: 1File name and location
Put the file at the root of your repository. Bumpkit looks for bumpkit.yml first and then .bumpkit.yml, and uses the first one it finds. If both exist, .bumpkit.yml is ignored.
All keys are lowercase with underscores. The gate rejects keys it doesn't know at the top level and under gate:, agent:, agents:, memory: and architecture:, so a typo such as requre_approval is an error, not a silently ignored line. Keys under train: and verify: are checked by their own features when they read the file, not by the gate.
Policy from the base commit
The gate reads bumpkit.yml as it is at the base of the change, never from the pull request itself. A pull request that edits bumpkit.yml can't loosen the rules it's judged by; its new policy applies to the pull requests after it merges. With the GitHub App, a pull request into any branch other than the default branch uses the default branch's copy, so a branch can't loosen the rules either.
| Where the gate runs | Policy it reads |
|---|---|
| Bumpkit GitHub App | bumpkit.yml at the base commit of a pull request into the default branch, and on the default branch for every other pull request |
bumpkit gate (CLI, locally or in CI) |
bumpkit.yml at --base, which defaults to the pull request's base commit, else the latest tag before HEAD^. --policy FILE reads a file instead |
POST /v1/gate |
The policy text you send in the request body |
| Deployment protection (deploy) | bumpkit.yml on the default branch, with your org policy applied |
A GitHub Enterprise Server connection, through its webhook, bumpkit gate or POST /v1/gate |
bumpkit.yml from your server: on the default branch, or at the base commit of a pull request into the default branch |
bumpkit gate or POST /v1/gate with the GitHub App installed on the repository for your workspace |
Bumpkit applies the bumpkit.yml it reads from GitHub itself, not the policy that was sent: on the default branch, or at the base commit of a pull request into the default branch. --base never picks the policy. If GitHub can't return it, 503 POLICY_UNAVAILABLE |
The decision's policy_source says which applied: base_branch:<ref> (like base_branch:main) or client. A client policy carries a policy_source: client reason, because it wasn't verified from the base branch. See The policy comes from the base.
See the CLI Reference and API Reference for the flags and request fields.
Default policy
If the repository has no bumpkit.yml, the file is empty, or the file has no gate: section, the gate applies this policy:
gate:
block_on: [secret, data_loss]
require_approval:
- breaking
- area: [authentication, authorization, billing, cryptography]
when: agent
- untested: true
when: agent
vulnerabilities: high
on_error: failOnce you write a gate: section, it replaces the default as a whole: block_on and require_approval you leave out are empty, and vulnerabilities you leave out is off, not inherited from the default. Copy the default rules you want to keep. Keys that have their own default keep it when you leave them out: on_error is fail, break_glass is true, hotfix.block_on is [breaking, contract_breaking, data_loss, migration], hotfix.backports is approve, hotfix.review_within is 72h and, with Close the loop, fix_tasks is block.
Invalid policy
An invalid bumpkit.yml never falls back to the default. The gate fails closed and shows the parse error with its line number:
- The GitHub App completes the check as a failure titled "Invalid bumpkit.yml". If it can't read the file at all, the check fails as well.
bumpkit gateprints the error and exits with code2, even whenon_error: pass.POST /v1/gatereturns400with the codeINVALID_POLICY.- Deployment protection rejects the deployment.
Errors name the key, for example bumpkit.yml: gate.hotfix.backports must be block, approve or off. To try an edited file before you merge it, run bumpkit gate --policy bumpkit.yml, which uses that file instead of the base copy. See the CLI Reference.
gate
The gate: mapping holds the release gate policy. Every key in the sections below, up to architecture, lives under gate:.
A gate decision is pass, needs_approval or fail. Only proven findings count: block_on, require_approval and hotfix.block_on apply to findings that are deterministic and not suppressed. Blast radius and quality findings are built by Bumpkit's own checkers, so they always count as deterministic. See Release Checks & Blast Radius for the finding kinds.
block_on
Finding kinds that fail the release outright. A finding fails the gate when it is high severity, deterministic and not suppressed.
| Type | list of strings |
| Default | [secret, data_loss, security_regression] with no gate: section; empty otherwise |
| Allowed values | secret, data_loss, security_regression, breaking, contract_breaking (Beta), version_mismatch (Beta), compatibility_break (Beta) |
gate:
block_on: [secret, data_loss, breaking]security_regression comes from the security regression check. contract_breaking comes from Contract Checks. version_mismatch comes from the version consistency check, which compares the decided version with your tags, package manifests, VERSION file and CHANGELOG headings. compatibility_break comes from the compatibility matrix: a proven break of a pair you declared as supported.
require_approval
Rules that ask a person to approve a release. Each rule that applies and is triggered needs approval; until it has enough, the decision is needs_approval.
| Type | list of rules; each rule is a string or a mapping |
| Default | The three rules in the default policy with no gate: section; empty otherwise |
A rule written as a string uses when: always:
| String | Triggered by |
|---|---|
breaking |
A high-severity breaking change (a removed or changed public API or route), or a major version bump |
untested |
An untested-change finding |
contract_breaking |
A high-severity breaking API contract change (Beta) |
intent |
An acceptance criterion with no evidence (Beta) |
scanner_finding |
A CodeQL, Semgrep, Snyk or Socket finding on a line the change touches or in code it reaches |
ai_review_incomplete |
An AI review that was partial or didn't run |
The mapping form takes these keys. A rule needs at least one of breaking, untested, area, contract_breaking, intent, scanner_finding, ai_review_incomplete or agent_track_record_below.
| Key | Type | Default | Meaning |
|---|---|---|---|
breaking |
bool | false |
Trigger on breaking changes and major bumps. Also triggers on contract_breaking findings |
untested |
bool | false |
Trigger on untested changes |
area |
list of strings | none | Trigger on sensitive-area findings for these areas |
when |
string | always |
Who wrote the change: always, agent or agent_or_unknown (both cover any change not confirmed as written by a person) |
approvers |
list of strings | any reviewer | Who may approve: GitHub logins and teams |
count |
int | 1 |
Approvals needed, 1 to 10 |
codeowners |
bool | false |
Code owners of the triggering files may approve |
contract_breaking |
bool | false |
Trigger on breaking contract changes (Beta) |
intent |
bool | false |
Trigger on unevidenced acceptance criteria (Beta) |
scanner_finding |
bool | false |
Trigger on scanner findings the change touches or reaches |
ai_review_incomplete |
bool | false |
Trigger when the AI review was partial or didn't run |
agent_track_record_below |
number | none | Trigger when an agent on the change has a clean share below this, 0 to 1 (Beta) |
min_releases |
int | 3 |
With agent_track_record_below: ignore agents with fewer releases than this |
work_types |
list of strings | all work | With agent_track_record_below: only these work types, from tests, migrations, auth, api, ui |
gate:
require_approval:
- breaking
- area: [billing]
when: agent
approvers: ["@acme/payments"]
count: 2
- untested: true
codeowners: truerequire_approval.area
The sensitive areas the release check reports: authentication, authorization, billing and cryptography. A rule triggers when the check finds a change in one of the listed areas. Names you list here also become named areas for blast_radius.
A change to bumpkit.yml, .bumpkit.yml or a CODEOWNERS file that targets the default branch needs one approval, with the built-in rule policy_change. No setting turns it off, and because the gate reads the policy from the default branch, a pull request can't remove it for itself.
require_approval.when
| Value | The rule applies when |
|---|---|
always |
Always |
agent |
The change isn't confirmed as written by a person: an agent signal, inferred included, or no signal at all. A blocking quality rule fails only on a declared or verified agent, and asks for an approval otherwise |
agent_or_unknown |
The same as agent for approval rules |
A change counts as written by a person only with no agent signal, hooks or telemetry on for the repository, and at least 90% of such changes measured as human across at least 20 verified releases. Without hooks or telemetry, every change that triggers one of these rules needs an approval.
Bumpkit detects coding agents with no setup. It recognizes claude (also anthropic), codex (also openai), cursor, copilot, devin, jules, amp (also ampcode), gemini, windsurf (also codeium), cline and aider. See Who wrote the change.
require_approval.approvers
GitHub logins (alice or @alice) and teams (@org/team). Only approvals from people on the list count toward count. Team membership can only be checked through the Bumpkit GitHub App or a repository host connection; elsewhere the decision says so and the team's approvals don't count.
Approvals count only when they are on the head commit. The author's own approval, bot approvals and approvals from agent accounts never count. See Approvals for Slack and dashboard approvals.
require_approval.count
How many qualifying approvals the rule needs, from 1 to 10. Leave it out for one approval.
require_approval.codeowners
With codeowners: true, the code owners of the files that triggered the rule may approve, in addition to anyone in approvers. Bumpkit reads .github/CODEOWNERS, CODEOWNERS or docs/CODEOWNERS from the same place as the policy, and the last matching pattern wins. If no entry covers the files and approvers is empty, any reviewer counts. CODEOWNERS can only be checked through the Bumpkit GitHub App or a repository host connection.
require_approval.contract_breaking
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:contract_checks.
Triggers on high-severity breaking changes to OpenAPI and Swagger specs, GraphQL schemas, protobuf files and JSON Schema payloads. Write it as the string contract_breaking or as contract_breaking: true in a mapping. See Contract Checks.
require_approval.agent_track_record_below
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:agent_track_records.
Asks a person to approve when an agent on the change has a poor record. Bumpkit counts each agent's releases over the last 90 days, overall and by work type, and the share that stayed clean (not reverted, not fixed up within 7 days, not blocked by the gate, no failed required checks). Put it in a rule of its own:
gate:
require_approval:
- agent_track_record_below: 0.8
min_releases: 1
work_types: [migrations]With work_types, the rule applies only when the change touches those work types; without it, the agent's overall record counts. Agents with fewer than min_releases releases (default 3) are skipped. The reason states the numbers, for example "claude's overall record is 0% clean over 1 release in 90 days (1 reverted, 0 fixed up, 0 blocked by the gate, 0 failed required checks); the policy asks a person to approve below 80%." approvers and count work as in other rules. See bumpkit agents records.
require_approval.intent
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:intent_check.
Triggers when an acceptance criterion from the pull request, its linked issues or specs has no evidence in the changed files, tests or behavioral results. The intent rule only asks for approval; it never passes or fails a release on its own.
require_approval.scanner_finding
Triggers when a scanner result you send with --sarif or --socket lands on a line the change touches or in a file it reaches. Scanner findings never block on their own; this rule only asks for approval. See Scanner results.
require_approval.ai_review_incomplete
Off by default. Triggers when a check's AI review is partly_reviewed or could_not_review, including when no AI provider is set up, the check ran in fast mode, or the model refused. A generated or binary file in the change counts as not reviewed, so this rule triggers on those too. It only asks for approval; an AI review never blocks a release. With codeowners: true, the owners of the files not reviewed may approve. See AI review coverage.
on_error
What the gate does when Bumpkit can't decide, for example when the API is unreachable or a required provider is unavailable.
| Type | string |
| Default | fail |
| Allowed values | fail, pass |
pass makes the gate advisory: an error lets the release through. An invalid bumpkit.yml fails even with on_error: pass, and so does any error on a pull request whose policy sets require_check_apps.
require_checks
CI checks that must pass on the head commit before the gate decides.
| Type | list of strings |
| Default | none |
| Allowed values | check run or commit status names, matched case-insensitively |
gate:
require_checks: [test, lint]While a required check is still running, the GitHub App waits and decides when it finishes. A check that didn't run on the commit fails the gate. A check passes with the conclusion success, neutral or skipped; anything else fails.
CI results are only visible to the Bumpkit GitHub App and repository host connections. When the gate runs from the CLI or API, a person must approve to vouch for them.
require_check_apps
Required checks that only count when a specific GitHub App reported them on the exact head commit.
| Type | map of check name to GitHub App ID |
| Default | none |
| Allowed values | unique check names, matched case-insensitively, and positive App IDs; not behavior |
gate:
require_check_apps:
test: 123456A name here is required even if require_checks doesn't list it. The gate only counts a check run whose App ID matches and whose head SHA is the commit being gated. A check with the same name from another App, a commit status, or a run for another commit doesn't count, so the check fails with "test from GitHub App 123456 didn't run on this commit." When the same check reports more than once, the worst result wins: a failure or a run still in progress can't be hidden by a passing duplicate.
The GitHub App reads every check run on the commit, up to 1,000. More than that fails closed, and so does a check run GitHub returns for a different commit.
Only the Bumpkit GitHub App and a GitHub Enterprise Server connection can verify the issuer, using the App IDs on that server. When the gate runs from the CLI, the API or another code host, require_check_apps fails, and a person's approval can't replace it.
If Bumpkit can't load every check run on the commit, for example when there are more than 1,000 or GitHub returns an error, the gate fails with "Bumpkit couldn't verify the required check apps". With require_check_apps set, that happens whatever on_error says.
require_checks: behavior
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:behavioral_verification.
The name behavior (matched case-insensitively) requires a signed bumpkit verify report for the commit instead of a CI check. Regressions fail the gate and changed behavior needs approval. See verify.
gate:
require_checks: [test, behavior]security_alerts
Fails the gate when the pull request has open code scanning alerts at or above this severity.
| Type | string |
| Default | off |
| Allowed values | critical, high, medium, low |
If code scanning results aren't available for the pull request, the gate fails. Like require_checks, this needs the GitHub App or a GitHub Enterprise Server connection; elsewhere a person must vouch.
vulnerabilities
Fails the gate when the release adds a dependency version with a known vulnerability at or above this severity.
| Type | string |
| Default | high with no gate: section; off otherwise |
| Allowed values | high, medium, low |
If Bumpkit can't check for vulnerabilities, the release needs approval instead.
break_glass
Whether an owner, admin or policy admin may override a failing or waiting gate, signed in to the dashboard on the commit's check page. An override applies to one commit and records the reason.
| Type | bool |
| Default | true |
With break_glass: false, an override is still recorded but doesn't change the decision. See Hotfixes & Break Glass.
hotfix
Rules for hotfix releases. A release is a hotfix when bumpkit gate --hotfix is passed, or when the branch name starts with hotfix/, hotfixes/, release/ or releases/ (or the same with -). A hotfix must be a patch release with no feature commits; otherwise it needs approval.
gate:
hotfix:
block_on: [breaking, data_loss, migration]
max_files: 20
review_within: 72h
backports: approvehotfix.block_on
Finding kinds a hotfix may not carry. Any deterministic, unsuppressed finding of these kinds fails a hotfix, whatever its severity.
| Type | list of strings |
| Default | [breaking, contract_breaking, data_loss, migration] (contract_breaking findings exist only with contract checks, Beta) |
| Allowed values | breaking, contract_breaking (Beta), data_loss, migration, dependency, vulnerable_dependency, config, secret, risk_area, untested |
hotfix.max_files
A hotfix that changes more files than this needs approval.
| Type | int |
| Default | 0 (no limit) |
hotfix.review_within
When someone overrides the gate with break glass, the override needs a post-hoc review within this time. Record it with bumpkit override review.
| Type | duration string, such as 24h or 72h |
| Default | 72h |
| Allowed values | more than 0 and at most 90 days (2160h) |
hotfix.backports
What happens when a regular release would ship without fixes that went out in an earlier hotfix tag (from the last year) but never reached this branch.
| Type | string |
| Default | approve |
| Allowed values | block (fail), approve (needs approval), off |
blast_radius
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:blast_radius.
The bumpkit CLI, locally or in CI, follows every caller of the changed functions through the code graph and report which product areas the change reaches. These keys decide which areas need approval and how far to follow calls.
gate:
blast_radius:
approve_areas: [billing, "@acme/payments"]
max_depth: 4blast_radius.approve_areas
Areas that need an approval when a change reaches them. A reached area in this list also raises the finding from low to medium severity.
| Type | list of strings |
| Default | none |
| Allowed values | plain area names, matched case-insensitively; no :, <, >, ` or ` |
Bumpkit names the area of a file in this order:
- A named area: a name from
approve_areasor require_approval.area, or a built-in sensitive area, that appears as a word in the file's path. - The file's CODEOWNERS owners, such as
@acme/payments. - The file's top directory, or the first two segments under
internal,pkg,src,lib,libs,app,apps,packages,services,cmdormodules.
blast_radius.max_depth
How many calls deep to follow callers.
| Type | int |
| Default | 4 |
| Allowed values | 1 to 10 |
deploy
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:deploy_protection.
With the Bumpkit GitHub App as a deployment protection rule, Bumpkit approves or rejects each deployment from the gate decision for the deployed commit, or the pull request it came from.
gate:
deploy:
environments: [production]
require: approveddeploy.environments
| Type | list of strings |
| Default | every environment |
| Allowed values | GitHub environment names, matched case-insensitively |
Deployments to environments not on the list are approved.
deploy.require
| Type | string |
| Default | pass |
| Allowed values | pass, approved |
With pass, a passing gate approves the deployment. With approved, the gate decision must also have at least one approval. A failed gate always rejects the deployment, and a decision that needs approval leaves it pending.
timezone
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:change_freezes.
The default time zone for windows and freezes.
| Type | string |
| Default | UTC |
| Allowed values | an IANA name, such as America/New_York or America/Los_Angeles |
windows
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:change_freezes.
Weekly release windows. Outside every window, a release needs approval or fails, depending on outside_windows. Hotfixes may ship outside the windows.
gate:
timezone: America/New_York
windows:
- days: [mon-thu]
from: "09:00"
to: "16:00"
- days: [fri]
from: "09:00"
to: "12:00"| Key | Type | Default | Allowed values |
|---|---|---|---|
days |
list of strings | every day | mon to sun, full names such as monday, or ranges like mon-fri |
from |
string | 00:00 |
a time like 09:00 |
to |
string | 24:00 |
a time like 17:00, after from |
timezone |
string | timezone | an IANA name |
Quote times in YAML ("09:00").
outside_windows
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:change_freezes.
| Type | string |
| Default | approve |
| Allowed values | approve, block |
freezes
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:change_freezes.
Scheduled change freezes. Each freeze is a date range, a list of dates, or a weekly time span. You can also declare a freeze on the spot with bumpkit freeze start or the Policy page. See Org Policies & Freezes.
gate:
freezes:
- name: Year-end freeze
start: 2026-12-20
end: 2027-01-02
mode: block
hotfix: approve
- name: Public holidays
dates: [2026-12-25, 2027-01-01]
- name: Friday afternoons
days: [fri]
from: "15:00"
mode: approve| Key | Type | Default | Allowed values |
|---|---|---|---|
name |
string | required | any text |
start, end |
string | none | dates like 2026-12-24 or times like 2026-12-24T18:00; set both. A date-only end includes that whole day |
dates |
list of strings | none | whole days, like 2026-12-25 |
days, from, to |
the same as in windows | ||
timezone |
string | timezone | an IANA name |
mode |
string | block |
block (fail), approve (needs approval) |
hotfix |
string | approve |
allow, approve, block |
During a block freeze, only a break-glass override lets a release through. hotfix sets what happens to hotfixes during the freeze.
areas
Beta, early access. Flag:
proven_changes.
Names parts of the repository for proven changes. Each name maps to path patterns. A file can be in more than one area. Files in no named area use their directory. The gate doesn't read this.
areas:
checkout: ["apps/web/checkout/**", "services/payments"]proven
Beta, early access. Flag:
proven_changes.
proven.never lists the kinds of change that are never proven in this repository: tests, migrations, auth, api, ui, deps, docs or code. Without it, deps, migrations and auth are excluded. An empty list measures every kind. The gate doesn't read this.
proven:
never: [deps, migrations, auth, ui]compatibility
Beta, early access. Flag:
compatibility_matrix.
A top-level section, next to gate, that declares your components and the version pairs you support. It feeds the compatibility matrix. Add compatibility_break to block_on to block a release that breaks a pair.
compatibility:
components:
- name: web
role: client
repository: acme/web
- name: api
role: server
paths: ["openapi/**"]
supported:
- consumer: web
consumer_versions: ">=1.4.0 <2.0.0"
provider: api
provider_versions: ">=2.0.0"components, 1 to 50:
| Key | Type | Required | Allowed values |
|---|---|---|---|
name |
string | Yes | Letters, digits, dots, dashes or underscores, up to 64 characters; unique |
role |
string | Yes | client, server, sdk, api, schema, app |
repository |
string | No | owner/name; defaults to the repository this file is in |
paths |
list of strings | No | Up to 50 path patterns such as openapi/**; only breaks in these paths count. Defaults to the whole repository |
supported, 1 to 200:
| Key | Type | Required | Allowed values |
|---|---|---|---|
consumer |
string | Yes | A component's name |
consumer_versions |
string | Yes | A version range |
provider |
string | Yes | A different component's name |
provider_versions |
string | Yes | A version range |
A version range looks like >=1.4.0 <2.0.0, >=2.0.0, ^1.4, ~1.4, 1.x or 2.3.1. Pre-release versions aren't in a range unless the range names one.
Removing the section removes the repository's pairs the next time Bumpkit reads the file from the base branch, or when you run bumpkit compatibility sync.
exports
Tunes the public API change findings, the removed or changed exports that count as breaking changes.
| Key | Type | Default | Allowed values |
|---|---|---|---|
severity |
string | high |
high, medium, low, info |
ignore_paths |
list of strings | none | up to 100 path patterns, CODEOWNERS style, such as generated/** |
max_findings |
int | 0 (no cap) |
0 to 1000; the rest are summarized in one finding |
Only high-severity breaking findings trigger block_on and the breaking approval rule, so a lower severity makes export changes informational. These keys apply to every release check and gate; they don't need the behavior_checks flag.
behavior
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:behavior_checks.
Release checks catch small behavior changes in every supported language, such as removed guard clauses or changed defaults, and the CLI flags changed files with a history of reverts. These findings are informational until you turn them on here.
gate:
behavior:
changes: approve
hotspots: block
severity: medium
hotspots_min: high| Key | Type | Default | Allowed values |
|---|---|---|---|
changes |
string | off |
off, approve, block: what behavior-change findings do |
hotspots |
string | off |
off, approve, block: what hotspot findings do |
severity |
string | none | high, medium, low: raises these findings to at least this severity |
hotspots_min |
string | medium |
high, medium, low: hotspots below this severity don't count |
quality
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flags:architecture_drift,slop_tracker,performance_diff.
Decides what code quality findings do, and sets the thresholds the checks use. See Code Quality & Architecture.
gate:
quality:
architecture_drift: block
code_quality:
action: approve
severity: medium
when: agent
performance: warnquality.architecture_drift
New import cycles, breaks of the architecture layers, and coupling and complexity growth.
quality.code_quality
Copied code, interfaces with one implementation, functions that only forward, unreferenced new symbols, oversized functions and comment noise.
quality.performance
Queries inside loops, blocking IO and complexity growth on hot paths, unbounded allocations, and benchmark regressions.
Quality rules
Each of the three keys takes a string (the action) or a mapping:
| Key | Type | Default | Allowed values |
|---|---|---|---|
action |
string | warn |
warn (report only), approve (needs approval), block (fail) |
severity |
string | medium |
high, medium, low: findings at or above this count |
when |
string | always |
always, agent, agent_or_unknown |
Quality thresholds
| Key | Type | Default | Allowed values |
|---|---|---|---|
max_function_lines |
int | 80 |
1 to 10000 |
max_complexity |
int | 15 |
1 to 1000 |
clone_tokens |
int | 40 |
10 to 1000: the smallest copied block reported |
hot_path_depth |
int | 4 |
1 to 10 |
bench_threshold |
number | 5 |
0 to 1000: the benchmark slowdown in percent that counts |
cross_repo
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:cross_repo_impact.
When a release breaks a contract or public API that other repositories in your workspace consume, the gate lists each consuming repository with its call sites. See Cross-Repo Impact.
| Key | Type | Default | Meaning |
|---|---|---|---|
block_on_consumer_break |
bool | false |
Fail the gate when a consumer breaks |
require_approval |
bool | true |
Ask for approval when a consumer breaks |
If Bumpkit can't check the consumers, the release needs approval regardless of these settings.
fix_tasks
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:close_the_loop.
What open fix tasks do to the gate. A fix task lists every file:line caller still on the old version of a Go function or method this branch renamed, removed or changed, with the expected edit. Bumpkit opens mechanical edits (a rename, or one removed parameter) as a pull request into the branch and routes the rest to the authoring agent and the pull request. A task is done only when a later gate run proves every listed place clean, never because an agent says so.
| Type | string |
| Default | block |
| Allowed values | block (fail), approve (needs approval), off |
gate:
fix_tasks: approveA task holds the gate once Bumpkit has confirmed it by reading the code at the commit through the GitHub App. Until then it shows as a fix_tasks: unconfirmed flag and doesn't hold the gate, so on GitLab, Bitbucket and Azure DevOps a task is a flag. Creating a task from a report takes a key with write access. Each confirmed task still open after the gate run adds one reason, fix_tasks: block or fix_tasks: approve, that names the places, the symbol, its old signature, what to change, who it was routed to and the fix pull request. With block, approval can't override it. With approve, any reviewer's approval counts. With off, tasks are still recorded and routed but don't change the outcome. An org policy can lock fix_tasks; a repository can then only tighten it. bumpkit loop --mine lists the tasks on your branch.
require_regression_evidence
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:regression_evidence.
Require test results on the exact commit before a release ships, with the tests picked by the change's blast radius. It's off until you turn it on.
| Type | bool |
| Default | false |
regression_evidence_action
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:regression_evidence.
What happens when the evidence isn't a clean pass. It needs require_regression_evidence: true.
| Type | string |
| Default | block |
| Allowed values | block (fail), approve (needs approval) |
gate:
require_regression_evidence: true
regression_evidence_action: approveThe gate adds one reason, require_regression_evidence: block or require_regression_evidence: approve. It passes only when every expected test passed in results a CI run attested for this exact commit. Results from a plain API key or another commit don't count. No results, partial results, a failed test, an unreadable upload, or a change Bumpkit can't map to tests all fail under block, where approval can't override it, and need approval under approve, where any reviewer's approval counts. See Regression evidence for the setup. An org policy can lock both keys; a repository can then only tighten them.
stacks
Beta, early access. Flag:
stacked_prs. Needs the Bumpkit GitHub App.
How the gate treats stacked pull requests. A pull request whose base branch is another open pull request's head branch in the same repository is stacked on it, so #128 → #130 → #131 is a stack of three. Bumpkit works the stack out from GitHub App events, never from what a client sends, and checks each pull request on its own changes: #131 is compared against #130's head, not against main. The policy and CODEOWNERS for a stacked pull request come from the default branch.
Every stacked pull request's decision carries a stacks reason that names its parent and what has to merge first. The result comment shows the whole stack, the pull request's position in it and the merge order.
Bumpkit keeps each decision tied to the exact head and base it checked:
- When a parent gets new commits, its direct children are checked again against the new parent head.
- When GitHub retargets a child after its parent merges, the child is checked again against its new base, and the decision against the old base no longer counts as current.
- Approvals count only for the head commit they approved.
| Type | mapping |
| Default | {require_parent_merged: false} |
stacks.require_parent_merged
Holds a stacked pull request until the pull request it's stacked on has merged. While the parent is open, the child's decision fails with a stacks.require_parent_merged reason that names the pull requests to merge first. Approval can't override it. Once the parent merges, Bumpkit checks the child again and the hold clears.
| Type | boolean |
| Default | false |
gate:
stacks:
require_parent_merged: trueAn org policy can lock stacks; a repository can then only turn require_parent_merged on. Run bumpkit stack list to see the repository's stacks, or bumpkit stack show NUMBER for one pull request's position and merge order.
architecture
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:architecture_drift.
A top-level key, next to gate:. It declares your layers and the imports between them that aren't allowed. Without it, Bumpkit infers layers from the base. gate.quality.architecture_drift decides what a break does.
architecture:
layers:
- name: api
paths: [services/api]
- name: store
paths: [services/db, services/store]
- web
forbidden:
- from: store
to: api| Key | Type | Meaning |
|---|---|---|
layers |
list | Each layer is a name and its paths. A plain string is a layer whose name is also its path |
layers[].name |
string | A unique name |
layers[].paths |
list of strings | Relative path prefixes; defaults to the name |
forbidden |
list | Imports that aren't allowed |
forbidden[].from, forbidden[].to |
string | A layer name or path |
agent
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:agent_pause.
A top-level key. It configures bumpkit pause, the hook that checks each shell command or file access a coding agent makes before it runs, and allows it, asks a human, or denies it. See Agent Controls.
agent:
ask: [rm_rf, "npm publish *"]
deny: [force_push, "terraform destroy*"]
allow: ["rm -rf ./dist*"]
protected_branches: [main, "release/*"]
remote: true
timeout: 45s| Key | Type | Default | Meaning |
|---|---|---|---|
ask |
list of strings | none | Rules or patterns that pause for a human |
deny |
list of strings | none | Rules or patterns that are blocked |
allow |
list of strings | none | Rules or patterns that are let through |
protected_branches |
list of strings | main, master, trunk, production, prod, release/*, releases/* |
Branch names or globs that force_push protects |
remote |
bool | false |
When a command pauses, a teammate can approve it from the Approvals page |
timeout |
duration string | 30s |
How long a remote approval waits, 5s to 120s |
Each entry in ask, deny and allow is a built-in rule ID or a pattern. A pattern matches a command line or file path, with * and ? as wildcards. A single lowercase word that isn't a rule ID is an error; add a space or * to make it a pattern.
A deny pattern always wins. An allow pattern lets a command through unless one of its rules is in deny. Listing a rule ID moves that rule to the level of the list.
| Rule ID | Default | Catches |
|---|---|---|
rm_rf |
ask | rm -r outside a temporary or build directory |
rm_rf_root |
deny | rm -r on /, the home directory, the repository root or a system directory |
force_push |
deny | git push --force or a branch delete on a protected branch |
git_reset_hard |
ask | git reset --hard |
git_clean |
ask | git clean -f |
sql_drop |
ask | DROP, TRUNCATE or an unfiltered DELETE sent to a database client |
infra_apply |
ask | terraform, tofu or pulumi apply and destroy |
kubectl_delete |
ask | kubectl delete or drain, helm uninstall |
pipe_to_shell |
ask | A downloaded or decoded script piped into a shell or interpreter |
chmod_777 |
ask | chmod -R that makes files world-writable |
secret_write |
ask | A write to .env, a key or a secrets file |
credential_file |
ask | Reading or copying a credential file such as .env, ~/.ssh or ~/.aws |
package_publish |
ask | Publishing a package or pushing an image |
prod_database |
ask | A database URL whose host isn't local |
self_approval |
deny | An agent approving or rejecting Bumpkit memories, lessons or Approvals items |
agent_scope |
deny | An agent writing outside the paths and areas agents: gives it |
too_complex |
ask | A command nested too deeply to check |
bumpkit pause reads bumpkit.yml from the default branch (origin/HEAD, origin/main or origin/master, else HEAD), not from your uncommitted changes, so an agent can't edit its own rules. If the file doesn't parse, it uses the default rules.
agents
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:agent_budgets.
A top-level key with budgets and scopes for coding agents. Map an agent id, or a glob such as claude-*, to its limits:
agents:
claude-*:
max_open_prs: 2
max_changed_lines: 400
paths_allow: [services/notify/**]
paths_deny: [services/billing/**]
areas_deny: [billing]
spend_limit: 10
on_violation: block| Key | Type | Default | Meaning |
|---|---|---|---|
max_open_prs |
int | no limit | The most open pull requests the agent may have; this change fails the limit when the agent already has that many others open |
max_changed_lines |
int | no limit | The most lines one change may touch |
paths_allow |
list of strings | every path | Path patterns the agent may change, such as services/notify/** |
paths_deny |
list of strings | none | Path patterns the agent may not change |
areas_deny |
list of strings | none | Areas the agent stays out of: tests, migrations, auth, api, ui, authentication, authorization, billing, cryptography |
spend_limit |
number | no limit | US dollars per calendar month (UTC), recorded with bumpkit agents spend |
on_violation |
string | block |
block fails the gate; approve asks for a person's approval |
The gate checks every agent on the change, including the BUMPKIT_AGENT_ID or BUMPKIT_AGENT that bumpkit gate sends. Each broken limit becomes its own reason, named agents.<pattern>.paths, .areas_deny, .max_changed_lines, .max_open_prs or .spend_limit. bumpkit pause --hook claude also denies file writes outside an agent's paths before they happen. Every violation is recorded and audited; see bumpkit agents violations. Limits can't be negative, and an unknown key or area is an error. With the GitHub App installed, the gate uses the agents: section from the base branch.
memory
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:memory_approval.
A top-level key for codebase memory.
| Key | Type | Default | Meaning |
|---|---|---|---|
require_approval |
bool | false |
Memories agents save wait as pending until a person approves them on the Approvals page or with bumpkit memory approve. Only approved memories are recalled |
memory:
require_approval: trueIf bumpkit.yml doesn't parse, new agent memories wait for approval.
verify
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:behavioral_verification.
A top-level key for bumpkit verify, which runs the base and the head side by side in your CI and uploads a signed report. Add behavior to require_checks to make the gate require it. bumpkit verify reads this section from the base commit, like the gate.
verify:
test: go test ./...
timeout: 15m
network: localhost
env: [DATABASE_URL]
http:
start: ./bin/server
ready: /healthz
port_env: PORT
openapi: api/openapi.yaml
ignore: [id, created_at]
library:
runs: 128
browser:
pages: [/, /pricing]
threshold: 0.02
require_ci_attestation: true| Key | Type | Default | Meaning |
|---|---|---|---|
test |
string | detected: go test ./..., npm test or python -m pytest |
The test command |
timeout |
duration string | 10m |
Up to 2h |
memory_mb |
int | 16384 |
Memory limit for the sandbox |
cpu_seconds |
int | 1800 |
CPU limit for the sandbox |
network |
string | localhost |
localhost or allow |
env |
list of strings | none | Names of environment variables to pass into the sandbox (names only, no =) |
require_ci_attestation |
bool | true |
gate.require_checks: [behavior] uses the latest report attested by GitHub Actions OIDC, so a later report signed only with an API key neither replaces nor blocks it. false opts out and trusts anyone with a key. Once the GitHub App is installed or a GitLab, Bitbucket or Azure DevOps connection is added, Bumpkit reads this setting from your repository's policy; with neither, it uses the policy your CI sends and the decision says policy_source: client. With the App installed, a report counts only if the pull request leaves .github/ and the local actions and scripts named in the default branch's workflow unchanged, and a report from a merge commit counts only while it is the pull request's current merge commit into your default branch. The workflow still runs the pull request's own code and tests. GitLab, Bitbucket and Azure DevOps have no GitHub Actions token, so set false there to use require_checks: [behavior] |
verify.http
Replays HTTP requests against the base and head versions of your service.
| Key | Type | Default | Meaning |
|---|---|---|---|
start |
string | required | The command that starts the service |
ready |
string | / |
The path that answers when the service is up |
port_env |
string | PORT |
The environment variable the service reads its port from |
openapi |
string | detected | An OpenAPI spec to derive requests from |
requests |
string | none | A file of recorded requests |
ignore |
list of strings | none | JSON body fields to ignore when comparing, such as id or $.created_at |
startup_timeout |
duration string | 60s |
How long to wait for ready |
verify.library
Generated calls to changed Go functions, compared between base and head.
| Key | Type | Default | Meaning |
|---|---|---|---|
disabled |
bool | false |
Turn it off |
runs |
int | 64 |
Calls per function, up to 1000 |
seed |
int | 1 |
Random seed |
verify.browser
Playwright screenshots of pages, compared pixel by pixel.
| Key | Type | Default | Meaning |
|---|---|---|---|
disabled |
bool | false |
Turn it off |
pages |
list of strings | [/] |
Pages to compare, up to 50 |
threshold |
number | 0.01 |
The share of pixels, 0 to 1, that may differ |
train
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:release_trains.
Top-level train: sets the rules for release trains cut from this branch. Bumpkit reads it from bumpkit.yml on the branch the train ships.
train:
label: "train:{slug}"
require_all_pass: true
max_breaking: 0
require_approval:
teams: ["@acme/release-managers"]
count: 1
block_on_unhealthy_deploys: true
release_workflow: release.yml| Key | Type | Default | Meaning |
|---|---|---|---|
label |
string | train:{slug} |
The pull request label that joins a train. At most 50 characters, no surrounding spaces. |
require_all_pass |
bool | true |
Hold the train until every member passes the gate. A failing member always blocks it. |
max_breaking |
int | no limit | The most breaking changes the train may carry. Must not be negative. |
require_approval |
map | none | Release manager approvals: approvers (list), teams (list of @org/team) and count (up to 10; leave it out for one approval). |
block_on_unhealthy_deploys |
bool | false |
Block when a member is regressed or degraded in production. |
release_workflow |
string | none | A workflow file name such as release.yml, dispatched with the train's name when the train is cut, instead of Bumpkit creating the GitHub Release. |
locked
Beta, early access. A workspace without access gets
403 FEATURE_EARLY_ACCESSand a link to request it. Flag:org_policies.
An org policy is one gate policy for the whole workspace. Workspace owners and admins save it on the Policy page, signed in to the dashboard; bumpkit policy set and PUT /v1/policy/org return 403 HUMAN_APPROVAL_REQUIRED with the link, since a key can't change org locks, or point it at a config repository whose bumpkit.yml on the default branch is read at gate time. Every version is kept and audited. See Org Policies & Freezes.
An org policy is a bumpkit.yml with one extra top-level key, locked:, the gate keys that repositories may only tighten:
locked: [block_on, require_approval, break_glass, freezes]
gate:
block_on: [secret, data_loss]
require_approval:
- breaking
break_glass: false
freezes:
- name: Year-end freeze
start: 2026-12-20
end: 2027-01-02locked accepts block_on, require_approval, on_error, require_checks, security_alerts, vulnerabilities, break_glass, hotfix, blast_radius, deploy, cross_repo, timezone, windows, outside_windows, freezes, quality, exports, behavior, fix_tasks, require_regression_evidence, regression_evidence_action, require_check_apps and stacks.
How the org policy merges
The org policy is the starting point. For each key a repository's bumpkit.yml sets under gate::
- An unlocked key replaces the org value.
- A locked key can only be tightened. When the repository tries to loosen it, the org value stays and the gate decision notes it.
| Locked key | Effective value |
|---|---|
block_on, require_checks |
Both lists combined |
require_approval, freezes |
The org rules plus any new repository rules |
on_error |
The org's fail stays fail |
security_alerts, vulnerabilities |
The repository may only lower the threshold |
break_glass |
The org's false stays false |
hotfix |
The stricter of each setting: both block_on lists, the smaller max_files, the shorter review_within, the stricter backports |
blast_radius |
Both approve_areas lists; the org's max_depth always applies |
timezone |
The org's value |
windows |
The org's windows, if it sets any; add freezes to narrow them |
outside_windows |
The org's block stays block |
fix_tasks |
The stricter of the two: off < approve < block |
require_regression_evidence |
The org's true stays true |
regression_evidence_action |
The stricter of the two: approve < block |
deploy, cross_repo, quality, exports, behavior |
The org's value; a different repository value is ignored |
Run bumpkit policy show --effective in a repository, or call POST /v1/policy/effective, to see the policy the gate applies and where each key came from. If the org policy doesn't parse or its config repository can't be read, the gate fails closed.