Skip to content

Repository files navigation

bbx

solrevdev.bbx

gh for Bitbucket Cloud. A .NET global tool that puts the Bitbucket Cloud API v2 on your command line, with JSON on stdout so scripts and LLMs can read it.

NuGet NuGet downloads .NET 10 MIT


Contents

Why bbx

Bitbucket has no first-party CLI. bbx fills that gap the way gh does for GitHub:

  • JSON on stdout, diagnostics on stderr. Pipe straight into jq without filtering noise.
  • Exit codes that mean something. 0 on success, 1 on any failure, so set -e and if ! work.
  • One credential. An Atlassian API token, stored 0600, with scopes you choose.
  • Wide coverage. Repos, pull requests, branches, tags, commits, source files, downloads, pipelines, snippets, workspaces, projects and users.
  • Errors you can act on. A missing scope tells you which scope and where to re-issue the token.

Install

dotnet tool install -g solrevdev.bbx

Upgrade or remove:

dotnet tool update -g solrevdev.bbx
dotnet tool uninstall -g solrevdev.bbx

Requires the .NET 10 runtime or SDK. If bbx isn't found afterwards, add the tools directory to your PATH:

export PATH="$PATH:$HOME/.dotnet/tools"

Authenticate

bbx uses Atlassian API tokens. Create one at https://id.atlassian.com/manage-profile/security/api-tokens, then:

bbx auth login

It prompts for your Atlassian account email and the token, checks them against /2.0/user, and saves them to ~/.config/bbx/config.json with mode 0600.

Set a default workspace so you can drop -w from every command:

bbx auth set-workspace myworkspace
bbx auth status

Scopes

The Atlassian page offers two buttons: Create API token and Create API token with scopes. Use the scoped one. A token from the plain button carries no scopes, so bbx cannot tell you which one is missing when a call fails.

Pick scopes when you create the token. Grant the least you need:

Doing this Needs
Read repos, PRs, commits, pipelines read:* for the areas you use
Create PRs, push files, comment write on repository / pullrequest
Deploy keys, branch restrictions, branching-model settings, repo create/delete admin:repository
Pipeline variables and schedules admin:pipeline

A token missing a scope gets a 403 that names the gap:

$ bbx repo deploy-keys list -w myworkspace -r myrepo
Error: Your credentials lack one or more required privilege scopes. (HTTP 403 Forbidden)
Missing token scopes: admin:repository:bitbucket. Re-issue your token with those
scopes at https://id.atlassian.com/manage-profile/security/api-tokens

In CI

Write the config file directly so nothing prompts:

- name: Configure bbx
  run: |
    mkdir -p ~/.config/bbx
    cat > ~/.config/bbx/config.json <<'JSON'
    { "AuthMethod": "api-token",
      "Username": "${{ secrets.BITBUCKET_EMAIL }}",
      "ApiToken": "${{ secrets.BITBUCKET_API_TOKEN }}",
      "DefaultWorkspace": "myworkspace" }
    JSON
    chmod 600 ~/.config/bbx/config.json

Set BBX_NO_INTERACTIVE=1 to be certain bbx never tries to prompt. Without a TTY it won't anyway, but the variable makes the intent explicit.

Quick start

bbx repo list -w myworkspace --limit 10
bbx pr list -w myworkspace -r myrepo --state OPEN
bbx pr view 42 -w myworkspace -r myrepo
bbx pr diff 42 -w myworkspace -r myrepo
bbx pipeline list -w myworkspace -r myrepo --limit 5

With a default workspace set, -w is optional:

bbx pr list -r myrepo --state OPEN

Output contract

Three rules, relied on by every example below.

1. JSON on stdout, everything else on stderr.

bbx pr list -r myrepo --state OPEN | jq -r '.pull_requests[].title'

Prompts, warnings and errors go to stderr, so the pipe above stays clean.

2. Exit 0 on success, 1 on failure. That covers a bad argument, missing credentials, and any API error.

