# bb — Bitbucket Cloud CLI
[](https://github.com/biokraft/bbcloud/actions/workflows/ci.yml)
[](https://codecov.io/gh/biokraft/bbcloud)
[](https://crates.io/crates/bbcloud)
[](https://github.com/biokraft/bbcloud/releases/latest)
[](https://github.com/biokraft/bbcloud)
[](LICENSE)
[](https://github.com/rust-secure-code/safety-dance)
Open pull requests, read every comment, and write replies — without leaving the shell or opening a
browser tab.
One binary, no runtime to install. Your API token lives in your OS keyring and is never printed,
never written to disk, and never sent anywhere except `api.bitbucket.org` over TLS. `bb update` is
the one command that talks to another host — it queries the GitHub Releases API without sending any
credentials.
```
$ bb pr list --build
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ID TITLE STATE BUILD SOURCE → TARGET AUTHOR REVIEWERS │
╞══════════════════════════════════════════════════════════════════════════════════════════════════════════╡
│ 42 Cache session lookups Open SUCCESSFUL feat/cache → main dev Dana ✓ │
│ 41 Fix token refresh window Draft FAILED fix/token-clock → main dev Ash · │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────┘
```
Across every repository you work in, not just this one:
```
$ bb pr mine
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ REPO ID TITLE STATE ROLE MINE UPDATED │
╞════════════════════════════════════════════════════════════════════════════════════════════════╡
│ acme/api 225 Validate mapi responses OPEN reviewer pending 4 hours ago │
│ acme/web 206 Add guardrail hooks OPEN reviewer pending 5 days ago │
│ acme/api 198 Cache session lookups OPEN author - 2 days ago │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
```
## Install
```bash
brew install biokraft/tap/bb
```
Recommended: updates via `brew update && brew upgrade`, no Rust toolchain needed. (`brew upgrade`
alone does not refresh the tap, so a freshly published version can stay invisible.)
### Alternatives
| Install script | `curl -fsSL https://raw.githubusercontent.com/biokraft/bbcloud/main/install.sh \| sh` | Nothing — detects platform, verifies checksum, installs to `~/.local/bin` |
| Prebuilt binary | Download from the [latest release](https://github.com/biokraft/bbcloud/releases/latest) | Manual `PATH` setup; verify against the matching `.sha256` |
| Nix | `nix profile install github:biokraft/bbcloud` | Nix with flakes enabled |
| `cargo binstall` | `cargo binstall bbcloud` | `cargo-binstall`, no compiler |
| `cargo install` | `cargo install bbcloud --locked` | Rust 1.88+ (a clone pins 1.97 via `rust-toolchain.toml`) |
Supported targets: `aarch64-apple-darwin`, `x86_64-apple-darwin`, `x86_64-unknown-linux-gnu`,
`aarch64-unknown-linux-gnu`.
The cargo routes install `bb` into `~/.cargo/bin` — add that to your `PATH` if the command isn't
found afterwards.
## Agent skills
This repository ships two [Agent Skills](.agents/skills/) — the portable `SKILL.md` format that
Claude Code, Codex, Cursor and OpenCode all read. `bitbucket-cloud` teaches the agent to review
pull requests through `bb` rather than ask you to open a browser: the `--json` contract, the
comment and reply flags, the exit codes, and what to do when a scope is missing. It also tells the
agent to answer comment threads and report them, and to leave the resolve decision to you.
`bbc-daily-brief` builds a ranked morning brief on top of `bb pr mine`, and is invoked only when you
explicitly ask for one.
Install both into a project:
```bash
bb skill install
```
`bb skill install` writes both skills — `bitbucket-cloud` and `bbc-daily-brief`. Pass
`--skill <name>` to narrow install (or uninstall) to just one of them. The skill text ships inside
the `bb` binary, so this needs no network and no credentials. It detects which agents the project
uses — `.claude/` means Claude Code, any of `.agents/`, `.cursor/`, `.opencode/` means the portable
location — and defaults to `.agents/skills/` if it finds none. Pass `--agent agents|claude|all` to
pick explicitly, or `--global` to install under your home directory instead, so every project
picks it up.
| [Codex](https://learn.chatgpt.com/docs/build-skills) | `.agents/skills/`, `~/.agents/skills/` | none |
| [Cursor](https://cursor.com/docs/skills) | `.agents/skills/`, `.cursor/skills/`, and the `~/` equivalents | none |
| [OpenCode](https://opencode.ai/docs/skills/) | `.opencode/skills/`, `.claude/skills/`, `.agents/skills/` | none |
| [Claude Code](https://code.claude.com/docs/en/skills) | `.claude/skills/`, `~/.claude/skills/` | none — `bb skill install` writes a symlink there |
Run `bb skill status` to see where each copy is installed and whether it is current, stale or
edited locally. Installed copies keep themselves current: when the running binary is newer than the
copy that wrote them — after `brew upgrade`, `cargo install` or `bb update` — the next `bb` command
refreshes them, so the instructions an agent reads never describe an older CLI. A locally edited
file is never overwritten; it is reported and left alone. Set `BB_SKILL_NO_AUTO_REFRESH=1` to manage
the files entirely by hand.
Run `bb skill uninstall` to remove every tracked copy (or `--global` to remove the ones under your
home directory instead). A locally edited copy is left alone unless you pass `--force`, same rule
as `install`.
Each agent loads the skill by itself when a task touches Bitbucket. To force it, name it:
*"use the bitbucket-cloud skill"*. If your tool reads no skills at all, paste the file into
`AGENTS.md` or `CLAUDE.md` — it is plain Markdown.
## Authenticate
Atlassian **removed Bitbucket Cloud app passwords on 2026-07-28.** `bb` uses an Atlassian API token,
sent as HTTP Basic auth with your account email as the username.
1. Create a token at <https://id.atlassian.com/manage-profile/security/api-tokens>, selecting the
scopes below.
2. Run `bb auth login` and paste it — the input is masked and never echoed.
```bash
bb auth login # prompts, verifies the token, then stores it in the OS keyring
bb auth logout # removes the stored credentials
bb auth status # shows the account; the token is always redacted to ****last4
```
### Token scopes
Grant the least you need. For the pull request workflow — listing, reading and commenting — four
scopes are enough:
| `read:user:bitbucket` | **mandatory.** `bb auth login` verifies the token against `/user`, so login fails without it |
| `read:pullrequest:bitbucket` | `pr list`, `pr view`, `pr diff`, `pr files`, `pr commits`, `pr mine` |
| `write:pullrequest:bitbucket` | `pr create`, `pr comment`, `pr resolve`, `pr unresolve`, `pr request-changes` |
| `read:repository:bitbucket` | `branch list`, the default-reviewer lookup `pr create` does, and the workspace/repository scan `pr mine` does |
One gotcha worth knowing: `write:pullrequest:bitbucket` does **not** imply
`read:repository:bitbucket`, so `pr create` needs both.
### CI and headless machines
There is no keyring on a CI runner, and on Linux the keyring backend is secret-service, which is
absent on servers. Set the credentials in the environment instead — they are checked **before** the
keyring, so this also works as a local override:
```bash
export BB_EMAIL='you@example.com'
export BB_TOKEN='...'
bb pr list --json
```
### Check it works
```bash
bb --version
bb auth status # exits 2 until you log in
cd any-bitbucket-repo && bb pr list
```
## Usage
`bb --help` lists every command, and `bb <command> --help` documents its flags. The shape is
`bb <noun> <verb>`:
```bash
bb pr list # open PRs, with state and per-reviewer decisions
bb pr list --needs-my-review # only PRs waiting on your review
bb pr view 42 --unresolved # the PR plus comment threads still needing action
bb pr build 42 # one PR's checks: key, name, state, url
bb pr reviewers add 42 dana # tag a reviewer; comma-separate for several
bb pr create main --title "Add caching" # source branch inferred from your checkout
bb pr comment 42 -f src/auth.rs -l 88 -b "off by one"
bb pr resolve 42 998877 # confirms first, then closes the thread
bb pr mine --role reviewer --build # your PRs across every repo you can see
bb branch list --user alice
bb update # check for a newer release and update
```
`bb pr list` also takes `--reviewer <name>`, `--author <name|@me>`, `--review-state
`bb pr mine` is the one command that is not repository-scoped. There is no Bitbucket api left that
lists which workspaces you belong to, so the workspace(s) to scan are resolved in this order:
`--workspace <slug>[,<slug>...]` (comma-separated, highest precedence), then the `BB_WORKSPACE`
env var (same syntax), then the workspace of the git remote in the current checkout. If none of
those apply — no flag, no env var, and not run inside a Bitbucket checkout — the command errors
instead of silently scanning nothing.
It also takes `--role author|reviewer|all`, `--state`, `--repo-limit <n>` (the most recently
updated repositories to scan per workspace, default 30 — a recency window, not the whole
workspace: a workspace with hundreds of repositories is only ever sampled, not fully covered), and
`--build`. A workspace the token cannot read is reported in a `partial` list rather than failing
the whole command.
`bb update` compares your version against the latest GitHub release. If Homebrew or cargo installed
`bb`, it prints the right upgrade command for that package manager instead of overwriting a file they
manage. For a standalone binary it verifies the download's checksum and replaces itself atomically.
Two things worth knowing that `--help` won't tell you:
**Everything speaks JSON.** Add `--json` to any command and pipe it to `jq` rather than parsing the
tables, whose layout is not a contract. Scripts and agents should default to it.
```bash
**`bb pr resolve` asks first.** It shows the thread it will close — the file and line, who raised
it, what it says — and waits for a yes. Without a terminal it fails and names `--yes`, so nothing
resolves in a script or under an agent unless the command line approves it. `bb pr unresolve`
reopens a thread, and needs no confirmation.
Shell completions make the rest discoverable:
```bash
bb completions zsh > ~/.zfunc/_bb # also bash, fish, powershell, elvish
```
## Reference
| `--json` | machine-readable output, on every command |
| `-R, --repo` | act on `workspace/repo` instead of the current git remote |
| `BB_REPO` | default repository |
| `BB_WORKSPACE` | workspace(s) `bb pr mine` scans, comma-separated, when `--workspace` is not given |
| `BB_EMAIL`, `BB_TOKEN` | credentials for CI and other non-interactive use |
| `BB_API_BASE` | override the API base URL (testing) |
| `BB_UPDATE_API_BASE` | override the release-lookup API base URL for `bb update` (testing) |
| `BB_SKILL_NO_AUTO_REFRESH` | set to `1` to stop `bb` refreshing installed skill files when the binary version changes |
| `NO_COLOR` | disable colour and spinners |
| 0 | success |
| 1 | general error |
| 2 | not authenticated |
| 3 | not found |
## Platform support
macOS (arm64, x86_64) and Linux (x86_64, aarch64), both covered by CI. Windows is not supported.
## Contributing
Issues and pull requests are welcome. Before opening a PR, run `cargo fmt --all --check`,
`cargo clippy --all-targets -- -D warnings`, and `cargo test` — CI enforces all three.
`rust-toolchain.toml` pins the exact toolchain used for those checks (currently 1.97), which rustup
auto-installs on first use but which a contributor building offline needs to already have.
Security reports: please use GitHub's
[private vulnerability reporting](https://github.com/biokraft/bbcloud/security/advisories/new)
rather than a public issue.
## License
MIT — see [LICENSE](LICENSE). This project is an independent Rust rewrite of the MIT-licensed PHP
`bb-cli`; see [NOTICE](NOTICE) for attribution.