CI/CD integration
The Bitbucket CLI automates pull request (PR) workflows, reports build statuses back to commits, and triggers Bitbucket Pipelines from any CI system.
Quick setup
Section titled “Quick setup”-
Store credentials as secrets in your CI/CD platform.
BB_USERNAME, your Atlassian account emailBB_API_TOKEN, your Bitbucket API token
-
Install the CLI. The standalone binary needs no Bun, Node.js or npm, so the job skips the runtime install. Verify it against the release’s
SHA256SUMSbefore running it:Terminal window base=https://github.com/0pilatos0/bitbucket-cli/releases/latest/downloadcurl -fsSLO "$base/bb-linux-x64"curl -fsSLO "$base/SHA256SUMS"sha256sum --check --ignore-missing SHA256SUMSinstall -D -m 755 bb-linux-x64 "$HOME/.local/bin/bb"export PATH="$HOME/.local/bin:$PATH"Replace
latest/downloadwithdownload/v<version>to pin a release, andbb-linux-x64withbb-linux-arm64on arm64 agents. See Installation for the other platforms and forgh attestation verify. The binary needs glibc, so on Alpine use the Bun route below.To use the npm package instead, install Bun first. The package is Bun-only; it exits immediately under Node.js.
Terminal window curl -fsSL https://bun.sh/install | bashexport PATH="$HOME/.bun/bin:$PATH"bun install -g @pilatos/bitbucket-cliOn an image that already ships Bun (
oven/bun:latest) skip thecurlline and keep the other two, those images contain no Node.js and no npm. -
Authenticate. With
BB_API_TOKENset in the environment,bb auth logintakes the API-token path and stores the credentials. With no token set it opens a browser for OAuth and waits five minutes for a callback that never arrives in a headless runner.Terminal window bb auth login -
Run commands with explicit workspace and repository flags.
Terminal window bb pr list -w myworkspace -r myrepo --json
Paging
Section titled “Paging”List commands return 25 items by default. Pass --limit <n> to raise or lower that cap, or --all to fetch every page. --all overrides --limit.
bb pr list -w myworkspace -r myrepo --all --jsonSee Global Flags.
Reading JSON without an external jq
Section titled “Reading JSON without an external jq”--json [fields] and --jq <expression> are global flags. --jq runs an embedded jq, so it works on minimal CI images and on Windows agents that have no jq binary. --jq requires --json.
# Project to a comma-separated field listbb pr list -w myworkspace -r myrepo --json id,title
# Filter with the embedded jqbb pr list -w myworkspace -r myrepo --all --json --jq '.pullRequests[].id'Projection runs before jq, and --json <fields> drops the envelope on list commands, count disappears once you project. See Scripting & Automation.
Platform examples
Section titled “Platform examples”Each snippet shows the platform-specific part: how secrets reach the job, and how the CLI gets on PATH. The GitHub Actions example uses the standalone binary and the others use Bun; either install from Quick setup works on any of them. The bb auth login step is the same everywhere.
GitHub Actions
Section titled “GitHub Actions”name: Bitbucket PR Check
on: push: branches: [main] pull_request:
jobs: check-bitbucket-prs: runs-on: ubuntu-latest
steps: - uses: actions/checkout@v4
- name: Install Bitbucket CLI run: | base=https://github.com/0pilatos0/bitbucket-cli/releases/latest/download curl -fsSLO "$base/bb-linux-x64" curl -fsSLO "$base/SHA256SUMS" sha256sum --check --ignore-missing SHA256SUMS install -D -m 755 bb-linux-x64 "$HOME/.local/bin/bb" echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: List open PRs env: BB_USERNAME: ${{ secrets.BB_USERNAME }} BB_API_TOKEN: ${{ secrets.BB_API_TOKEN }} run: | bb auth login bb pr list -w myworkspace -r myrepo --all --json --jq '.count'Appending to $GITHUB_PATH puts bb on PATH for every later step.
GitLab CI
Section titled “GitLab CI”stages: - check
variables: BB_WORKSPACE: myworkspace BB_REPO: myrepo
check-prs: stage: check image: oven/bun:latest
before_script: - bun install -g @pilatos/bitbucket-cli - export PATH="$HOME/.bun/bin:$PATH" - bb auth login
script: - bb pr list -w $BB_WORKSPACE -r $BB_REPO --json - bb repo view -w $BB_WORKSPACE -r $BB_REPODefine BB_USERNAME and BB_API_TOKEN under Settings > CI/CD > Variables (masked, protected). GitLab exports project variables into the job environment, so no variables: entry is needed for them.
Bitbucket Pipelines
Section titled “Bitbucket Pipelines”image: oven/bun:latest
pipelines: default: - step: name: Check PRs script: - bun install -g @pilatos/bitbucket-cli - export PATH="$HOME/.bun/bin:$PATH" - bb auth login - bb pr list -w $BITBUCKET_WORKSPACE -r $BITBUCKET_REPO_SLUG --json
pull-requests: '**': - step: name: PR Info script: - bun install -g @pilatos/bitbucket-cli - export PATH="$HOME/.bun/bin:$PATH" - bb auth login - bb pr view $BITBUCKET_PR_ID -w $BITBUCKET_WORKSPACE -r $BITBUCKET_REPO_SLUG
definitions: caches: bun: ~/.bunPipelines injects BITBUCKET_WORKSPACE, BITBUCKET_REPO_SLUG, and BITBUCKET_PR_ID, which the snippet above passes to -w, -r, and bb pr view.
Jenkins
Section titled “Jenkins”pipeline { agent any
environment { BB_USERNAME = credentials('bitbucket-account-email') BB_API_TOKEN = credentials('bitbucket-token') }
stages { stage('Setup') { steps { sh 'curl -fsSL https://bun.sh/install | bash' sh 'export PATH="$HOME/.bun/bin:$PATH" && bun install -g @pilatos/bitbucket-cli' sh 'export PATH="$HOME/.bun/bin:$PATH" && bb auth login' } }
stage('Check PRs') { steps { sh ''' export PATH="$HOME/.bun/bin:$PATH" bb pr list -w myworkspace -r myrepo --all --json --jq '.count' ''' } } }}Each sh step is a fresh shell, so PATH has to be exported in every one.
To automate merges from Jenkins, use the checked merge recipe.
Azure DevOps
Section titled “Azure DevOps”trigger: - main
pool: vmImage: 'ubuntu-latest'
variables: - group: bitbucket-credentials # Variable group with BB_USERNAME, BB_API_TOKEN
steps: - script: | curl -fsSL https://bun.sh/install | bash echo "##vso[task.prependpath]$HOME/.bun/bin" displayName: 'Install Bun'
- script: bun install -g @pilatos/bitbucket-cli displayName: 'Install Bitbucket CLI'
- script: | bb auth login bb pr list -w myworkspace -r myrepo --json displayName: 'List PRs' env: BB_USERNAME: $(BB_USERNAME) BB_API_TOKEN: $(BB_API_TOKEN)##vso[task.prependpath] puts ~/.bun/bin on PATH for every later step.
Common use cases
Section titled “Common use cases”Report build status back to Bitbucket
Section titled “Report build status back to Bitbucket”bb status set <sha> creates or updates a build status on a commit. It is idempotent per --key, so calling it again with the same key replaces the previous status instead of adding a second one.
bb status set "$GITHUB_SHA" -w myworkspace -r myrepo \ --key CI --state INPROGRESS --url "$RUN_URL"
# ... run the build ...
bb status set "$GITHUB_SHA" -w myworkspace -r myrepo \ --key CI --state SUCCESSFUL --url "$RUN_URL" --description "All tests passed"--state accepts INPROGRESS, SUCCESSFUL, FAILED, or STOPPED. --name, --description, and --refname are optional. Read statuses back with bb status list <sha>.
Trigger a Bitbucket pipeline from another CI system
Section titled “Trigger a Bitbucket pipeline from another CI system”# Latest commit on a branchbb pipeline run -w myworkspace -r myrepo --branch main
# A custom pipeline from bitbucket-pipelines.yml, with variablesbb pipeline run -w myworkspace -r myrepo \ --pipeline deploy-prod --var ENV=prod --var DRY_RUN=falsebb pipeline watch waits for the latest run on the current branch and exits non-zero unless it passes; bb pipeline logs --follow streams its logs. bb pipeline list --status FAILED, bb pipeline view <id>, bb pipeline logs <id> --step <n>, and bb pipeline stop <id> cover the rest. See bb pipeline.
Create a PR from a branch
Section titled “Create a PR from a branch”Run this in a branch build after pushing the source branch. It uses external
jq to pass the branch name as data, and lists every open PR before creating one:
set -euo pipefailBRANCH=${GITHUB_REF#refs/heads/}
EXISTING=$(bb pr list -w myworkspace -r myrepo --all --json | \ jq --arg branch "$BRANCH" '[.pullRequests[] | select(.source.branch.name == $branch)] | length')
if [ "$EXISTING" -eq 0 ]; then bb pr create -w myworkspace -r myrepo \ -t "chore: $BRANCH" -b "Opened automatically by CI" \ -s "$BRANCH" -d mainfiUse your platform’s source-branch variable outside GitHub Actions. A concurrent job can create the same PR between the lookup and create call; handle that failure in your job rather than assuming the lookup is a lock.
Merge approved PRs automatically
Section titled “Merge approved PRs automatically”Use Auto-merge on green CI. It reads every build-status page, checks required status keys, and rechecks the PR head before merging. Repository merge policies must enforce your authoritative requirements. One approval alone does not establish that a PR is ready to merge.
Generate a changelog from merged PRs
Section titled “Generate a changelog from merged PRs”See Reporting and analytics for paginated PR reports and diff statistics.
Exit codes and errors
Section titled “Exit codes and errors”Commands exit 0 on success and 1 on failure. Interrupted interactive prompts
exit 130; disable prompts in automation with --no-input. Set
BB_DETAILED_EXIT_CODES=1 to tell usage (2), not found (3), authentication
(4) and confirmation required (5) apart.
In --json mode, successful JSON goes to stdout and command errors,
argument-parsing errors included, go to stderr as JSON. HTTP traces from
BB_DEBUG also go to stderr, so stdout stays parseable.
See Scripting and automation for an error handling example and Error codes for numeric codes.
Security considerations
Section titled “Security considerations”Token scopes
Section titled “Token scopes”Create a dedicated CI token with only the permissions its commands require. Use the scope reference rather than copying a broad scope list. Grant read, write, admin, and delete scopes separately as needed.
Secrets management
Section titled “Secrets management”Store in Settings > Secrets and variables > Actions
Store in Settings > CI/CD > Variables (masked, protected)
Use Credentials plugin with Secret text type
Store as secured repository or workspace variables
Troubleshooting CI/CD
Section titled “Troubleshooting CI/CD”Authentication fails
Section titled “Authentication fails”✗ Authentication required. Run 'bb auth login'.Under --json the same failure appears on stderr as {"name":"BBError","code":1001,...}.
Check that both variables reach the job, that BB_USERNAME is the Atlassian
account email, and that the token has not expired:
echo "Account email set: $([ -n "$BB_USERNAME" ] && echo 'yes' || echo 'no')"echo "Token set: $([ -n "$BB_API_TOKEN" ] && echo 'yes' || echo 'no')"The auth step hangs
Section titled “The auth step hangs”bb auth login only uses the API-token path when BB_API_TOKEN is set (or when you pass -u/-p/--with-token). Otherwise it starts the OAuth browser flow on http://localhost:19872/callback and blocks for five minutes. Set BB_API_TOKEN in the step’s environment.
Rate limiting in loops
Section titled “Rate limiting in loops”Add a delay between API calls:
for pr_id in $pr_ids; do bb pr view "$pr_id" -w myworkspace -r myrepo --json sleep 2donebb: command not found
Section titled “bb: command not found”bun install -g puts binaries in ~/.bun/bin, which is not on PATH in a fresh shell. Export it before calling bb, in the same shell invocation:
export PATH="$HOME/.bun/bin:$PATH"bb --version