if ! prs=$(bbx pr list -r myrepo --state OPEN); then
  echo "lookup failed" >&2
  exit 1
fi

3. Pretty-printed by default, single-line on request. Use --json-compact or BBX_JSON_COMPACT=1 for one object per line:

bbx repo list -w myworkspace --json-compact

A few commands emit raw text rather than JSON, because that is the useful form: pr diff, pr patch, commit diff, commit patch, src cat.

Command reference

Every group takes -w/--workspace and, where relevant, -r/--repo. Destructive commands prompt unless you pass --yes.

auth: credentials
bbx auth login                    # prompt for email + API token
bbx auth login --email me@x.com   # prompt for just the token
bbx auth status                   # who am I, which workspace
bbx auth token                    # print email:token (for curl -u)
bbx auth set-workspace myws       # default for -w
bbx auth logout                   # clear stored credentials
bbx version                       # print the installed bbx version
repo: repositories, hooks, deploy keys, reviewers
bbx repo list -w myws --limit 10
bbx repo view myrepo -w myws
bbx repo create myrepo -w myws --private --description "..."
bbx repo delete myrepo -w myws --yes
bbx repo fork myrepo -w myws --name myfork
bbx repo clone myrepo -w myws            # prints the clone URL
bbx repo permissions myrepo -w myws
bbx repo watchers -w myws -r myrepo
bbx repo forks list -w myws -r myrepo

bbx repo update myrepo -w myws --description "..." --main-branch trunk
bbx repo file-conflicts 'feat/x..main' -w myws -r myrepo
bbx repo override-settings view|update -w myws -r myrepo

bbx repo hooks list|view|create|update|delete -w myws -r myrepo
bbx repo deploy-keys list|view|add|update|delete -w myws -r myrepo
bbx repo default-reviewers list|view|add|remove|effective -w myws -r myrepo
bbx repo branching-model view|settings|update|effective -w myws -r myrepo
bbx repo access groups list|view|set|remove -w myws -r myrepo
bbx repo access users view|set|remove -w myws -r myrepo

repo update changes only the fields you name, like pr update. Bitbucket rejects a --language it does not recognise. There is no repo deploy-keys update: Bitbucket refuses to change a key's contents and refuses a body without them, so delete and re-add instead.

pr: pull requests, tasks, reviews
bbx pr list -w myws -r myrepo --state OPEN --limit 25
bbx pr view 42 -w myws -r myrepo
bbx pr create --title "Fix" --source feat/x --dest main -w myws -r myrepo
bbx pr update 42 --title "Better title" -w myws -r myrepo
bbx pr update 42 --dest release/next -w myws -r myrepo    # retarget
bbx pr merge 42 --strategy squash --yes -w myws -r myrepo
bbx pr decline 42 --reason "superseded" -w myws -r myrepo

bbx pr diff 42 -w myws -r myrepo         # raw text
bbx pr patch 42 -w myws -r myrepo        # raw text
bbx pr commits 42 -w myws -r myrepo
bbx pr activity 42 -w myws -r myrepo
bbx pr statuses 42 -w myws -r myrepo

bbx pr diffstat 42 -w myws -r myrepo      # per-file line counts
bbx pr conflicts 42 -w myws -r myrepo
bbx pr merge-status 42 --task-id <id> -w myws -r myrepo
bbx pr activity -w myws -r myrepo         # no ID: the whole repository

bbx pr comment 42 --body "LGTM" -w myws -r myrepo
bbx pr comments 42 -w myws -r myrepo
bbx pr comment-view|comment-update|comment-delete 42 --comment-id <id> -w myws -r myrepo
bbx pr comment-resolve|comment-unresolve 42 --comment-id <id> -w myws -r myrepo
bbx pr approve|unapprove 42 -w myws -r myrepo
bbx pr request-changes|unrequest-changes 42 -w myws -r myrepo
bbx pr tasks list|view|add|update|complete|delete 42 -w myws -r myrepo

