A lightweight command-line interface for Bitbucket Cloud. Wraps the Bitbucket REST API for common operations like managing pipelines, pull requests, and repositories. Ships with a Python MCP server so any Claude Code session (or any other MCP-aware client) can drive Bitbucket Cloud as native tools.
The bash CLI has no dependencies beyond curl and jq. The MCP server adds Python 3.10+. Works on macOS, Linux, and WSL.
- Pipelines: List, view, watch, trigger, and stop pipeline builds
- Pull Requests: Create, view, approve, unapprove, merge, decline, diff, comment
- Repositories: List repos, view details, list/show branches, list recent commits
- Browser Integration: Quick-open any resource in your browser
- MCP server: 31 tools covering the full surface, plus git-context wrappers (current branch, status, recent commits, uncommitted changes) for agent workflows
bash(3.2+) — works with macOS system bash; bash 4+ also finecurl- usually pre-installed on macOS/Linuxjq- JSON processor (install instructions)- Python 3.10+ (only required for the MCP server)
macOS (Homebrew):
brew install jqUbuntu/Debian:
sudo apt-get install jqFedora/RHEL:
sudo dnf install jqWindows (via Chocolatey):
choco install jq-
Clone this repository:
git clone https://github.com/daniel-pittman/bitbucket-cli.git cd bitbucket-cli -
Make the script executable:
chmod +x bb
-
Symlink to your PATH. Pick the directory that's on your PATH and that you own:
# macOS with Homebrew (no sudo needed; resolves to /opt/homebrew on # Apple Silicon, /usr/local on Intel Macs): ln -s "$(pwd)/bb" "$(brew --prefix)/bin/bb" # macOS without Homebrew, or Linux (needs sudo on most setups): sudo ln -s "$(pwd)/bb" /usr/local/bin/bb
Or add the directory to your PATH (pick the rc file your shell uses; macOS defaults to zsh since Catalina):
# bash: echo 'export PATH="$PATH:/path/to/bitbucket-cli"' >> ~/.bashrc # zsh (default on macOS): echo 'export PATH="$PATH:/path/to/bitbucket-cli"' >> ~/.zshrc
Create a config file at ~/.config/bb/config:
mkdir -p ~/.config/bb
cat > ~/.config/bb/config <<EOF
BB_USER=your-email@example.com
BB_TOKEN=your-api-token
BB_WORKSPACE=your-workspace # optional — see "How the workspace is resolved"
EOFBB_USER and BB_TOKEN are required. BB_WORKSPACE is optional: when
you run bb inside a Bitbucket git checkout, the workspace is auto-detected
from the origin remote, so you only need BB_WORKSPACE as a fallback for
commands run outside a repo (e.g. bb repos from an arbitrary directory).
For any command that needs a workspace, bb resolves it in this order
(highest priority first):
-w/--workspace <name>flag — explicit, per-invocation override.workspace/slugargument — e.g.bb pipelines acme/widgettargets theacmeworkspace regardless of git context or config.- git
originauto-detect — when you're inside a Bitbucket checkout, the workspace comes from the remote URL. This is whycd-ing into any repo and runningbb prs/bb pipelinesJust Works across multiple workspaces. BB_WORKSPACE— your configured default, used when none of the above apply (notably for repo-less commands likebb reposrun outside a checkout).- If none resolve a workspace, the command fails with a message naming all three ways to supply one.
This mirrors the MCP server's _resolve_repo behavior, so the bash CLI and the
Python tools agree on which workspace a given invocation targets.
- Go to Atlassian API Tokens
- Click "Create API token"
- Copy the token and set it as
BB_TOKEN - Set
BB_USERto your Bitbucket account email address
Your Bitbucket account needs these workspace permissions:
| Feature | Required Permission |
|---|---|
| View pipelines, PRs, repos | Read access to repositories (read:repository:bitbucket) |
| Trigger/stop pipelines | Read + Write access to Pipelines (read:pipeline:bitbucket, write:pipeline:bitbucket) |
| Create/approve/merge PRs | Read + Write access to Pull Requests (read:pullrequest:bitbucket, write:pullrequest:bitbucket) |
List workspaces (bb workspaces) |
read:workspace:bitbucket (new in v1.2.0 — Atlassian API token scope, opt-in when creating the token) |
List projects (bb projects) |
read:project:bitbucket (Atlassian API token scope, opt-in when creating the token). Verified against the live 403 envelope: the missing scope is named under error.detail.required. |
Create a repository (bb repo-create) |
Admin access to repositories (admin:repository:bitbucket). write:repository:bitbucket alone is not sufficient. |
Update a repository (bb repo-update, e.g. move its project) |
Admin access to repositories (admin:repository:bitbucket). write:repository:bitbucket alone is not sufficient (same scope as bb repo-create). |
Read Pipelines status (bb pipelines-status) |
Read access to Pipelines (read:pipeline:bitbucket). |
Enable/disable Pipelines (bb pipelines-enable, bb pipelines-disable) |
Admin access to Pipelines (admin:pipeline:bitbucket). write:pipeline:bitbucket alone is not sufficient. |
List deployment environments (bb environments) |
Read access to Pipelines (read:pipeline:bitbucket). |
Create/delete deployment environments (bb environment-create, bb environment-delete) |
Admin access to Pipelines (admin:pipeline:bitbucket). write:pipeline:bitbucket alone is not sufficient. |
Set or delete pipeline variables, any scope (bb vars set, bb vars delete, with --workspace / --deployment <env>) |
Admin access to Pipelines (admin:pipeline:bitbucket). write:pipeline:bitbucket alone is not sufficient. This one scope covers set and delete at all three variable scopes (repo, workspace, deployment-environment); verified against the live 403 envelope. |
Note: Atlassian API tokens inherit your account's workspace permissions. If you can perform an action in the Bitbucket UI, the CLI can do it too — provided the token carries the scope. The cross-workspace listing endpoints (/2.0/workspaces, /2.0/repositories?role=member) were removed under Atlassian's CHANGE-2770 on 2026-04-14; bb workspaces uses the replacement /2.0/user/workspaces endpoint (CHANGE-3022) which requires the read:workspace:bitbucket scope. Rotating the token to add it leaves existing tokens unchanged.
The bb repo-create and bb vars set admin scopes are the most common to be missing, because most day-to-day tokens are scoped read + write only. A token's scopes are fixed at creation: adding a scope does not apply to an already-issued token. To use these two commands you must create a new token (or rotate the existing one) with the admin scope included. A token without the scope returns a 403 whose body names the exact missing scope under error.detail.required, so the failure is self-diagnosing.
You can also set configuration via environment variables:
export BB_USER="your-email@example.com"
export BB_TOKEN="your-api-token"
export BB_WORKSPACE="your-workspace"bb <command> [options]
bb pipelines [repo] [count] # List recent pipelines (default: 10)
bb pipeline [repo] <number> # Show pipeline details and steps
bb watch [repo] [number] [interval] # Poll pipeline until done (default: 15s)
bb logs [repo] <number> [step] # Show step logs
bb trigger [repo] [branch] [pattern] # Trigger a pipeline run
bb stop [repo] <number> # Stop a running pipeline
bb approve [repo] <number> # Open pipeline in browser (manual steps require UI)
bb pipelines-status [repo] # Show whether Pipelines (CI) is enabled
bb pipelines-enable [repo] # Enable Pipelines (CI) on a repo
bb pipelines-disable [repo] # Disable Pipelines (CI) on a repoPipelines must be enabled on a repo before pipeline variables, custom pipelines, or builds work at all. bb pipelines-status reports the current state (it reads as "disabled (never configured)" when Pipelines has never been set up, which the API signals with a 404). bb pipelines-enable / bb pipelines-disable toggle it and need admin:pipeline:bitbucket scope.
bb prs [repo] [state] # List PRs (default: OPEN)
bb pr [repo] <id> # View PR details
bb pr-create [repo] <title> [dest] # Create PR from current branch
bb pr-approve [repo] <id> # Approve a PR
bb pr-merge [repo] <id> [strategy] # Merge a PR (merge_commit|squash|fast_forward)
bb pr-decline [repo] <id> # Decline a PR
bb pr-diff [repo] <id> # Show PR diff
bb pr-comments [repo] <id> # Show PR commentsbb branches [repo] # List branches
bb projects [workspace] # List workspace projects
bb repos # List workspace repos
bb repo [repo] # Show repo details
bb repo-create <name> [opts] # Create a repo (default PRIVATE)
bb repo-update [repo] <opts> # Update a repo (move project, change description)
bb downloads [repo] # List repo downloads
bb environments [repo] # List deployment environments
bb environment-create [repo] <name> [--type T] # Create a deployment environment
bb environment-delete [repo] <name> # Delete a deployment environment
bb vars [scope] [repo] # List pipeline variables (repo|workspace|deployment)
bb vars set [scope] [repo] <KEY> [opts] # Create or update a pipeline variable
bb vars delete [scope] [repo] <KEY> # Delete a pipeline variable (destructive)bb environments lists a repo's deployment environments (the named targets a pipeline deploys to: Test / Staging / Production). bb environment-create <name> [--type Test|Staging|Production] adds one (default type Test); bb environment-delete <name> removes it by name. Each environment carries its own deployment variables, managed via bb vars [set] --deployment <env>. Create and delete need admin:pipeline:bitbucket scope.
bb projects lists a workspace's projects (KEY and NAME). The KEY is what --project expects on bb repo-create and bb repo-update. The workspace defaults to the resolved one (-w / git origin / BB_WORKSPACE); pass an explicit [workspace] to list another's. Needs read:project:bitbucket scope. See Required Bitbucket Permissions.
bb projects # projects in the resolved workspace
bb projects acme # projects in workspace "acme"bb repo-create defaults to a private repo so a forgotten flag never publishes one. Flags: --public / --private, --project KEY (required on workspaces that use projects), --description TEXT.
bb repo-create widget-service # private, default project
bb repo-create widget-service --project WID # private, in project WID
bb repo-create docs-site --public --description "Docs" # publicbb repo-update changes an existing repo's settings. The dominant use is moving a repo between projects (bb repo-create takes a project but nothing else could change it afterward). At least one of --project KEY / --description TEXT is required; [repo] accepts the same shapes as every other repo command (bare slug, ws/slug, or omitted to auto-detect from the git origin).
bb repo-update widget-service --project WID # move into project WID
bb repo-update acme/widget-service --description "..." # change description
bb repo-update --project WID # current checkout, move projectBoth bb repo-create and bb repo-update need admin:repository:bitbucket scope on the token. A read/write-only token must be rotated to add it (adding a scope does not apply to an already-issued token). See Required Bitbucket Permissions.
bb vars, bb vars set, and bb vars delete operate at three scopes, selected by a flag (default is repo):
- repo (default): no flag.
- workspace:
--workspace(no repo argument; variables are shared across the workspace). - deployment-environment:
--deployment <env>.<env>is the environment NAME or slug (for exampleDevelopmentorproduction), which the command resolves to its environment UUID by listing the repo's environments first. An unknown name fails with the list of available environments and writes nothing.
The scope endpoints are pipelines_config (repo, underscore), pipelines-config (workspace, hyphen), and deployments_config/environments/{uuid} (deployment); the hyphen-vs-underscore difference is a Bitbucket API quirk, handled for you.
bb vars set creates the variable if its key is new at that scope, or updates the existing one. Provide the value via exactly one of --value, --value-file, or --value-env. For secrets prefer --value-file or --value-env so the secret never appears in argv / the process list / shell history, and pass --secured so Bitbucket masks it. The command never echoes a value back, at any scope.
# Repo scope (default)
bb vars set widget-service AWS_REGION --value us-east-1 # non-secret
bb vars set widget-service AWS_SECRET --secured --value-file ./secret.txt
bb vars set widget-service AWS_KEY --secured --value-env AWS_KEY # read from env
# Workspace scope (shared across the workspace; no repo argument)
bb vars --workspace
bb vars set --workspace DOCKERHUB_TOKEN --secured --value-env DOCKERHUB_TOKEN
# Deployment-environment scope (env name resolves to its UUID)
bb vars --deployment Production widget-service
bb vars set --deployment Production widget-service DB_URL --secured --value-file ./db_url.txtbb vars delete <KEY> removes a variable by key at the chosen scope (it resolves the key to its UUID first, walking all pages). A key that does not exist at the scope fails with a clean not-found error and issues no delete. This is destructive (a secured value can't be recovered after deletion), so confirm the key and scope before running it.
bb vars delete widget-service AWS_ACCESS_KEY_ID # repo scope
bb vars delete --workspace DOCKERHUB_TOKEN # workspace scope
bb vars delete --deployment Production widget-service DB_URL # deployment scopeAll three scopes, for bb vars, bb vars set, and bb vars delete, need admin:pipeline:bitbucket scope on the token (write:pipeline:bitbucket alone is not enough). A read/write-only token must be rotated to add it. See Required Bitbucket Permissions.
bb open [repo] [section] # Open in browser (pr|pipelines|branches|settings|commits)
bb help # Show help-w, --workspace <name> # Override workspace for this commandWhen inside a git repository with a Bitbucket remote, the [repo] argument is optional — both the repo slug AND the workspace are auto-detected from the origin remote URL. This is what lets you cd between repos in different workspaces and have commands target the right one without a -w flag. To override, pass -w <workspace>, a workspace/slug argument, or set BB_WORKSPACE as a default (see How the workspace is resolved).
# Watch the latest pipeline on current repo
bb watch
# List open PRs
bb prs
# Create a PR from current branch to main
bb pr-create "Add new feature"
# Trigger a custom pipeline with variables
bb trigger my-repo main manual-deploy-prod LAMBDA_NAMES=mci
# View pipeline logs for step 1
bb logs my-repo 42 1
# Open repo settings in browser
bb open my-repo settingsA Python Model Context Protocol server (mcp_server.py) ships as a peer to the bb bash script. Both implement the same Bitbucket Cloud REST contract independently — the MCP server does not shell out to bb; it speaks HTTP directly via Python stdlib (no requests etc.). Any Claude Code session — or any other MCP-aware client — can drive Bitbucket Cloud as native tools without invoking the CLI.
41 tools covering pipelines, pull requests, workspaces, projects, repos, branches, commits, pipeline config + variables, deployment environments, and git-context helpers:
| Category | Tools |
|---|---|
| Pipelines (read) | pipelines_list, pipeline_show, pipeline_steps, pipeline_logs, pipelines_config_show |
| Pipelines (write) | pipeline_trigger, pipeline_stop, pipelines_config_set (enable/disable; needs admin:pipeline:bitbucket) |
| Pull requests (read) | prs_list, pr_show, pr_activity, pr_diff, pr_comments_list |
| Pull requests (write) | pr_create, pr_approve, pr_unapprove, pr_merge, pr_decline, pr_comment_add |
| Workspaces / projects | workspaces_list (needs read:workspace:bitbucket scope), projects_list (needs read:project:bitbucket scope) — see Required Bitbucket Permissions |
| Repos / metadata | repos_list, repo_show, repo_create, repo_update, branches_list, branch_show, commits_list, vars_list, vars_set, vars_delete, downloads_list |
| Deployment environments | environments_list, environment_create, environment_delete (create/delete need admin:pipeline:bitbucket) |
| Git context | git_current_branch, git_status, git_remote_repo, git_recent_commits, git_uncommitted_changes |
| Meta | whoami (see note below) |
Note on whoami: resolves config + git context + a workspace-reachability probe (single low-cost GET /repositories/{workspace}?pagelen=1, 10 s timeout). Never echoes BB_TOKEN. The probe requires repository:read scope — a workspace-scoped token granting only pipelines:read or pullrequest:read will report auth.ok=False even though pipeline/PR tools still work, so treat the probe as a scope hint rather than a global credential verdict.
Every tool that takes a repo argument supports auto-detection (omit repo to resolve from the current git checkout's origin remote — or from BB_DEFAULT_REPO_PATH if set; see Environment overrides below) and workspace override (workspace/repo shape).
- Python 3.10+ available on PATH (the bash CLI doesn't need Python — only the MCP server does).
- The same
~/.config/bb/config(orBB_USER/BB_TOKEN/BB_WORKSPACEenv vars) as the CLI — see Configuration above.
# 1. Make sure bb itself is installed and configured (see Configuration above).
# 2. Register the MCP server with Claude Code (user scope = all sessions on this machine):
claude mcp add --scope user bitbucket \
-- python3 /absolute/path/to/bitbucket-cli/mcp_server.py # ← replace with your clone path
# `python3` is intentionally bare — `claude mcp add` inherits PATH, so a
# Homebrew or pyenv Python 3.10+ resolves naturally. Do NOT hardcode
# /usr/bin/python3 on macOS: Apple's bundled Python at that path is 3.9,
# which is below the MCP server's 3.10 minimum. The `--` separator before
# `python3` keeps the command robust if you later add `--env` flags
# (see "Multiple workspaces" below).
# 3. On first invocation, the server self-bootstraps a durable venv at
# $XDG_DATA_HOME/bitbucket-cli/venv (default: ~/.local/share/bitbucket-cli/venv)
# and installs the `mcp` package into it. Subsequent launches reuse the venv.
#
# To force a clean rebuild:
# rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/bitbucket-cli/venv"
# and relaunch the MCP server.
# 4. Verify the connection (handshake only — does NOT validate credentials):
claude mcp list
# Should show: bitbucket: ... - ✓ Connected
#
# First invocation may briefly show "✗ Failed to connect" while the venv
# bootstraps (pip-installs `mcp`, 5-30 s depending on network). Retry once.
# 5. Verify credentials in a Claude Code session by asking it to run the
# `whoami` tool — `Connected` above only confirms the stdio handshake;
# `whoami` confirms BB_USER/BB_TOKEN/BB_WORKSPACE actually resolve AND
# the token reaches your configured workspace.Multiple workspaces: to register more than one server (e.g. bitbucket-work and bitbucket-personal pointing at different workspaces), use --env flags per registration so each server entry carries its own credentials:
claude mcp add --scope user bitbucket-work \
--env BB_USER=you@work.com \
--env BB_TOKEN=... \
--env BB_WORKSPACE=acme \
-- python3 /absolute/path/to/bitbucket-cli/mcp_server.py # ← replace with your clone pathmcp_server.py is a stdio MCP server, so any client that speaks MCP-over-stdio can use it. The command is python3 /absolute/path/to/bitbucket-cli/mcp_server.py — same Python-version constraint as above. Credentials come from ~/.config/bb/config or environment variables; clients that strip HOME from the subprocess environment need to pass BB_USER / BB_TOKEN / BB_WORKSPACE explicitly instead.
| Variable | Purpose |
|---|---|
BB_API_BASE |
Override the Bitbucket REST base URL (default https://api.bitbucket.org/2.0). Useful for a test / proxied / staging mirror. |
BB_DEFAULT_REPO_PATH |
Default working directory for repo auto-detection (when a Bitbucket tool is called with repo="") AND for the git_* tools' default path="" resolution. Defaults to the MCP server's launch cwd. |
XDG_DATA_HOME |
Standard XDG override for the data root. The venv lives at $XDG_DATA_HOME/bitbucket-cli/venv (default ~/.local/share/bitbucket-cli/venv). |
The MCP server exposes the tools; the bundled agent (agents/bitbucket.md in this repo) is the behavioral layer that makes a Claude Code session use those tools intelligently — propose-first protocol for destructive ops (pr_merge, pr_decline, pipeline_stop, pr_unapprove), resolve-git-context-first before any Bitbucket call, show-diffs-before-merge discipline, bash/Python parity rule for delegated CLI maintenance, and the per-workspace conventions block for tracking each workspace's defaults.
The bundled agents/bitbucket.md is a deliberately-generic template — it ships with placeholder examples (acme/widget-service, fictional reviewers, generic custom-pipeline patterns like deploy-prod) and an explicitly-blank "Per-workspace conventions" section at the bottom. After copying it to ~/.claude/agents/bitbucket.md, personalize your local copy with your default workspace, required reviewers, custom pipeline patterns, branch naming conventions, and any other non-generic context. Anything you contribute back to this repo via PR should be re-genericized first — real workspace slugs, real ticket titles, real reviewer handles, and project-specific custom-pipeline patterns belong only in your personal ~/.claude/agents/ copy, never in the upstream-tracked version.
The agent is a single Markdown file with frontmatter. To install:
# 1. Copy the agent definition into user-scope agents.
mkdir -p ~/.claude/agents
cp agents/bitbucket.md ~/.claude/agents/bitbucket.md
# 2. Populate the "Per-workspace conventions" section using bb itself —
# don't type defaults from memory, let the CLI discover them:
# bb workspaces # which workspaces you belong to
# bb -w <ws> repos # what's in each
# bb repo <ws>/<repo> # → Main branch (verify PR base; GitFlow repos target develop)
# bb pipelines <ws>/<repo> # → TRIGGER column = custom pipelines
# bb branches <ws>/<repo> # → branch-naming convention
# bb vars <ws>/<repo> # → SECURED=true = sensitive vars to mask
# Add one block per workspace (the template at the bottom of the agent
# file shows the shape). The bundled agent can run this survey for you.
# 3. Newly-started Claude Code sessions pick up the agent automatically.
# Existing sessions need a restart. In any new session you can then
# delegate to it:
#
# "Use the bitbucket agent to merge PR 42"
# "Have the bitbucket agent watch pipeline 142"
# "Ask the bitbucket agent to trigger a deploy-prod run on main"The agent description tells Claude Code's orchestrator when to delegate to it automatically (e.g. when the user mentions Bitbucket pipeline / PR / repo operations). You don't have to invoke it by name.
What the agent enforces on top of the raw tools:
The MCP tools already do per-call auto-detection on their own (source-branch auto-detect on pr_create, repo auto-detect on every Bitbucket tool given repo="") — the agent doesn't re-implement those. What the agent adds:
| Behavior | Raw MCP tools | With bundled bitbucket subagent |
|---|---|---|
Destructive ops (pr_merge, pr_decline, pipeline_stop, pr_unapprove) |
Fired immediately when invoked | Propose-first: show diff / activity / current state, confirm with user, then act |
| Pipeline failure investigation | Caller must navigate pipeline_show → pipeline_steps → pipeline_logs manually |
Triages in that order, surfaces the relevant log tail (last ~50 lines around the failure) instead of dumping the whole stream |
| Avoiding redundant probes | Caller may re-fetch git_current_branch / git_remote_repo per call even when the tool would auto-detect |
Lets tool-level auto-detect carry the call (passes repo="" and omits source_branch= instead of pre-fetching git context just to echo it back) |
bb-CLI maintenance (delegated) |
Re-discovers the parity rule, naming conventions, redaction patterns per session | Owns the design → implement → test → docs → PR cycle with the rules already baked in |
| Per-workspace conventions | Re-discovered each session | Reads (or bb-discovers and proposes) the agent file's "Per-workspace conventions" block for the active workspace before any write op |
BB_TOKENis never echoed (whoami, error envelopes, log lines).- URL credentials (
https://user:token@host/...) and signed-URL query parameters (AWS / Azure / GCP / bearer / access_token / api_key) are stripped from every error message. - Cross-host
Authorizationheaders are stripped on redirect so the Bitbucket Basic header never reaches S3 when fetching pipeline logs. - Pipeline variable values are masked as
KEY=***when echoed back.
The agent file is genuinely portable — strip the example "Per-workspace conventions" section and you have a clean template that works for any Bitbucket Cloud workspace.
MIT License - see LICENSE for details.
