Pull requests: every pr command plus reviewer and auto-merge recipes # PR Commands > Task-based reference for creating, reviewing, and merging pull requests Manage pull requests (PRs) in Bitbucket repositories. New here? Start with [Create, edit, and view](/commands/pr/create-and-edit/). See [Global flags](/reference/global-flags/) for JSON output, workspace/repository selection, and display options. ## Command groups [Create, edit, and view](/commands/pr/create-and-edit/)Open a PR, change its title or description, list and filter PRs, see your PR status, inspect one. [Activity and checks](/commands/pr/activity-and-checks/)Read the activity timeline and CI build statuses before approving or merging. [Diff and checkout](/commands/pr/diff-and-checkout/)Print the patch or diffstat, fetch the PR branch locally, open the diff in a browser. [Review and merge](/commands/pr/review-and-merge/)Approve, request changes, decline, mark a draft ready, and merge with an explicit strategy. [Comments](/commands/pr/comments/)List, add, view, edit, reply to, resolve, unresolve, and delete general or inline review comments. [Reviewers](/commands/pr/reviewers/)Add and remove reviewers. Adding someone already assigned is a no-op, as is removing someone who is not. ## Pull request from the current branch Commands that act on one pull request take its ID as an optional `[id]`: `view`, `activity`, `checks`, `edit`, `merge`, `approve`, `decline`, `ready`, `diff`, and `comments list`. Leave it out and the CLI asks Bitbucket for the open pull request whose source branch is your current git branch, in the repository your checkout’s `origin` points at. That keeps a fork’s `main` from matching your `main`, and still works from a fork with `--repo` set to upstream. ```bash git switch feature/login bb pr view # the open PR from feature/login bb pr checks bb pr merge --strategy squash ``` It only picks a pull request when exactly one matches. No match, several matches (the same branch opened against two destinations), or a detached `HEAD` all stop with an error asking for the ID. `bb pr checkout`, `bb pr reviewers` and the other `bb pr comments` subcommands still need the ID. ## Most-used commands | Task | Command | | --------------------------------------------------- | --------------------------------------------------- | | Create a PR | `bb pr create -t "Add feature"` | | Create a PR with the repository’s default reviewers | `bb pr create -t "Add feature" --default-reviewers` | | List open PRs | `bb pr list` | | List all PRs (ignore the default limit) | `bb pr list --all` | | List PRs you opened | `bb pr list --author @me` | | List PRs where you are a reviewer | `bb pr list --reviewer @me` | | Your PRs, review requests and current branch PR | `bb pr status` | | View PR details | `bb pr view 42` | | View the PR for the current branch | `bb pr view` | | View checks | `bb pr checks 42` | | Wait for checks to finish | `bb pr checks 42 --watch` | | Review diff | `bb pr diff 42 --stat` | | Checkout PR locally | `bb pr checkout 42` | | Approve PR | `bb pr approve 42` | | Request changes | `bb pr request-changes 42` | | Merge PR | `bb pr merge 42 --strategy squash` | ## JSON for automation List commands wrap their results in an envelope. Bare `bb pr list --json` returns `{workspace, repoSlug, state, filters, count, pullRequests}`, so a `--jq` filter starts at `.pullRequests[]`. Adding a field list (`--json id,title`) drops the envelope and returns a flat array, so the filter starts at `.[]` instead. Single-PR commands like `bb pr view` return the PR object itself, with no envelope. ```bash # Project to specific fields (returns a flat array) bb pr list --json id,title,author.display_name # Filter with built-in --jq bb pr list --json --jq '.pullRequests[] | select(.state == "OPEN") | .title' # Combine projection + filter (jq runs after projection) bb pr list --json id,title,state --jq '.[] | select(.state == "OPEN") | .title' # Grab a PR URL from view output bb pr view 42 --json --jq '.links.html.href' # Capture totals for the returned diffstat page bb pr diff 42 --stat --json --jq '{filesChanged, totalAdditions, totalDeletions}' ``` Diffstat totals can be partial; see [Diff and checkout](/commands/pr/diff-and-checkout/). `--json ` misfires on `bb pr create`, `bb pr edit` and `bb pr view`, see [Create, Edit, and View PRs](/commands/pr/create-and-edit/) for why, and [JSON Output](/reference/json-output/) for the full reference. # Activity and Checks > Inspect pull request activity history and CI/CD check status Inspect pull request activity and build checks. See [Global flags](/reference/global-flags/) for JSON output, workspace/repository selection, and display options. ## `bb pr activity` Show a pull request activity log. ```bash bb pr activity [id] [options] ``` ### Arguments | Argument | Description | | -------- | -------------------------------------------------------------------------- | | `id` | Pull request ID (optional, defaults to the open PR for the current branch) | ### Options | Option | Description | Default | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------- | ------- | | `--limit ` | Maximum number of activity entries | `25` | | `--all` | Show all activity entries (overrides `--limit`) | | | `--type ` | Filter by activity type (comma-separated): `comment`, `approval`, `changes_requested`, `merge`, `decline`, `commit`, `update` | | | `--no-truncate` | Global flag. Show full details instead of fitting them to the terminal | | ### Examples ```bash # View activity for PR #42 bb pr activity 42 # Filter to comment and approval events bb pr activity 42 --type comment,approval # Limit results bb pr activity 42 --limit 10 # Show the full activity history bb pr activity 42 --all # Get activity as JSON bb pr activity 42 --json ``` Output: ```text TYPE ACTOR DATE DETAILS -------- -------- ----------- -------------------------------- UPDATE Sam Ali 2 hours ago state: OPEN COMMENT Jane Doe 5 hours ago #486513002 Why was this removed? APPROVAL Lee Park yesterday approved COMMIT Sam Ali yesterday commit a1b2c3d ``` ### Notes * Long details are shortened to fit the terminal width. Use `--no-truncate` for the full text * An unrecognized `--type` token fails with `--type must be one of: comment, approval, changes_requested, merge, decline, commit, update`. Each bad token that is close to a valid one adds a `(Did you mean ...?)` line; tokens with no close match add nothing * `--limit` is enforced across paginated activity responses * When the result is capped by `--limit`, a hint shows how many were listed; use a higher `--limit` or `--all` to see the rest (suppressed with `--json`) *** ## `bb pr checks` Show CI/CD checks and build status for a pull request. ```bash bb pr checks [id] [options] ``` ### Arguments | Argument | Description | | -------- | -------------------------------------------------------------------------- | | `id` | Pull request ID (optional, defaults to the open PR for the current branch) | ### Options | Option | Description | | ---------------------- | -------------------------------------------------------------------------- | | `--watch` | Wait until no check is in progress; exit non-zero if any failed or stopped | | `--interval ` | Seconds between polls with `--watch` (default: `10`) | | `--no-truncate` | Global flag. Show full check descriptions without fitting them | ### Examples ```bash # View checks for PR #42 bb pr checks 42 # View checks in a specific repository bb pr checks 42 -w myworkspace -r myrepo # Get checks as JSON bb pr checks 42 --json # Wait for running checks, then merge only if none failed bb pr checks 42 --watch && bb pr merge 42 ``` Output: ```text Pull Request #42 - 3 checks ──────────────────────────────────────────────────────────── STATUS NAME DESCRIPTION UPDATED ----------- -------------- ----------------------------- -------------- OK passed build Build succeeded in 2m 11s 5 minutes ago FAIL failed unit-tests 3 of 412 tests failed 2 minutes ago RUN running deploy-preview Deploying preview environment now OK 1 successful, FAIL 1 failed, RUN 1 pending ``` With `--watch`, the command prints `Waiting for 1 of 3 checks on pull request #42...`, then one line per check whose state changes, then the table above once nothing is running: ```text Waiting for 1 of 3 checks on pull request #42... OK deploy-preview passed ``` Required checks `--watch` only judges the checks Bitbucket reports. When none is listed yet it waits three more polls for the first one, then fails with `No checks were reported on pull request #42.` A required check that has not started while others finish is still invisible. The [auto-merge recipe](/recipes/auto-merge-on-ci-green/) explains required check keys and merge policies. ### Notes * The `STATUS` cell is an icon plus a label: `OK passed`, `FAIL failed`, `RUN running`, `STOP stopped`, or `?` plus the raw state for anything else * The summary line counts only successful, failed, and running checks, so it can total fewer than the header count * Long check names and descriptions are shortened to fit the terminal width. Use `--no-truncate` for the full text * `bb pr checks` reads every status page, so it has no `--limit` or `--all` * Without `--watch` the exit status is `0` whatever the checks say. With `--watch` a failed or stopped check exits `1` with error code [`10001` CI\_FAILED](/reference/error-codes/#10001---ci_failed), after printing the final state; `--json` prints only that final envelope, no progress lines * `--json` returns `{ pullRequestId, workspace, repoSlug, summary, statuses }`. Unlike list commands, there is no `count` key, use the length of `statuses` * With no checks, the command prints `No CI/CD checks found for this pull request`; with `--json` it returns an empty `statuses` array # Comments > List, add, view, edit, reply to, resolve, unresolve, and delete pull request comments Manage pull request comments. See [Global flags](/reference/global-flags/) for JSON output, workspace/repository selection, and display options. `` and `` identify the pull request. `list` takes it as an optional `[id]` and falls back to the open PR for your current branch. `` identifies a comment; find it with `bb pr comments list `. `view`, `edit`, `reply`, `resolve`, and `unresolve` take only [global flags](/reference/global-flags/). ## `bb pr comments` ### Subcommands | Subcommand | Description | | -------------------------------------- | -------------------------------------------------- | | `list [id]` | List comments on a pull request | | `add ` | Add a comment to a pull request | | `view ` | View a single comment on a pull request | | `edit ` | Edit a comment on a pull request | | `reply ` | Reply to a comment on a pull request | | `resolve ` | Resolve a comment thread on a pull request | | `unresolve ` | Reopen a resolved comment thread on a pull request | | `delete ` | Delete a comment on a pull request | *** ## `bb pr comments list` List comments on a pull request. ```bash bb pr comments list [id] [options] ``` ### Arguments Use the identifiers described [above](#bb-pr-comments). ### Options | Option | Description | Default | | ------------------ | ------------------------------------------------------- | ------- | | `--limit ` | Maximum number of comments | `25` | | `--all` | List all comments (overrides `--limit`) | | | `--resolved` | Only show resolved comments | | | `--unresolved` | Only show unresolved comments | | | `--no-truncate` | Global flag. Show full comment content, never shortened | | ### Examples ```bash # List comments on PR #42 bb pr comments list 42 # Only comments that still need attention bb pr comments list 42 --unresolved # List more comments bb pr comments list 42 --limit 50 # List every comment bb pr comments list 42 --all # Show full comment content (not shortened) bb pr comments list 42 --no-truncate ``` Output: ```text ID Author Content Status Date --------- -------- ------------------------------- -------- ----------- 486512301 Jane Doe Consider renaming this variable resolved 2 days ago 486512477 Sam Ali Good catch, fixed. open 2 days ago 486513002 Jane Doe Why was this removed? open 5 hours ago ``` ### Notes * Long comment content is shortened to fit the terminal width. Use `--no-truncate` for the full text * The `Status` column shows `resolved`, `pending`, or `open`. Bitbucket records resolution on the comment that was resolved, so a reply inside a resolved thread shows `open` (or `pending` if it is an unpublished draft) * `--resolved` and `--unresolved` filter on the same resolution state and cannot be combined * With `--resolved`/`--unresolved` the filter is applied client-side after each page is fetched, so `--limit` counts comments that survive the filter, `--unresolved --limit 25` keeps fetching pages until 25 unresolved comments are found or the list is exhausted * When the result is capped by `--limit`, a hint shows how many were listed; use a higher `--limit` or `--all` to see the rest (suppressed with `--json`) *** ## `bb pr comments add` Add a general comment, or an inline comment anchored to a file line. ```bash bb pr comments add [message] [options] ``` ### Arguments Use the identifiers described [above](#bb-pr-comments). ### Options | Option | Description | | ------------------------ | --------------------------------------------------------------------------------------------- | | `-F, --body-file ` | Read the comment text from a file, or `-` for stdin (instead of ``) | | `--file ` | File path for an inline comment (requires `--line-to` and/or `--line-from`) | | `--line-to ` | Line number in the new version of the file (requires `--file`) | | `--line-from ` | Line number in the old version of the file (requires `--file`) | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ### Examples ```bash # Add a general comment to PR #42 bb pr comments add 42 "LGTM! This looks great." # Inline comment on a line in the new file bb pr comments add 42 "Consider renaming this variable" --file src/index.ts --line-to 15 # Inline comment on a line in the old (removed) version of the file bb pr comments add 42 "Why was this removed?" --file src/utils.ts --line-from 10 # Inline comment spanning old and new lines bb pr comments add 42 "This logic changed" --file src/app.ts --line-from 5 --line-to 8 # Multi-line markdown from a file, or from stdin with - bb pr comments add 42 -F review.md bb pr comments add 42 -F - <<'EOF' Nit: prefer `const` here. EOF ``` ### Notes * Pass the text as `` or with `-F/--body-file`, not both. Blank text is rejected before anything is sent * `-F/--body-file` is the comment text; `--file` is the diff path an inline comment anchors to * `--file` is required when using `--line-to` or `--line-from` * At least one of `--line-to` or `--line-from` is required when using `--file` * Line numbers must be positive integers *** ## `bb pr comments view` View a single comment, including whether it is resolved. ```bash bb pr comments view ``` ### Arguments Use the identifiers described [above](#bb-pr-comments). ### Examples ```bash # View comment #486512301 on PR #42 bb pr comments view 42 486512301 ``` ### Notes * The header shows `[resolved]` or `[unresolved]` for that specific comment. Bitbucket records the resolution on the comment that was resolved, so a reply inside a resolved thread still shows `[unresolved]` * Unpublished draft review comments show `[pending]` instead * Deleted comments render their content as `[deleted]` * `--json` prints the raw comment object returned by the API *** ## `bb pr comments edit` Edit a comment on a pull request. ```bash bb pr comments edit ``` ### Arguments Use the identifiers described [above](#bb-pr-comments). ### Options | Option | Description | | ----------- | --------------------------------------------------------------------------------------------- | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ### Examples ```bash # Replace the body of comment #486512301 on PR #42 bb pr comments edit 42 486512301 "Updated: I noticed something else..." ``` *** ## `bb pr comments reply` Reply to an existing comment. The reply is attached to the parent comment, so it lands in the same thread. ```bash bb pr comments reply [message] [options] ``` ### Arguments Use the identifiers described [above](#bb-pr-comments). ### Options | Option | Description | | ------------------------ | --------------------------------------------------------------------------------------------- | | `-F, --body-file ` | Read the reply text from a file, or `-` for stdin (instead of ``) | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ### Examples ```bash # Reply to comment #486512301 on PR #42 bb pr comments reply 42 486512301 "Good catch, fixed." # Reply with multi-line markdown from stdin bb pr comments reply 42 486512301 -F - <<'EOF' Fixed in `a1b2c3d`: retries are capped at 3. EOF ``` ### Notes * Pass the text as `` or with `-F/--body-file`, not both. Blank text is rejected before anything is sent * Use `bb pr comments list ` to find the comment ID to reply to * How Bitbucket anchors a reply to an inline comment is decided server-side *** ## `bb pr comments resolve` Resolve a comment thread on a pull request. ```bash bb pr comments resolve ``` ### Arguments Use the identifiers described [above](#bb-pr-comments). ### Options | Option | Description | | ----------- | --------------------------------------------------------------------------------------------- | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ### Examples ```bash # Resolve comment thread #486512301 on PR #42 bb pr comments resolve 42 486512301 ``` ### Notes * Resolving is reversible with `bb pr comments unresolve` * `--json` returns `{ success, pullRequestId, commentId, resolution }`; the API returns the resolution record, not the full comment, use `bb pr comments view` to read the comment back *** ## `bb pr comments unresolve` Reopen a resolved comment thread on a pull request. ```bash bb pr comments unresolve ``` ### Arguments Use the identifiers described [above](#bb-pr-comments). ### Options | Option | Description | | ----------- | --------------------------------------------------------------------------------------------- | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ### Examples ```bash # Reopen comment thread #486512301 on PR #42 bb pr comments unresolve 42 486512301 ``` ### Notes * The API returns no body, so `--json` reports only `{ success, pullRequestId, commentId }` *** ## `bb pr comments delete` Delete a comment from a pull request. Asks for confirmation unless `--yes` is passed. ```bash bb pr comments delete [options] ``` ### Arguments Use the identifiers described [above](#bb-pr-comments). ### Options | Option | Description | | ----------- | --------------------------------------------------------------------------------------------- | | `-y, --yes` | Skip the confirmation prompt (required when not in an interactive terminal) | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ### Examples ```bash # Delete comment #486512301 from PR #42 bb pr comments delete 42 486512301 --yes ``` ### Notes * Without `--yes`, `bb pr comments delete` asks `Continue? (y/N)` in an interactive terminal. Anywhere else (see [`--no-input`](/reference/global-flags/#--no-input)) it exits with a validation error ending in `Use --yes to confirm.` * Deleting a comment is permanent and cannot be undone # Create, Edit, and View PRs > Create pull requests, edit metadata, and inspect PR details Create and inspect pull requests (PRs). See [Global flags](/reference/global-flags/) for JSON output, workspace/repository selection, and display options. Field projection (`--json id,title`) works on list commands such as `bb pr list`. It does not work on `bb pr create`, `bb pr edit` or `bb pr view`. The payload there is a single PR carrying a `reviewers` array, and the projector unwraps that array. It returns reviewers, or `[]` when there are none. Use `--json --jq '{...}'` on those three. ## `bb pr create` Create a pull request. ```bash bb pr create [options] ``` ### Options | Option | Description | | ---------------------------- | --------------------------------------------------------------------------------------------- | | `-t, --title ` | PR title (required; asked for in an interactive terminal when missing) | | `-b, --body <body>` | PR description | | `-F, --body-file <file>` | Read the description from a file, or `-` for stdin | | `-s, --source <branch>` | Source branch (default: current branch) | | `-d, --destination <branch>` | Destination branch (default: the repository’s main branch) | | `--close-source-branch` | Close source branch after merge | | `--draft` | Create the PR as draft | | `--reviewer <user>` | Add a reviewer by name, email, `@me`, account ID or `{uuid}` (repeatable) | | `--default-reviewers` | Include the repository’s default reviewers (opt-in) | | `--no-default-reviewers` | Skip default reviewers even when the config key enables them | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ### Examples ```bash # Create a PR from the current branch to the repository's main branch bb pr create -t "Add new feature" # Create a PR with full details bb pr create -t "Add login page" -b "Implements user login functionality" -d develop # Read a multi-line markdown description from a file, or from stdin with - bb pr create -t "Add login page" -F description.md git log -1 --format=%b | bb pr create -t "Add login page" -F - # Create a PR that will close the source branch after merging bb pr create -t "Hotfix: Critical bug" --close-source-branch # Create a draft PR bb pr create -t "WIP: Add feature" --draft # Auto-add the repository's default reviewers (matches the Bitbucket web UI) bb pr create -t "Add new feature" --default-reviewers # Add specific reviewers by nickname or display name (repeatable) bb pr create -t "Add new feature" --reviewer jdoe --reviewer "Jane Smith" # Or by account ID or {uuid} bb pr create -t "Add new feature" \ --reviewer "712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f" \ --reviewer "{c1cb1bb5-2e32-456e-a373-43978dc12aa1}" # Combine defaults + explicit additions (duplicates are de-duped) bb pr create -t "Add new feature" --default-reviewers \ --reviewer "712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f" # Capture the new PR's URL from JSON output for scripting bb pr create -t "Add new feature" --json --jq '.links.html.href' ``` ### Interactive prompts Run `bb pr create` without `--title` in an interactive terminal and it asks for the title, then for an optional one-line description (press Enter to skip it; a `--body` or `--body-file` you passed is kept and not asked for). Use `--body-file` for a multi-line description. The questions come after the repository and source branch are resolved, so a bad context fails before you type anything. Outside an interactive terminal (pipes, CI, `--json`, [`--no-input`](/reference/global-flags/#--no-input)) a missing title still fails straight away with `Pull request title is required. Use --title option.` ### Reviewers By default `bb pr create` attaches no reviewers. Use `--default-reviewers` to include the defaults suggested by Bitbucket’s web UI. * `--default-reviewers` opts in per-invocation. The command fetches the repository’s *effective* default reviewers (repo-level + project-inherited) and attaches them. * `--reviewer <user>` adds specific reviewers regardless of the defaults and can be passed multiple times. Accepts a **nickname** or **display name** (matched against the workspace members), an **email** (workspace admins only), `@me`, an **account ID** (e.g. `712020:3cfed7e0-...`) or a **UUID** in curly braces (e.g. `{c1cb1bb5-...}`). An unknown or ambiguous name aborts the create and, when ambiguous, lists the candidates. See [Identifying users](/commands/pr/reviewers/#identifying-users) for the rules. You can’t review your own PR, so the author (including `@me`) is dropped from the list. * The CLI excludes the author when the current-user lookup returns a UUID. If that lookup fails, Bitbucket may reject a self-review assignment. * To make `--default-reviewers` the default behavior, set the config key: ```bash bb config set prCreateIncludeDefaultReviewers true ``` Pass `--no-default-reviewers` to skip defaults for a single invocation when this is enabled. * If the default-reviewer fetch fails (network error, permission issue, etc.) the CLI prints `Could not fetch default reviewers: … Continuing without them.` and creates the PR anyway. Only the *defaults* are dropped, reviewers you passed with `--reviewer` are still attached. A failed `--reviewer` lookup, by contrast, aborts the create. See [`bb repo default-reviewers`](/commands/repo/default-reviewers/) to inspect or manage the underlying default reviewer list. ### Notes * `-F/--body-file` sends the file content exactly as written, so markdown with backticks, quotes or `$` needs no shell escaping * Passing both `-b/--body` and `-F/--body-file` fails with `Cannot combine --body with --body-file. Pass one or the other.` * `-F -` reads stdin, so it can’t also answer the title prompt: pass `--title` with it * An unreadable path fails with `Failed to read file '<path>': <reason>` *** ## `bb pr edit` Edit an existing pull request’s title or description. ```bash bb pr edit [id] [options] ``` `[id]` is the PR number. Omit it to use the open PR whose source branch is your current git branch ([how it is picked](/commands/pr/#pull-request-from-the-current-branch)). ### Options | Option | Description | | ------------------------ | --------------------------------------------------------------------------------------------- | | `-t, --title <title>` | New PR title | | `-b, --body <body>` | New PR description | | `-F, --body-file <file>` | Read the description from a file, or `-` for stdin | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ### Examples ```bash # Edit the title by ID bb pr edit 42 -t "Updated: Add new feature" # Edit the description bb pr edit 42 -b "This PR implements the new login flow" # Edit both title and description bb pr edit 42 -t "New title" -b "New description" # Auto-detect the PR from the current branch and update the title bb pr edit -t "Updated title" # Read the description from a file, or from stdin with - bb pr edit 42 -F description.md cat description.md | bb pr edit 42 -F - # Get the updated PR as JSON bb pr edit 42 -t "New title" --json ``` ### Notes * When no ID is provided, the command searches for an open PR where the source branch matches your current git branch * At least one of `--title`, `--body`, or `--body-file` must be provided * If both `-b/--body` and `-F/--body-file` are given, the file wins and no error is raised * An unreadable path fails with `Failed to read file '<path>': <reason>` *** ## `bb pr list` List pull requests. ```bash bb pr list [options] ``` ### Options | Option | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | | `-s, --state <state>` | Filter by state: OPEN, MERGED, DECLINED, SUPERSEDED (default: OPEN) | | `--limit <number>` | Maximum number of PRs (default: 25) | | `--all` | List all PRs (overrides `--limit`) | | `--author <user>` | Only PRs authored by this user (see below for accepted forms) | | `--reviewer <user>` | Only PRs with this reviewer (see below for accepted forms) | | `--mine` | Same as `--reviewer @me` | | `--source <branch>` | Only PRs from this source branch | | `--destination <branch>` | Only PRs into this destination branch | | `--query <bbql>` | Raw [BBQL](https://developer.atlassian.com/cloud/bitbucket/rest/intro/#filtering) filter, combined with the other filters using `AND` | ### Examples ```bash # List open PRs in current repository bb pr list # List merged PRs bb pr list -s MERGED # List declined PRs bb pr list -s DECLINED # List PRs in specific repository bb pr list -w myworkspace -r myrepo # List with JSON output for scripting bb pr list --json # Project to specific fields (returns a flat array) bb pr list --json id,title,author.display_name # Filter with built-in --jq (no external jq binary needed) bb pr list --json --jq '.pullRequests[] | select(.state == "OPEN") | .title' # List more results bb pr list --limit 50 # Fetch every open PR, ignoring the default limit of 25 bb pr list --all # PRs you opened bb pr list --author @me # PRs assigned to you for review (same as --mine) bb pr list --reviewer @me # The open PR for a branch bb pr list --source feature/login # Merged PRs into develop bb pr list --destination develop -s MERGED # Anything BBQL can express, e.g. a title search bb pr list --query 'title ~ "hotfix"' ``` ### Notes * Draft PRs are shown with a `[DRAFT]` prefix in the title * `--limit` is enforced across paginated API responses * Columns: ID, TITLE, AUTHOR, BRANCHES, UPDATED. UPDATED is relative on a terminal (`2 hours ago`) and ISO 8601 when piped * Long titles and branch names are shortened to fit the terminal width. Pass `--no-truncate` for full titles; `--json` output is never truncated * All filters run server-side through the Bitbucket `q` parameter, so `--limit` counts matching PRs only * `--author` and `--reviewer` accept a nickname, display name, email (workspace admins only), `@me`, an account ID or a `{uuid}`, resolved the same way as `bb pr create --reviewer` (see [Identifying users](/commands/pr/reviewers/#identifying-users)), then match on the UUID * `--mine` is kept for compatibility. It means “PRs I review”, not “PRs I wrote”; use `--author @me` for those * A malformed `--query` is rejected by Bitbucket with an HTTP 400 and its error message *** ## `bb pr status` Show what needs your attention in the current repository: the open PR for the branch you have checked out, your open PRs, and open PRs where you are a reviewer. ```bash bb pr status ``` ```plaintext myworkspace/myrepo Current branch #42 Add login page [feature/login] Created by you #42 Add login page [feature/login] #40 [DRAFT] Rework settings [settings] Requesting your review #38 Bump dependencies [deps] ``` ### Notes * The “Current branch” section only appears filled when you run the command inside a clone of the target repository; with `-w`/`-r` pointing at another repository it reads “Not on a branch of this repository” * Each list shows up to 25 PRs; the footer names the `bb pr list` command that shows the rest * `--json` returns `{ workspace, repoSlug, currentBranch, currentBranchPullRequest, createdByYou, reviewRequested }`; `currentBranch` and `currentBranchPullRequest` are `null` when there is nothing to show *** ## `bb pr view` View pull request details. ```bash bb pr view [id] [options] ``` `[id]` is the PR number. Omit it to use the open PR for your current branch. ### Examples ```bash # View PR #42 in current repository bb pr view 42 # View the open PR for the current branch bb pr view # View PR in specific repository bb pr view 42 -w myworkspace -r myrepo # Get PR details as JSON bb pr view 42 --json # Pick out fields with built-in --jq bb pr view 42 --json --jq '{id, title, state, author: .author.display_name}' # Extract just the web URL bb pr view 42 --json --jq '.links.html.href' ``` ### Notes * On a terminal the output opens in your pager (`less -FRX` unless [`BB_PAGER` or `PAGER`](/reference/environment-variables/#pager) says otherwise). Short output prints and returns straight away # Diff and Checkout > Checkout pull request branches locally and inspect diff output Review pull request changes with local checkout and diff tooling. See [Global flags](/reference/global-flags/) for JSON output, workspace/repository selection, and display options. ## `bb pr checkout` Check out a pull request’s source branch locally. ```bash bb pr checkout <id> [options] ``` ### Arguments | Argument | Description | | -------- | --------------- | | `id` | Pull request ID | ### Options Only [global flags](/reference/global-flags/) apply. ### Examples ```bash # Checkout PR #42 to review locally bb pr checkout 42 # Checkout PR from specific repository bb pr checkout 42 -w myworkspace -r myrepo ``` ### Notes The command fetches only the pull request’s source branch, then checks it out: * **Branch in this repository:** it uses the git remote that points at the repository (whatever its name, falling back to `origin` when no remote URL matches) and checks out `<source-branch>`. A new branch tracks `<remote>/<source-branch>`. * **Branch in a fork:** it fetches from the fork’s remote if you have one, otherwise straight from the fork’s URL (same protocol as your remote), and checks it out as `pr-<id>`. Your own branches are never touched, even when the fork’s branch has the same name (for example `main`). * **Local branch already exists:** it is fast-forwarded to the latest commit, and its upstream setting is left alone. Unpushed local commits on top of the pull request are kept. If the branch has diverged from the pull request, the command fails before switching branches rather than overwrite anything. git errors, such as uncommitted changes that would be overwritten, stop the command and are reported as they are. Fetch progress is shown on stderr. `--json` returns `{ success, pullRequestId, branch, pullRequest }`, where `branch` is the local branch that was checked out. *** ## `bb pr diff` View the diff of a pull request in unified diff format. ```bash bb pr diff [id] [options] ``` ### Arguments | Argument | Description | | -------- | -------------------------------------------------------------------------- | | `id` | Pull request ID (optional, defaults to the open PR for the current branch) | ### Options | Option | Description | | ---------------- | ---------------------------------------------------------------------- | | `--color <when>` | Colorize output: `auto`, `always`, `never` (default: auto) | | `--name-only` | Show only names of changed files | | `--stat` | Show diffstat (files changed, insertions, deletions) | | `--web` | Open diff in web browser; prints the URL when stdout is not a terminal | ### Examples ```bash # View diff for PR #42 bb pr diff 42 # Auto-detect PR from current branch bb pr diff # Show only changed file names bb pr diff 42 --name-only # Show statistics (like git diff --stat) bb pr diff 42 --stat # Open diff in browser bb pr diff 42 --web # Return browser URL as JSON bb pr diff 42 --web --json # Disable colors for piping to file or other commands bb pr diff 42 --color never > pr-42.patch # Get diffstat as JSON for scripting bb pr diff 42 --stat --json ``` `--stat` output: ```text src/index.ts | +12 -3 src/utils.ts | +4 docs/README.md | -8 3 files changed, 16 insertions(+), 11 deletions(-) ``` Diffstat can be incomplete `--stat` and `--name-only` fetch one diffstat page. For a large PR, file counts and addition/deletion totals may cover only part of the changes. For complete totals, use the [paginated reporting recipe](/recipes/reporting-analytics/). ### Notes * When no ID is provided, the command searches for an open pull request whose source branch matches your current git branch * `--color auto` colors the diff only when stdout is a terminal: green for additions, red for deletions, cyan for hunk headers. Whole lines are colored by their leading marker, there is no language-aware highlighting * On a terminal the diff opens in your pager (`less -FRX` unless [`BB_PAGER` or `PAGER`](/reference/environment-variables/#pager) says otherwise). Piped output and `--json` are never paged * `--color never` forces plain text, which is what you want when redirecting to a file or piping into another command. The global `--no-color` flag does the same for every command * The value is validated before the request. A typo fails with `--color must be one of: auto, always, never` plus a `(Did you mean never?)` suggestion, rather than silently falling back * Passing `--color <when>` at all turns the *global* color setting on, because the CLI resolves color by scanning raw argv for a `--color` token. `bb pr diff 42 --color never` still leaves the diff body uncolored, but it overrides `--no-color` and `NO_COLOR` for everything else that invocation prints. See [Global Flags → Precedence summary](/reference/global-flags/#precedence-summary) * `-w` is the global short alias for `--workspace`. To open the diff in a browser you must spell out `--web` * For opening other Bitbucket pages (PR detail, files, commits, pipelines, settings) in the browser, see [`bb browse`](/commands/browse/) # Review and Merge > Approve, request changes, decline, mark ready, and merge pull requests The commands that review a pull request or change its state: `bb pr approve`, `bb pr unapprove`, `bb pr request-changes`, `bb pr decline`, `bb pr ready`, `bb pr merge`. See [Global flags](/reference/global-flags/) for JSON output, workspace/repository selection, and display options. On these commands the field list is matched against the result envelope shown under [JSON output](#json-output), not against the PR, so `--json title` returns `{"title": null}`. Use a dotted path (`--json pullRequest.state`) or `--jq` instead. ## `bb pr merge` ```bash bb pr merge [id] [options] ``` `[id]` is the pull request ID. Omit it to merge the open PR for your current branch ([how it is picked](/commands/pr/#pull-request-from-the-current-branch)). ### Options | Option | Description | | ------------------------- | --------------------------------------------------------------------------------------------- | | `-m, --message <message>` | Merge commit message | | `--close-source-branch` | Delete the source branch after merging | | `--strategy <strategy>` | Merge strategy (see below) | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ### Merge strategies | Strategy | Description | | --------------------- | ---------------------------------------------------------------- | | `merge_commit` | Create a merge commit | | `squash` | Squash all commits into a single commit | | `fast_forward` | Fast-forward if possible, fail otherwise | | `squash_fast_forward` | Squash commits and fast-forward | | `rebase_fast_forward` | Rebase source commits onto destination and fast-forward | | `rebase_merge` | Rebase source commits onto destination and create a merge commit | Omitting `--strategy` uses the repository’s configured merge strategy (typically `merge_commit`), not a CLI default. The CLI sends no strategy at all unless you pass one. Strategy names are checked when the command runs, not by the argument parser. An unknown value fails with [`5002` VALIDATION\_INVALID](/reference/error-codes/#5002---validation_invalid) and the message `--strategy must be one of: merge_commit, squash, …`. Case doesn’t matter (`SQUASH` works); a typo such as `sqush` gets a “did you mean” suggestion. Under `--json` that failure comes back as a JSON error envelope. ### Examples ```bash # Merge PR #42 using the repository's configured strategy bb pr merge 42 # Squash and delete the source branch bb pr merge 42 --strategy squash --close-source-branch # Merge with a custom commit message bb pr merge 42 -m "Merge feature: Add user authentication" # Rebase and fast-forward bb pr merge 42 --strategy rebase_fast_forward # Capture the merge commit hash (--jq prints JSON-quoted strings, so strip them) bb pr merge 42 --json --jq '.pullRequest.merge_commit.hash' | tr -d '"' ``` *** ## `bb pr approve`, `bb pr unapprove`, `bb pr decline`, `bb pr ready` Each takes an optional pull request ID; without one they act on the open PR for your current branch. The only command-specific option is `--dry-run`, which prints the write request instead of sending it ([details](/reference/global-flags/#--dry-run)). ```bash bb pr approve 42 # Approve bb pr unapprove 42 # Withdraw your approval bb pr decline 42 # Decline bb pr ready 42 # Clear the draft flag, marking the PR ready for review bb pr approve # Approve the open PR for the current branch # Any of them against an explicit repository bb pr approve 42 -w myworkspace -r myrepo ``` `bb pr ready` is a pull request update that sets `draft: false`. It sends no other fields. Bitbucket Cloud has no API to reopen a declined pull request, so there is no `bb pr reopen`. Open a new one with `bb pr create` instead. ## `bb pr request-changes` ```bash bb pr request-changes [id] [--undo] [--dry-run] ``` Marks the PR as “changes requested” by you, the counterpart of `bb pr approve`. `--undo` removes your change request again. Without an ID it acts on the open PR for your current branch. ```bash bb pr request-changes 42 bb pr request-changes 42 --undo bb pr request-changes # the open PR for the current branch ``` ## JSON output The commands on this page do not return the same shape. `bb pr approve` and `bb pr unapprove` return only the identifiers: ```json { "success": true, "pullRequestId": 42 } ``` `bb pr request-changes` adds `"changesRequested": true` (`false` with `--undo`). `bb pr decline`, `bb pr ready`, and `bb pr merge` add the pull request exactly as the API returned it, `decline` and `merge` change the state, while `ready` clears `draft` without requesting a state change. Abridged, for `bb pr merge`: ```json { "success": true, "pullRequestId": 42, "pullRequest": { "id": 42, "title": "Add user authentication", "state": "MERGED" } } ``` A script that reads `.pullRequest` after `bb pr approve --json` gets `null`. Fetch the PR separately with `bb pr view 42 --json` if you need its fields after approving. # Reviewers > List, add, and remove pull request reviewers Manage pull request (PR) reviewers. See [Global flags](/reference/global-flags/) for JSON output, workspace/repository selection, and display options. ## Identifying users The `<user>` positional (and `bb pr create --reviewer`) accepts any of these: | Form | Example | How it is resolved | | ------------------------ | --------------------------------------------- | -------------------------------------------------- | | `@me` | `@me` | The authenticated account (`GET /user`) | | Account ID | `712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f` | Looked up directly | | UUID in braces | `{c1cb1bb5-2e32-456e-a373-43978dc12aa1}` | Looked up directly | | Email | `jane@example.com` | Workspace members filtered by email (admins only) | | Nickname or display name | `jdoe`, `"Jane Doe"` | Exact, case-insensitive match on workspace members | Names are matched against the members of the PR’s workspace. A nickname match wins over a display name match. The member list is fetched once per command run (one request per 50 members) and reused for every name you pass. An email asks Bitbucket for that member directly and only counts if the member Bitbucket returns has that email. * **No match** fails with `No member of workspace '<ws>' has the nickname or display name '<name>'` (error code 2002). * **Several matches** (two people called “John Park”) fail with error code 5002 and list every candidate with its account ID, so you can rerun with the ID: ```text 'John Park' matches 2 members of workspace 'myworkspace': John Park nickname: jpark 712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f John Park nickname: johnp 712020:9a1b2c3d-0ed6-49fc-bb35-410a00ccee6f Pass one of the account IDs above instead. ``` * **Email** lookups only work when Bitbucket lets you filter members by email, which it allows for workspace admins and workspace or integration tokens. Bitbucket never returns email addresses, so for everyone else an email simply finds no match; use a name or ID instead. Account IDs and UUIDs also come back from `bb pr reviewers list --json`, as the `account_id` and `uuid` fields, which is the most reliable form for scripts: ```bash # One object per reviewer: [{"account_id": "712020:3cfed..."}, …] bb pr reviewers list 42 --json account_id # Raw IDs for shell scripts bb pr reviewers list 42 --json --jq '.reviewers[].account_id' --raw-output ``` `--json account_id` returns a flat array of objects. Built-in `--jq` prints JSON-quoted strings unless you add `--raw-output`. For assigning reviewers in bulk, including author exclusion, see the [reviewer assignment recipe](/recipes/bulk-reviewer-assignment/). See [`bb pr create`](/commands/pr/create-and-edit/#bb-pr-create) for matching `--reviewer` examples. ## `bb pr reviewers` | Subcommand | Description | | -------------------- | ------------------------------------- | | `list <id>` | List reviewers on a pull request | | `add <id> <user>` | Add a reviewer to a pull request | | `remove <id> <user>` | Remove a reviewer from a pull request | None of the three take command-specific options, only the global ones. `<id>` is the pull request ID; `<user>` is any of the [forms above](#identifying-users). *** ## `bb pr reviewers list` ```bash bb pr reviewers list <id> ``` ```bash # List reviewers on PR #42 bb pr reviewers list 42 # List reviewers in a specific repository bb pr reviewers list 42 -w myworkspace -r myrepo ``` Human output is a two-column table of display name and account ID. If the pull request has no reviewers, the command prints `No reviewers assigned to this pull request`. The deprecated `username` field is never shown, Bitbucket Cloud stopped returning it for GDPR reasons. `--json` returns the full envelope: ```json { "workspace": "myworkspace", "repoSlug": "myrepo", "pullRequestId": 42, "count": 1, "reviewers": [ { "display_name": "Jane Doe", "account_id": "712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f", "uuid": "{c1cb1bb5-2e32-456e-a373-43978dc12aa1}" } ] } ``` *** ## `bb pr reviewers add` Add a reviewer by [nickname, display name, email, `@me`, account ID or UUID](#identifying-users). ```bash bb pr reviewers add <id> <user> ``` ### Options | Option | Description | | ----------- | --------------------------------------------------------------------------------------------- | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ```bash # By nickname or display name bb pr reviewers add 42 jdoe bb pr reviewers add 42 "Jane Doe" # Yourself bb pr reviewers add 42 @me # By account ID bb pr reviewers add 42 "712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f" # By UUID (keep the braces, and quote the argument so the shell leaves them alone) bb pr reviewers add 42 "{c1cb1bb5-2e32-456e-a373-43978dc12aa1}" ``` Adding someone who is already a reviewer succeeds and changes nothing. *** ## `bb pr reviewers remove` Remove a reviewer. Same `<user>` rules as `add`. ```bash bb pr reviewers remove <id> <user> ``` ### Options | Option | Description | | ----------- | --------------------------------------------------------------------------------------------- | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | ```bash # By nickname bb pr reviewers remove 42 jdoe # By account ID bb pr reviewers remove 42 "712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f" # By UUID bb pr reviewers remove 42 "{c1cb1bb5-2e32-456e-a373-43978dc12aa1}" ``` Removing someone who is not a reviewer succeeds and changes nothing. ## JSON output for `add` and `remove` Both commands emit the same envelope. `reviewer.username` echoes the `<user>` value you passed, whatever form it was in; `reviewer.uuid` is the resolved UUID. ```json { "success": true, "pullRequestId": 42, "reviewer": { "username": "712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f", "uuid": "{c1cb1bb5-2e32-456e-a373-43978dc12aa1}" }, "pullRequest": { "id": 42, "title": "Add user authentication" } } ``` ## When the user lookup fails Both commands resolve `<user>` before touching the pull request, so a failed lookup never changes the reviewer list. Names and emails fail with the messages described under [Identifying users](#identifying-users). A bad account ID or UUID fails at Bitbucket’s user endpoint with a 404, carrying whatever message Bitbucket returns. The CLI appends its generic 404 hint, which mentions `--workspace` and `--repo`, but for these two commands the wrong value is almost always the `<user>` argument, not the repository. # Repository default reviewers > Manage repository defaults and inherited project reviewers. See [Global flags](/reference/global-flags/) for JSON output and workspace/repository selection. ## `bb repo default-reviewers` Default reviewers are auto-suggested when someone opens a pull request in Bitbucket’s web UI. This group reads and edits that list. ### `bb repo default-reviewers list` ```bash bb repo default-reviewers list [options] ``` By default the **effective** reviewer list is shown: reviewers configured directly on the repository *and* reviewers inherited from the parent project, matching what Bitbucket’s web UI would auto-populate. | Option | Description | | ------------- | ---------------------------------------------------------------------------- | | `--repo-only` | Only show reviewers configured on the repository (exclude project-inherited) | ```bash # Effective list (repo + project-inherited) bb repo default-reviewers list # Only repo-level entries bb repo default-reviewers list --repo-only # JSON for scripting bb repo default-reviewers list --json ``` `--json` emits `{ workspace, repoSlug, mode, count, reviewers }`, where `mode` is `effective` or `direct`. ### `bb repo default-reviewers add` ```bash bb repo default-reviewers add <user> ``` #### Options | Option | Description | | ----------- | --------------------------------------------------------------------------------------------- | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | Adds a user as a default reviewer on the repository. Requires repository admin permission. `<user>` accepts an account ID or a UUID in braces, not a nickname. See [Identifying users](/commands/pr/reviewers/#identifying-users) for how to find these IDs. ```bash bb repo default-reviewers add "712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f" bb repo default-reviewers add "{c1cb1bb5-2e32-456e-a373-43978dc12aa1}" ``` ### `bb repo default-reviewers remove` ```bash bb repo default-reviewers remove <user> --yes ``` #### Options | Option | Description | | ----------- | --------------------------------------------------------------------------------------------- | | `--dry-run` | Print the write request instead of sending it ([details](/reference/global-flags/#--dry-run)) | Removes a user from the repository’s default reviewers. Without `--yes` it asks for confirmation in an interactive terminal and fails everywhere else (see [`--no-input`](/reference/global-flags/#--no-input)). Requires repository admin permission. `<user>` accepts the same identifiers as `add` (account ID or `{uuid}`). ```bash bb repo default-reviewers remove "712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f" --yes ``` ### Notes * Project-inherited reviewers can only be removed by editing the parent project, not the repository. * Related: [`bb pr create --default-reviewers`](/commands/pr/create-and-edit/) applies these reviewers when opening a pull request. # Auto-merge when CI is green > Poll every build-status page, require named checks, and recheck the PR head before requesting a merge. This recipe requires an approval and an explicit list of CI check keys. It reads every status page with `bb api --paginate`, then checks that the PR head still matches the commit inspected. Caution Configure Bitbucket’s required checks and approval rules on the destination branch before using this script. A head or status can change between the final read and the merge request. The CLI cannot make these operations atomic; server-side merge policies must enforce the actual merge requirements. ## What “all-green” means Each required key must have exactly one status with `state: SUCCESSFUL`. Every returned status must also be successful. Missing checks, zero checks, duplicate keys, `INPROGRESS`, `STOPPED` and unknown states never permit a merge. A failed check aborts the run. Set `REQUIRED_CHECK_KEYS` to the exact keys your CI publishes, separated by spaces. These are status keys, not display names. Keep keys free of whitespace for this script. `bb pr checks 42 --watch` waits for running checks and exits non-zero when one failed or stopped, but it does not know which keys you require, so this recipe reads the statuses itself. ### jq filter for all-green ```bash bb api "/repositories/$WORKSPACE/$REPO/pullrequests/42/statuses" --paginate --json \ | jq --arg keys 'build test' ' .values as $statuses | ($keys | split(" ")) as $required | ($statuses | length) > 0 and all($statuses[]; .state == "SUCCESSFUL") and ([$statuses[].key] | length == (unique | length)) and all($required[]; . as $key | [$statuses[] | select(.key == $key)] | length == 1) ' ``` ## Recipe: poll-then-merge Save as `auto-merge-on-green.sh`. It exits `0` after a successful merge, `1` on errors or timeout, and `2` when `--once` finds a PR that is not ready. ```bash #!/bin/bash set -euo pipefail WORKSPACE="${WORKSPACE:?set WORKSPACE}" REPO="${REPO:?set REPO}" PR_ID="${1:?Usage: $0 <pr-id> [--once]}" REQUIRED_CHECK_KEYS="${REQUIRED_CHECK_KEYS:?set required CI check keys}" TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-1800}" POLL_INTERVAL="${POLL_INTERVAL:-30}" once="${2:-}" path="/repositories/$WORKSPACE/$REPO/pullrequests/$PR_ID" required=$(printf '%s' "$REQUIRED_CHECK_KEYS" | jq -Rc 'split(" ") | map(select(length > 0)) | unique') jq -e 'length > 0' <<< "$required" >/dev/null deadline=$(( $(date +%s) + TIMEOUT_SECONDS )) while true; do pr=$(bb api "$path" --json) [ "$(jq -r '.state' <<< "$pr")" = OPEN ] || exit 2 head=$(jq -er '.source.commit.hash | select(type == "string" and length > 0)' <<< "$pr") statuses=$(bb api "$path/statuses" --paginate --json) jq -e '.values | type == "array"' <<< "$statuses" >/dev/null if jq -e 'any(.values[]; .state == "FAILED")' <<< "$statuses" >/dev/null; then echo "PR #$PR_ID has a failed check." >&2 exit 1 fi if jq -e --argjson required "$required" ' .values as $statuses | ($statuses | length) > 0 and all($statuses[]; .state == "SUCCESSFUL") and ([$statuses[].key] | length == (unique | length)) and all($required[]; . as $key | [$statuses[] | select(.key == $key)] | length == 1) ' <<< "$statuses" >/dev/null; then current=$(bb api "$path" --json) if jq -e --arg head "$head" ' .state == "OPEN" and .source.commit.hash == $head and any(.participants[]?; .approved == true) ' <<< "$current" >/dev/null; then bb pr merge "$PR_ID" -w "$WORKSPACE" -r "$REPO" \ --strategy squash --close-source-branch exit 0 fi fi [ "$once" != --once ] || exit 2 if [ "$(date +%s)" -ge "$deadline" ]; then echo "Timed out waiting for PR #$PR_ID checks and approval." >&2 exit 1 fi sleep "$POLL_INTERVAL" done ``` ### Usage ```bash WORKSPACE=myworkspace REPO=myrepo REQUIRED_CHECK_KEYS="build test" \ ./auto-merge-on-green.sh 42 ``` ## Recipe: scan all open PRs Save the script above alongside this one. Run it on a schedule to attempt each ready PR once. A failed check, API error or rejected merge makes the scan exit nonzero after processing the remaining PRs. ```bash #!/bin/bash set -euo pipefail WORKSPACE="${WORKSPACE:?set WORKSPACE}" REPO="${REPO:?set REPO}" export WORKSPACE REPO export REQUIRED_CHECK_KEYS="${REQUIRED_CHECK_KEYS:?set required CI check keys}" script_dir=$(cd "$(dirname "$0")" && pwd) open_prs=$(bb pr list -w "$WORKSPACE" -r "$REPO" --all --json --jq '.pullRequests[].id') failed=0 for pr_id in $open_prs; do if "$script_dir/auto-merge-on-green.sh" "$pr_id" --once; then echo "Merged PR #$pr_id" else status=$? if [ "$status" -eq 2 ]; then echo "PR #$pr_id: not ready" else echo "PR #$pr_id: check or merge failed" >&2 failed=1 fi fi sleep 2 done exit "$failed" ``` Both scripts need Bash and external jq. `--all` makes the PR scan include older open PRs rather than only the default first 25. ## Related * [`bb pr checks`](/commands/pr/activity-and-checks/#bb-pr-checks) * [`bb pr merge`](/commands/pr/review-and-merge/) * [Scripting and automation](/guides/scripting/) # Bulk reviewer assignment > Assign a list of reviewers across many open pull requests at once; useful for team rotations, onboarding, and review coverage policies. Assign reviewers to existing open pull requests without removing the reviewers already there. Use repository default reviewers if you only need assignments on new PRs. ## Identifying reviewers `bb pr reviewers add` takes a nickname, display name, email, `@me`, account ID (`712020:3cfed7e0-...`) or braced UUID (`{c1cb1bb5-...}`). Names cost a workspace member lookup on every call, so the scripts below keep the pool as account IDs. See [Identifying users](/commands/pr/reviewers/#identifying-users) for the rules and for how to look the IDs up. These scripts use account IDs only and compare them with `author.account_id`. Do not mix UUIDs or display names into the pool. Missing author IDs stop the run before any assignments. ## Recipe: assign a fixed reviewer list Adds every account ID in `REVIEWERS` to every open PR in `WORKSPACE/REPO`. Existing reviewers are not removed; if a reviewer is already assigned, [`bb pr reviewers add`](/commands/pr/reviewers/#bb-pr-reviewers-add) is a no-op. bulk-assign-reviewers.sh ```bash #!/bin/bash set -euo pipefail WORKSPACE="${WORKSPACE:-myworkspace}" REPO="${REPO:-myrepo}" # Space-separated Bitbucket account IDs (not usernames, not display names). REVIEWERS="${REVIEWERS:?set REVIEWERS to space-separated account IDs}" open_prs=$(bb pr list -w "$WORKSPACE" -r "$REPO" --all --json \ | jq -er ' if all(.pullRequests[]; .author.account_id | type == "string" and length > 0) then [.pullRequests[] | "\(.id)\t\(.author.account_id)"] | join("\n") else error("Missing PR author account ID") end ') failed=0 while IFS=$'\t' read -r pr_id author; do [ -n "$pr_id" ] || continue echo "PR #$pr_id (by $author)" for reviewer in $REVIEWERS; do if [ "$reviewer" = "$author" ]; then echo " - skip $reviewer (PR author)" continue fi if bb pr reviewers add "$pr_id" "$reviewer" \ -w "$WORKSPACE" -r "$REPO" >/dev/null; then echo " + added $reviewer" else echo " ! failed to add $reviewer" >&2 failed=1 fi sleep 1 # rate-limit cushion done done <<< "$open_prs" exit "$failed" ``` ### Usage ```bash WORKSPACE=myworkspace REPO=myrepo \ REVIEWERS="712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f 712020:9ab1f22c-51de-4e7d-9f0e-2b7a10cd3311" \ ./bulk-assign-reviewers.sh ``` Each assignment may resolve the user, fetch the PR and update it. A bulk run can make several requests per reviewer. Both scripts continue after individual assignment failures and exit nonzero if any failed. ## Recipe: rotation by hash bucket To select one reviewer per PR, take its ID modulo the eligible pool size. The author is always excluded. With the same pool and author, the selection is stable; changing either can select someone else. Existing reviewers remain assigned. rotation-assign.sh ```bash #!/bin/bash set -euo pipefail WORKSPACE="${WORKSPACE:-myworkspace}" REPO="${REPO:-myrepo}" # Account IDs, same rule as above. POOL=( "712020:3cfed7e0-0ed6-49fc-bb35-410a00ccee6f" "712020:9ab1f22c-51de-4e7d-9f0e-2b7a10cd3311" "712020:c40be5aa-7c19-4a0b-83f2-6d1e94ab7702" ) open_prs=$(bb pr list -w "$WORKSPACE" -r "$REPO" --all --json \ | jq -er ' if all(.pullRequests[]; .author.account_id | type == "string" and length > 0) then [.pullRequests[] | "\(.id)\t\(.author.account_id)"] | join("\n") else error("Missing PR author account ID") end ') failed=0 while IFS=$'\t' read -r pr_id author; do [ -n "$pr_id" ] || continue eligible=() for reviewer in "${POOL[@]}"; do [ "$reviewer" = "$author" ] || eligible+=("$reviewer") done if [ "${#eligible[@]}" -eq 0 ]; then echo "PR #$pr_id: no eligible reviewer" >&2 failed=1 continue fi idx=$(( pr_id % ${#eligible[@]} )) reviewer="${eligible[$idx]}" if ! bb pr reviewers add "$pr_id" "$reviewer" -w "$WORKSPACE" -r "$REPO"; then failed=1 fi sleep 1 done <<< "$open_prs" exit "$failed" ``` ## Handling rate limits The CLI already retries 429 responses up to 3 times automatically. For large bulk operations, use a larger delay or bound each run with `--limit 50`. There is no offset flag, so track handled IDs to avoid repeatedly processing the same page. Split large runs across scheduled jobs. Use the [retry wrapper](/recipes/retry-wrapper/) only when rate limits persist beyond the built-in retries. ## Related * [`bb pr reviewers add`](/commands/pr/reviewers/#bb-pr-reviewers-add) * [`bb repo default-reviewers`](/commands/repo/default-reviewers/) * [Reviewers reference](/commands/pr/reviewers/)