Merge strategies: merge_commit (default), squash, fast_forward. merge, fast-forward and ff are accepted as aliases.

pr update changes only the fields you name and works on open pull requests only. --body "" clears the description. --close-source-branch and --no-close-source-branch need another real change in the same call, because Bitbucket silently drops the setting otherwise.

branch: branches, restrictions, tags
bbx branch list -w myws -r myrepo --limit 25
bbx branch view main -w myws -r myrepo
bbx branch create feat/x --target main -w myws -r myrepo
bbx branch delete feat/x --yes -w myws -r myrepo

bbx branch refs -w myws -r myrepo         # branches and tags together

bbx branch restrictions list|view -w myws -r myrepo
bbx branch restrictions add --kind push --pattern main -w myws -r myrepo
bbx branch restrictions update 12345 --pattern 'release/*' -w myws -r myrepo
bbx branch restrictions delete 12345 --yes -w myws -r myrepo

bbx branch tag list|view|create|delete -w myws -r myrepo
commit: history, diffs, build statuses
bbx commit list -w myws -r myrepo --limit 25
bbx commit view <hash> -w myws -r myrepo
bbx commit diff|patch|diffstat <hash> -w myws -r myrepo
bbx commit comments|statuses|pullrequests <hash> -w myws -r myrepo
bbx commit approve|unapprove <hash> -w myws -r myrepo
bbx commit filehistory main path/to/file -w myws -r myrepo
bbx commit merge-base 'feat/x..main' -w myws -r myrepo

bbx commit list --include feat/x --exclude main -w myws -r myrepo

bbx commit comment <hash> --body "..." --path src/a.cs --line 3 -w myws -r myrepo
bbx commit comment-view|comment-update|comment-delete <hash> --comment-id <id> -w myws -r myrepo

bbx commit status create <hash> --key ci --state SUCCESSFUL --url https://ci/1 -w myws -r myrepo
bbx commit status update <hash> --key ci --state FAILED --url https://ci/1 -w myws -r myrepo
bbx commit status view <hash> --key ci -w myws -r myrepo

--include and --exclude walk a commit range. Bitbucket takes them in a POST body only, so passing either switches the verb.

src: browse and write files
bbx src ls -w myws -r myrepo             # root of the main branch
bbx src ls --ref main -w myws -r myrepo
bbx src ls src/ --ref main -w myws -r myrepo
bbx src cat --ref main README.md -w myws -r myrepo
bbx src write --branch main --message "docs: update" --file ./local.md=README.md -w myws -r myrepo

src write commits directly. Repeat --file for several files in one commit.

pipeline: runs, logs, variables, schedules
bbx pipeline list -w myws -r myrepo --limit 10
bbx pipeline view '{uuid}' -w myws -r myrepo
bbx pipeline steps '{uuid}' -w myws -r myrepo
bbx pipeline logs '{pipeline-uuid}' '{step-uuid}' -w myws -r myrepo
bbx pipeline trigger --branch main -w myws -r myrepo
bbx pipeline stop '{uuid}' --yes -w myws -r myrepo

bbx pipeline step '{pipeline-uuid}' '{step-uuid}' -w myws -r myrepo
bbx pipeline logs '{pipeline}' '{step}' --log-uuid '{log}' -w myws -r myrepo

bbx pipeline config view|update|build-number -w myws -r myrepo
bbx pipeline variables list|view|add|update|delete -w myws -r myrepo
bbx pipeline schedules list|view|create|update|delete|executions -w myws -r myrepo
bbx pipeline caches list|clear|content-uri -w myws -r myrepo
bbx pipeline caches clear --name node --yes -w myws -r myrepo
bbx pipeline ssh key-pair view|set|delete -w myws -r myrepo
bbx pipeline ssh known-hosts list|view|add|update|delete -w myws -r myrepo

bbx pipeline deployments list|view|create|delete|changes -w myws -r myrepo
bbx pipeline deployments variables list|add|update|delete -e '{env}' -w myws -r myrepo
bbx pipeline deploys list|view -w myws -r myrepo

bbx pipeline reports list|view|update|delete <hash> -w myws -r myrepo
bbx pipeline reports annotations|annotations-create <hash> <report-id> -w myws -r myrepo
bbx pipeline reports annotation-view|annotation-update|annotation-delete <hash> <report-id> <ann-id> -w myws -r myrepo
bbx pipeline test-reports '{pipeline}' '{step}' -w myws -r myrepo
bbx pipeline test-cases '{pipeline}' '{step}' -w myws -r myrepo
bbx pipeline test-case-reasons '{pipeline}' '{step}' '{test-case}' -w myws -r myrepo

UUIDs include the braces. Quote them so your shell doesn't expand them.

deployments manages the environments; deploys reads the records of what was released to them. deployments changes takes --name, --admin-only and --no-admin-only, and nothing else: Bitbucket refuses to change an environment's lock, rank, type or hidden flag through it. caches clear takes a cache UUID, or --name to clear every cache with that name. reports update needs --details: Bitbucket refuses a report without it whatever the docs say. pipeline config answers 404 until Pipelines has been enabled on the repository at least once. There is no pipeline oidc: only the workspace form of that path exists, and workspace pipelines oidc reaches it.

download: repository artifacts
bbx download list -w myws -r myrepo
bbx download upload --file ./build.zip -w myws -r myrepo
bbx download get build.zip --output ./build.zip -w myws -r myrepo
bbx download delete build.zip --yes -w myws -r myrepo
workspace: members, hooks, projects
bbx workspace view myws
bbx workspace members -w myws
bbx workspace member '{account-uuid}' -w myws
bbx workspace permissions -w myws
bbx workspace repo-permissions -w myws [--repo myrepo]
bbx workspace gpg-key -w myws
bbx workspace pullrequests '{account-uuid}' -w myws --state OPEN
bbx workspace hooks list|view|create|update|delete -w myws

bbx workspace pipelines variables list|view|add|update|delete -w myws
bbx workspace pipelines oidc config|keys -w myws

bbx workspace project list -w myws
bbx workspace project view KEY -w myws
bbx workspace project create --key KEY --name "Name" -w myws
bbx workspace project update KEY --description "..." -w myws
bbx workspace project delete KEY --yes -w myws
bbx workspace project default-reviewers list|view|add|remove --project-key KEY -w myws
bbx workspace project deploy-keys list|view|add|delete --project-key KEY -w myws
bbx workspace project branching-model view|settings|update --project-key KEY -w myws
bbx workspace project access groups list|view|set|remove --project-key KEY -w myws
bbx workspace project access users list|view|set|remove --project-key KEY -w myws
snippet, user, issue
bbx snippet list|view|create|update|delete -w myws
bbx snippet view|update|delete <id> --revision <rev> -w myws
bbx snippet files|watch|comments <id> -w myws
bbx snippet commits <id> -w myws
bbx snippet diff|patch <id> <revision> -w myws
bbx snippet comments <id> --update <comment-id> --content "..." -w myws

bbx user view                       # the authenticated account
bbx user emails [--email me@x.com]
bbx user workspaces                 # replaces the withdrawn workspace list
bbx user permissions workspace|workspace-repositories -w myws
bbx user gpg-keys list|view
bbx user ssh-keys list|view|add|delete

bbx issue list|view|create|update|delete -w myws -r myrepo
bbx issue comment|comments <id> -w myws -r myrepo

[!WARNING] Bitbucket Issues are being retired by Atlassian. The API is removed on 2026-08-20 and these commands go with it. See docs/bitbucket-issues-wikis-sunset.md.

Commands Bitbucket has withdrawn

Important

bbx workspace list and bbx user permissions workspaces|repositories return HTTP 410 Gone. Atlassian removed the cross-workspace discovery endpoints under CHANGE-2770. Nothing in bbx can bring them back. Name the workspace, or set one with bbx auth set-workspace.

bbx user workspaces is the account-scoped replacement for workspace list and still works.

A few endpoints refuse an API token outright, answering HTTP 403 "This resource does not support authentication using the provided token". bbx pr conflicts, bbx repo file-conflicts and the OIDC discovery commands are the ones we found. Nothing in bbx can work around it; it needs a different credential type.

Recipes

Open PRs, oldest first

bbx pr list -r myrepo --state OPEN --limit 100 \
  | jq -r '.pull_requests | sort_by(.created_on)[] | "\(.id)\t\(.title)"'

Did the last pipeline pass?

bbx pipeline list -r myrepo --limit 1 \
  | jq -r '.pipelines[0].state | "\(.name) \(.result // "")"'

Read the newest pipeline's first step log

p=$(bbx pipeline list -r myrepo --limit 1 | jq -r '.pipelines[0].uuid')
s=$(bbx pipeline steps "$p" -r myrepo | jq -r '.steps[0].uuid')
bbx pipeline logs "$p" "$s" -r myrepo | jq -r '.log'

Report a build status from CI

bbx commit status create "$COMMIT" --key ci --state INPROGRESS --url "$BUILD_URL" -r myrepo
# ... run the build ...
bbx commit status update "$COMMIT" --key ci --state SUCCESSFUL --url "$BUILD_URL" -r myrepo

Commit a generated file without cloning

bbx src write --branch main --message "chore: regenerate" --file ./out.json=data/out.json -r myrepo

Every repo in the workspace, as TSV

bbx repo list -w myws --limit 200 | jq -r '.repositories[] | [.slug, .updated_on] | @tsv'

Using bbx with an LLM

Every command answers with JSON and reports failure through its exit code, so an agent can call bbx and act on the result without scraping human prose. Point your agent at docs/llm-guide.md for command selection, argument shapes and worked examples.

Two flags matter for agents:

bbx pr list -r myrepo --json-compact   # one line per response, cheaper to read
BBX_NO_INTERACTIVE=1 bbx repo list     # never prompt; fail with a clear error

Troubleshooting

Symptom Cause and fix
Not authenticated. Run: bbx auth login No stored credential. Log in, or write the config file directly in CI.
Missing token scopes: … The token lacks a scope. Re-issue it at the API tokens page with that scope.
HTTP 410 Gone on workspace list Atlassian withdrew the endpoint (CHANGE-2770). Name the workspace instead.
Bitbucket Cloud Issues are being sunset A warning, not a failure. The Issues API goes away 2026-08-20.
Workspace and repository are required Pass -w and -r, or set a default with bbx auth set-workspace.
A UUID argument "does nothing" Quote it. {...} is brace expansion in bash and zsh.

Check what bbx thinks it is doing:

bbx auth status
bbx <group> <command> --help

Build from source

git clone <this repo> && cd solrevdev.bbx

dotnet build src/Bbx/Bbx.csproj
dotnet test tests/Bbx.Tests/Bbx.Tests.csproj

# run without installing
dotnet run --project src/Bbx/Bbx.csproj -f net10.0 -- repo list -w myws

# install your build globally
dotnet pack src/Bbx/Bbx.csproj -c Release
dotnet tool install -g --add-source ./nupkg solrevdev.bbx

Layout:

src/Bbx/
  Api/            BitbucketClient: pagination, redirects, error shaping
  Auth/           credential storage and the auth gate
  Commands/       System.CommandLine wiring only, no business logic
  Features/       one folder per verb: request + handler
  Composition/    DI container and shared JSON options
tests/Bbx.Tests/  xunit v3, fake HTTP handler, no network

Contributing

Issues and pull requests are welcome.

  • Conventional Commits for messages (feat:, fix:, docs:, refactor:, test:).
  • dotnet test must pass; new behaviour needs a test.
  • Business logic belongs in Features/, not in Commands/.

License

MIT © solrevdev

About

gh for Bitbucket Cloud. A .NET global tool for the Bitbucket Cloud API v2, with JSON output for scripts and LLM agents.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages