Skip to content

v5.0.0

Choose a tag to compare

@github-actions github-actions released this 01 Oct 22:34
· 82 commits to main since this release

v5.0.0

bb v5.0.0 works with every Bitbucket Data Center release Atlassian supports, completes what you type from your own Bitbucket, and makes its MCP server something you work with: it asks you before it merges, takes the pull request or file you hand it, and shows what it found as a view in your client.

It is a major release. Seven changes can break a script, a pipeline or an MCP configuration. They are under "Before you upgrade", each with what to change, and are the part to read first if bb runs in CI, in scripts or under an AI agent. What is deprecated keeps working until v6.0.0 and is listed at the end.

New at the command line

  • Every Bitbucket Data Center release Atlassian supports (ADR-088, #307):

    bb was built against the newest Bitbucket release and tested against that one alone. It now works with every release Atlassian supports, each tested against a real instance of it, and a release keeps working after Atlassian's support for it ends.

    An older release behaves like the newest except where it lacks something a later one added. There bb answers as the newest release would where it can, and otherwise refuses before it sends anything, naming the release that can do it:

    $ bb branch restriction create --repo PROJ/app --type no-creates --matcher-id refs/heads/main
    unsupported: a no-creates branch restriction is not supported by this Bitbucket version (9.2.1); it needs 9.4.0 or later
    

    Before, Bitbucket accepted such a request and dropped the part it did not know, so a required build meant to spare pull requests blocked every one of them. unsupported, exit 14, is a new error kind: a script that lists the kinds or exit codes it handles gains one. Bitbucket Versions lists the four places where a release differs.

  • Tab completion that knows your Bitbucket (ADR-089, #407, #397):

    Press tab after bb pr merge and bb lists the open pull requests of the repository you are in, by number and title. After bb branch delete it lists the branches, each with its latest commit message. Projects, repositories, tags, reviewers, file paths and the values a flag accepts complete the same way, read from your Bitbucket with your own credentials, in bash, zsh, fish and PowerShell.

    Homebrew and the .deb and .rpm packages set it up for bash, zsh and fish when they install bb, and Scoop sets it up for PowerShell, along with the agent skill. Anywhere else one command does it, and bb doctor says whether it is in place:

    bb completion install
  • bb pr create needs no flags in a checkout, and bb pr merge takes a strategy (ADR-102, #705):

    Standing on a pushed branch, bb pr create is enough. The source is the branch that is checked out, the target is the repository's default branch, and the title is the commit's subject when the branch holds exactly one commit. At a terminal each is offered for you to accept or change. With nobody to ask they are used as they are and named on stderr, and a branch that holds several commits still needs --title. It prints the pull request's link, which every reported pull request now carries as url.

    git push -u origin feature/refunds
    bb pr create
    bb pr merge 42 --strategy squash

    --strategy takes any strategy the repository enables, and its default applies without it. --dry-run says so first when the repository has not enabled the one asked for.

  • bb search prs takes a period, so it can answer "what did I work on" (#697):

    What it lists has not changed. Without --repo that is every pull request you are involved in across every repository, whether you wrote it, are a reviewer on it or took part in it, and --role picks one of the three. What is new is the period: --since and --until bound the listing on the created, updated or closed date that --date-field names, and --group-by week or repo arranges the text output. With --since the listing holds the whole period rather than the first 25.

    bb search prs --role author --state all --since 2026-07-20 --until 2026-09-27 --group-by week
    • --state takes merged and declined, in bb pr list too, and all and closed no longer fail across repositories.

    • A pull request reports closedDate once it is merged or declined, and the issue keys its title and source branch mention:

      {
        "data": {
          "pullRequests": [
            {
              "id": 6,
              "title": "PAY-12: retry a declined refund",
              "state": "MERGED",
              "open": false,
              "closed": true,
              "repository": { "projectKey": "PAY", "slug": "ledger" },
              "sourceRepository": { "projectKey": "PAY", "slug": "ledger" },
              "version": 2,
              "author": "Administrator",
              "authorUsername": "admin",
              "sourceBranch": "feature/refunds",
              "targetBranch": "master",
              "sourceCommit": "6b9cb2216ad56a58f976325627a2d87ad41d6a2a",
              "createdDate": 1790758330929,
              "updatedDate": 1790758331777,
              "closedDate": 1790758331777,
              "url": "https://bitbucket.example.com/projects/PAY/repos/ledger/pull-requests/6",
              "issueKeys": ["PAY-12"],
              "commentCount": 0,
              "openTaskCount": 0,
              "resolvedTaskCount": 0
            }
          ]
        },
        "meta": { "command": "search prs", "limitReached": true, "bbVersion": "..." }
      }
  • bb branch list --details prints the details. It lists what Bitbucket's branch page shows beside each branch: how far it is ahead of and behind the default branch, its last commit, its builds and its pull requests. --base measures against another branch, tag or commit, and asks for the details by itself. Both flags used to be accepted and change nothing.

    $ bb branch list --repo PAY/ledger --details
    feature/refunds  refs/heads/feature/refunds  6b9cb2216ad56a58f976325627a2d87ad41d6a2a  default=false  ahead=2 behind=1  2026-09-28 alice  pr=#42 OPEN  builds=1 successful, 1 failed
    master           refs/heads/master           0d4e1c7a9b3f52e86a1d7c40b9e2f35a6c8d1e07  default=true                     2026-09-27 bob
    

    Under --json each branch gains ahead, behind, lastCommit, builds and pullRequests, each left out when Bitbucket has nothing to report: the base has no counts, and a branch nobody built has no builds. Bitbucket names the pull request when a branch has exactly one, as only, and gives the counts alone when it has more:

    {
      "data": {
        "repository": { "projectKey": "PAY", "slug": "ledger" },
        "branches": [
          {
            "id": "refs/heads/feature/refunds",
            "displayId": "feature/refunds",
            "latestCommit": "6b9cb2216ad56a58f976325627a2d87ad41d6a2a",
            "default": false,
            "ahead": 2,
            "behind": 1,
            "lastCommit": {
              "id": "6b9cb2216ad56a58f976325627a2d87ad41d6a2a",
              "displayId": "6b9cb2216ad",
              "message": "PAY-12: retry a declined refund",
              "author": { "name": "alice", "emailAddress": "alice@example.com" },
              "authorTimestamp": 1790586000000,
              "committer": { "name": "alice", "emailAddress": "alice@example.com" },
              "committerTimestamp": 1790586000000,
              "parents": ["0d4e1c7a9b3f52e86a1d7c40b9e2f35a6c8d1e07"]
            },
            "builds": { "successful": 1, "failed": 1, "inProgress": 0, "unknown": 0, "cancelled": 0 },
            "pullRequests": {
              "open": 1,
              "merged": 0,
              "declined": 0,
              "only": { "id": 42, "title": "PAY-12: retry a declined refund", "state": "OPEN" }
            }
          }
        ]
      },
      "meta": { "command": "branch list", "limitReached": false, "bbVersion": "..." }
    }
  • --yaml (ADR-095, #606):

    Every command that takes --json takes --yaml, and prints the same document as YAML, for a pipeline that keeps its data in YAML or for reading a long answer at a terminal. --dry-run and --describe follow it too. bb --yaml branch list --repo PAY/ledger --filter develop:

    data:
      repository:
        projectKey: PAY
        slug: ledger
      branches:
        - id: refs/heads/develop
          displayId: develop
          latestCommit: f62bfb84cba2a12ef7f2437dfc8c084ac61c489d
          default: false
    meta:
      command: branch list
      limitReached: false
      bbVersion: "..."
  • Examples in every --help, and a reference page per command (#604, #701):

    The help of every command ends with examples to copy, showing the values a flag's description leaves you to guess. The command reference on the site has a page per command in place of one long page, with each flag under the command it comes from.

New in the MCP server

The server also asks you before a tool merges, or decides what merges. That changes an existing setup, so it is under "Before you upgrade".

  • Put a pull request, a diff or a file in front of the AI yourself (ADR-099, #685):

    Until now the AI only saw what it went and fetched through bb's tools, so you had to hope it found the right pull request or file. Now you can hand it Bitbucket content yourself, the way you attach a file to a message: the pull request you are reviewing, its diff or its open comments, a file on any branch, tag or commit, or a single commit. Your MCP client helps you find it, suggesting projects, repositories, pull requests, paths and branches as you type, and it lists your own open pull requests and the ones waiting on your review, so the one you want is usually a click away.

    In VS Code, for example, choose Add Context > MCP Resources, pick the diff of pull request 42 in PAYMENTS/ledger, and ask what could break. Or type /bitbucket.review_pull_request to attach a pull request with its diff and open comments and ask for a review in one step. It works the same in any MCP client, including chat apps without a terminal, and everything still goes through bb, with its token, its --project and --repo scope and its audit trail. Your client never talks to Bitbucket itself.

  • See a pull request, a list or a diff as a view in your MCP client (ADR-101, #686):

    In clients that render MCP Apps, such as Claude Desktop, VS Code and Goose, the AI can now put what it found in front of you instead of describing it: a pull request with its reviewers' avatars and decisions, its builds and the ones its target branch requires, open tasks, its formatted description and its activity, comments included; a list of pull requests; or its diff, a file at a time, highlighted, with each comment on its line. It looks and reads like Bitbucket, and anything you click opens there.

    Ask for PAYMENTS/ledger#42 and the answer comes with its card; open the card for the full overview and its activity, or its diff. In the diff, select lines to add them to the chat, to ask about them or to comment on them; reply to a comment, and approve or request changes, without leaving the conversation. Ask the AI to open a pull request and it opens it; when you want a say in its description or reviewers first, it hands you its draft as a form to finish and submit, with the default reviewers and code owners filled in as Bitbucket's create page does. A view carries what it shows, so it still renders when you come back to the conversation, even without bb running, and it says when it was read. While it is on screen it keeps itself current: watch a build finish or a comment arrive without asking again, and the AI is told what changed. Terminal agents such as Claude Code show the usual text.

    A pull request card: its title, author and branches, who requested changes, a failed and a running build, a required build missing, two open tasks, and how many approvals and builds passed

    A pull request's diff: the file tree with each file's open comments counted, beside one file's highlighted changes, a task on the line it was written on and a resolved thread folded to a line

    Views in your agent shows all five: the card, the overview with its activity, a list, the diff and the form.

  • Files reach the AI in a format it can ingest (ADR-094):

    get_file_content passed every file as one string, whatever its size, and a file that is not text as unreadable characters. It now converts the file on the server: text as a window of numbered lines, so a long file is read a part at a time; an image as an image; a Word, PowerPoint or Excel file as its text; an archive as a list of its entries. Anything else is described by its type and size, with its page in Bitbucket. This is the MCP server's tool; bb repo cat still prints a file as it is.

For administrators

  • Administrators decide whether bb, or its MCP server, may be used at all (ADR-100, #690):

    Three new system policy settings, which no flag, environment variable or user configuration overrides:

    Setting Registry value Effect
    disable_mcp_server DisableMCPServer bb ai mcp serve is refused; the rest of bb keeps working.
    read_only ReadOnly Commands that change Bitbucket are refused, bb api sends only GET and HEAD, and the MCP server offers only the tools that read.
    disable_bb DisableBB Every command is refused except help, --describe, --version, bb doctor and the completion scripts.

    Set them in /etc/bb/config.yaml, or %ProgramData%\bb\config.yaml on Windows:

    policy:
      read_only: true

    Or through Group Policy, as the registry value set to 1 under HKLM\Software\Policies\bb.

  • Running and auditing the MCP server (ADR-098, ADR-099, ADR-101):

    • A tool that asks records the answer: the audit record has confirmation (accepted, declined, cancelled or unavailable), and a call the confirmation stops is status: denied. The question is a record of its own, status: asked, written before the person answers, so an agent that asks and never answers still leaves a trace.

    • The audit trail redacts credentials wherever they appear in an argument or a resource URI (#731). An argument was redacted only when its name marked it secret or its whole value was a URL, and the resource field not at all, so a credential inside a path, a ref or a title was written to the audit file. Both now get the redaction error_message gets, which also catches token=... as Bitbucket quotes it back and BITBUCKET_TOKEN=.... A redacted URL reads [REDACTED] rather than %5BREDACTED%5D.

    • --tools and --exclude decide which resources and prompts are offered, as they decide the tools. The audit trail records reads, the resource list and prompts as mcp_resource_read, mcp_resource_list and mcp_prompt_get, with resource or prompt in place of tool; completions are not recorded. A SIEM rule that expects every record to name a tool needs to allow for them:

      {"timestamp":"2026-08-29T09:32:40Z","event":"mcp_resource_read","resource":"bitbucket://projects/PAYMENTS/repos/ledger/pull-requests/42/diff","project":"PAYMENTS","repo":"ledger","status":"success","duration_ms":61,"user_identity":"alice","host":"https://bitbucket.example.com","scope":"PAYMENTS"}
    • A view has no network access; bb fetches the avatars with its own credentials and puts them in the result. --exclude show turns views off. A view keeps current by calling refresh_view, and the form suggests values through suggest_form_values: read-only tools only views are offered, each call recorded in the audit log like any other; --exclude refresh_view keeps views as they were drawn. What you do in a view goes through the AI's own tools, with their confirmations, and a view has no connection of its own to Bitbucket. The server tells agents to show views only to a person who is there, never in unattended work. Of Svelte, ERB, PHTML, Go HTML and Jinja templates only the markup is highlighted; --highlight-templates highlights the code in them too, with lexers a crafted file can keep busy for seconds, though no view waits for them.

    • For MCP clients: every tool declares all four MCP hints and a title as the specification defines them, so a client that decides its own prompts from the hints may prompt for different tools. openWorldHint is false on every tool, and update_pull_request and disable_auto_merge are destructive. bb ai mcp tools has asks (always, never or when-setting-draft) and takes --read-only. bb ai mcp tools --json for one tool:

      {
        "name": "merge_pull_request",
        "description": "Merge a pull request. All required build checks must pass and all reviewers must have approved. Asks the person to confirm in the client before it runs.",
        "writes": true,
        "asks": "always",
        "safe": true,
        "exposure": "SAFE"
      }
  • bb update on premises (ADR-092, #637, #633):

    bb update installs the new binary itself before it exits, on every operating system. On Windows it used to leave the swap to a PowerShell helper that ran after bb had exited. Application control such as AppLocker or WDAC blocked the helper, and bb had already reported success.

    Behind a release mirror, every download now goes through the mirror, with the CA and the client certificate it was configured with, and a mirror whose certificate this host does not trust is reported as a failure to fix, no longer as one to retry. bb update --dry-run verifies the release the mirror serves, its signature, its checksums and the archive itself, also when nothing newer is there. That makes it the check to run on a host after a rollout. A slow link no longer fails the download at the request timeout.

  • Requests name bb (#702). Every request carries User-Agent: bb/<version> (<os>/<arch>), ending in mcp when the MCP server sends it, so an administrator can find bb's traffic, and an agent's, in Bitbucket's access log or at a proxy.

Before you upgrade

If you consume bb inside CI/CD pipelines, shell scripts, or AI agent toolchains, review this checklist before upgrading:

  1. bb pr checks gates on CI the way gh pr checks does (ADR-091, #646):
    • Without --json, bb pr checks and bb pr build status exit 1 when a build failed, and 8 when none failed and one is still in progress or has no result. They used to exit 0 whatever the builds said, so a gate written for gh, bb pr checks 42 || exit 1, let every pull request through.
    • A failed build wins over one still running, and a cancelled build counts as neither. The exit status covers every build, not only the --limit shown. When it is not 0, a line on stderr says how many builds failed or are still running.
    • Exit 8 is new to bb. It is not an error kind, and only these two commands use it.
    • Under --json both commands still exit 0, with each build's state in data.statuses, as gh pr checks --json does.
    • A script that runs either command for its output and relies on exit 0 adds || true, or passes --json.
  2. bb bulk is gone, as the v4.1.0 notes announced (ADR-084, #608):
    • bb bulk plan, bb bulk apply and bb bulk status no longer exist, nor do BB_BULK_STATUS_DIR and the bulk policy, plan and apply-status schemas.
    • Set permissions, webhooks, default tasks and branch restrictions once on the project, with bb project permissions, bb project webhook, bb project default-task and bb project branch-restriction. Bitbucket applies them to every repository in the project.
    • For a setting Bitbucket keeps per repository, loop over bb repo list --project PROJ --json and run the bb repo settings command for each, previewing with --dry-run. The loop is safe to run again: a webhook create that finds its webhook already there reports it rather than adding a second.
    • The bb-bulk agent skill is gone too, so bb ai skill install bulk exits 2. Delete any copy an earlier bb installed, in .agents/skills/bb-bulk or .claude/skills/bb-bulk, in a project or in your home directory. bb doctor names every copy it finds.
  3. --dry-run answers with a verdict, in its own member (ADR-096, #616):
    • Under --json, a dry run answers in preview rather than data: a tier, one effect per change with its action, target, outcome (would-apply, no-op or would-fail) and reasons, and the error the real run would fail with. dryRun, planningMode, capability, summary, and per item intent, predictedAction, supported, confidence, requiredState and blockingReasons are gone; a script reading summary reads effects instead. bb --json pr merge 42 --dry-run, for a pull request that is already merged:

      {
        "preview": {
          "tier": "preconditions-checked",
          "effects": [
            {
              "action": "update",
              "target": { "id": "42", "repository": "PROJ/app" },
              "outcome": "would-fail",
              "reasons": ["pull request is already merged"]
            }
          ],
          "error": { "kind": "conflict", "message": "pull request is already merged", "exitCode": 5 }
        },
        "meta": { "command": "pr merge", "bbVersion": "..." }
      }
    • A command that only reads still runs, and its data is in preview.data. A failure the check runs into, such as invalid arguments or a missing pull request, is preview.error rather than a top-level error, which under --dry-run now means only that no verdict was reached: 10 Bitbucket did not answer, 12 interrupted, 1 a bug in bb.

    • Without --json, a dry run that finds the run would fail exits with the code the real run would, so bb pr merge 42 --dry-run && bb pr merge 42 stops at the check. It used to exit 0. Under --json or --yaml a verdict exits 0, with the verdict in the document.

    • The text output names each change and why it would or would not go through, in place of the intent=... action=... lines.

    • bb ai mcp serve no longer takes --dry-run.

    • There is no warning period: one document cannot carry the old preview beside the new one.

  4. --describe describes the whole document, for a run and for a dry run (ADR-097, #616):
    • Under --json it answers in description rather than data. run.outputSchema is the JSON Schema of the whole document a run writes, meta and the error included, and dryRun.outputSchema the one --dry-run writes, beside dryRun.behaviour and dryRun.tier. described is gone, command is meta.command and reason is run.reason. A script reading schema reads run.outputSchema.oneOf[0].properties.data, or better, validates the whole document against run.outputSchema.
    • Without --json or --yaml it prints an outline of the fields for people, rather than the JSON Schema.
    • bb <group> --describe and bb --describe list their commands with what --dry-run does for each, rather than saying a group has nothing to describe. A path that names no command answers with description.error, exiting 0 under --json.
    • There is no warning period: one document cannot carry the old description beside the new one.
  5. The MCP server asks your permission in your MCP client, and offers every tool by default (ADR-098, #620):
    • bb ai mcp serve moves to MCP's newer way of asking for permission, elicitation: the server asks, and your MCP client shows you the question. By default it offers every tool, as it did with --yolo, but a tool that merges, or decides what merges or gets released, asks you first. That covers merging, turning auto-merge on or off, approving or requesting changes, reporting a build status, creating a tag, and moving a pull request into or out of draft. Your client shows what the call will do, and it runs only once you accept. Before, the server hid most of these unless it started with --yolo, and then nobody was asked.
    • Locking the server down is now opt-in: with --read-only it offers only the tools that read. --yolo and --allow-writes do nothing, and warn.
    • You accept the pull request you were shown. If someone pushes to it before you accept, the merge or auto-merge is refused.
    • Those tools need a client that supports elicitation. One that does not gets error -32021 for them, and nothing changes in Bitbucket.
    • What changes in the audit record, in the hints a client reads and in bb ai mcp tools is under "For administrators".
  6. bb api authenticates like every other command (ADR-083, #707):
    • -H with an Authorization, Proxy-Authorization or Cookie header exits 2, and so does a user or password in the endpoint URL or --host. A secret on the command line is readable in the process list and lands in shell history.
    • A script that passed its token that way stores it once with bb auth login https://bitbucket.example.com --token-stdin, or sets BITBUCKET_TOKEN in the environment.
  7. A stored credential goes only to the host it was stored for (#730):
    • A credential bb auth login stored for one Bitbucket is sent to that host alone. A command pointed at another host, by --host, BITBUCKET_URL, a .env, a workspace .bb/config.yaml or a full URL given to bb api, sends that host no credential unless one is stored for it too, and Bitbucket answers 401 for anything that is not public. The same holds for the fork lookup after bb repo clone of another host's URL, which also no longer shows that host your default host's client certificate. An alias of the stored host still counts as the same host.
    • A host profile in a workspace .bb/config.yaml gives that host its url and username, and nothing that acts as you: it never makes bb send a stored token or password, and its client_cert and client_key are ignored. A profile keyed to another host with its url set to your Bitbucket, or one naming another host as an alias of yours, was handed your token. If a workspace file set a client certificate, set it with --client-cert and --client-key on bb auth login, or in BB_CLIENT_CERT and BB_CLIENT_KEY.
    • A credential stored for https:// is not sent to the same host over http://, so a .env or .bb/config.yaml naming your Bitbucket over http:// can no longer send your token in the clear, and bb clone no longer passes it to git for an http:// clone link. A login stored for http:// still answers over https://.
    • Before v4.1.0 a host with nothing stored for it got the default host's credential, which sent your token to whatever host a cloned repository's .env or workspace file named. v4.1.0 closed that everywhere but bb api and the clone's fork lookup, without saying so in its notes; v5.0.0 closes those two.
    • A script that relied on the old fallback logs in to each host it talks to, bb auth login <host>, or sets BITBUCKET_TOKEN for the run.
  8. A credential goes into the configuration file in plaintext only when you ask (ADR-047):
    • Where the OS keyring cannot hold the secret, on a headless server, in most containers, or in WSL without gnome-keyring, bb auth login exits 1 and stores nothing. It used to write the secret into the configuration file in plaintext, with a warning on stderr, without being asked.
    • This affects a login on a machine with no keyring. Where a keyring works, nothing changes. The token bb repo clone asks for when nothing is stored for the host is then used for that clone and not stored.
    • To keep the old behaviour, pass --allow-insecure-storage to bb auth login. Better, in CI and containers, set BITBUCKET_TOKEN in the environment and do not log in at all. BB_REQUIRE_KEYRING=1 and the require_keyring policy refuse plaintext even with the flag, and --require-keyring cannot be combined with it.
    • A credential already stored in plaintext keeps working, with its warning, so nobody is locked out by the upgrade. Only a new login needs the flag.
    • Where a keyring is required, by BB_REQUIRE_KEYRING=1 or the require_keyring policy, a credential stored in plaintext is refused wherever it is read: git no longer gets it from bb auth git-credential and falls through to its own prompt, and bb repo clone says to log in again where the keyring works.
  9. --yes is refused unless the repository is on the command line (ADR-073, #752):
    • A command that deletes, removes, revokes or clears something in a repository, given --yes with the repository from BITBUCKET_PROJECT_KEY and BITBUCKET_REPO_SLUG, now refuses: it exits 2, changes nothing, and says how to name the repository. It used to go ahead in the repository the variables named. A repository from the git remote was already refused this way.
    • What to do: add --repo PROJ/repo to the command, for example bb branch delete feature/x --repo PROJ/repo --yes. For bb reviewer-group, bb reviewer condition and bb repo ssh-key, --project PROJ does it too; BITBUCKET_PROJECT_KEY no longer does. An argument that names the repository also counts: the PROJECT/slug of bb repo delete, or a pull request's URL.
    • Without --yes nothing changes: a person at a terminal is still asked to type back what is about to be destroyed, and with nobody to ask the command still refuses.

Other fixes worth knowing

  • A project key or repository slug cannot carry a path. A slug such as repo/pull-requests/7/merge?version=3# turned a request into one for another endpoint, so through the MCP server a tool that never asks could merge a pull request. A key or slug holding a slash, ?, #, % or whitespace is refused.

  • A repository command no longer changes what its project defines (#657). A repository's branch restrictions, default reviewer conditions and default tasks include the ones it inherits from its project. bb branch restriction delete --repo, given the id of an inherited one, deleted it from the project, and so from every repository in it. These commands now refuse an inherited entry and name the project command that changes it, and the listings mark what is inherited.

  • A branch restriction survives an update that is refused, and --user and --access-key-id work. An update deleted the old restriction before it created the new one, so a refusal, for a user name that does not exist for instance, left the branch unprotected. The two flags had failed on every call.

  • A long transfer is no longer cut off. bb clone was stopped after 60 seconds whatever it was doing, and bb repo archive, bb repo cat and the download in bb update had to finish within request_timeout. Each now runs for as long as it makes progress, and a failed bb repo archive leaves no partial file.

  • bb ai skill install reaches Claude Code. It wrote the skill to .agents/skills, which Claude Code does not read. It writes .claude/skills as well now, and bb ai skill remove takes out both.

  • Git authenticates as the login bb auth setup-git set up (#733). The helper line named bb and nothing else, so git pushed as whichever configuration file BB_CONFIG_PATH named when git ran, and two logins for one host could not be kept apart. The line now names the configuration file setup-git read, and bb auth git-credential takes it as --config. Run bb auth setup-git again to pin an existing setup; it replaces bb's own earlier line without --force.

  • bb pr checkout keeps the credential off git's command line, where any local account could read it while git ran, as bb clone already did.

  • --project inside a clone means the project (#725). In a clone, bb filled in the clone's repository beside --project, so bb reviewer-group and bb repo ssh-key refused it for naming both, and bb reviewer condition acted on the repository instead: create --project wrote the condition there. bb search prs --role was refused the same way. A scope you name now keeps the clone out of it. bb reviewer condition refuses --project and --repo together, as bb reviewer-group does.

  • bb build required delete --dry-run finds the check wherever it is (#728). The preview looked for the check among the first --limit checks only, 25 by default, and predicted no-op, "not found", for one further down, which the real run then deleted. It reads every check now.

  • An https:// URL for a server that speaks plain HTTP is permanent (exit 1) (#704). It was transient (exit 10) and tried three times, though the answer cannot change. The message says to check whether the URL should begin with http://.

  • Creating a webhook that is already there reports it (#729). Bitbucket stores a second webhook with the name, URL and settings of one it has, and both fire, so a setup script run twice made two. bb webhook create, bb project webhook create and bb repo settings workflow webhooks create now report the webhook that is there and exit 0, with created: false under --json. One with the same name and URL and other settings is refused as a conflict (exit 5) that names it and what differs; change it with update. --dry-run predicts both. Bitbucket never returns a webhook's endpoint password, so a password you pass is not compared, and a note on stderr says so.

    {
      "data": {
        "status": "ok",
        "repository": { "projectKey": "PROJ", "slug": "repo" },
        "webhook": {
          "id": 12,
          "name": "ci",
          "url": "https://ci.example.com/hooks/bitbucket",
          "active": true,
          "events": ["repo:refs_changed"],
          "sslVerificationRequired": true,
          "scopeType": "repository",
          "secretConfigured": false
        },
        "created": false
      },
      "meta": { "command": "webhook create", "bbVersion": "..." }
    }
  • An HTML error page is reported by its title (#704). The message used to show the page's first 300 characters, which were all markup. Now it says what the page is:

    validation: bitbucket API returned 400: an HTML page titled "Bad request - Bitbucket" (18389 characters; pass --full-error-body to see all of it)
    
  • bb auth git-credential honours BB_DISABLE_STORED_CONFIG=1. With it set, git gets no stored credential from bb, the same as every other command.

  • bb clone and bb repo clone ask for no token under --no-input. They report that no credential is stored for the host instead.

  • Repository inference honours the global flags. It loaded its configuration from the environment alone, so a --request-timeout given beside a broken BB_REQUEST_TIMEOUT turned inference off without a word.

  • Output that was wrong, for a script that reads it:

    • bb pr get lists a pull request's reviewers. It listed everyone who took part, so whoever merged it or commented in passing appeared as a reviewer, and the review summary counted a real approval as missing.
    • A resolved comment thread counts as resolved, in bb pr comment list and in the unresolved count of a pull request.
    • bb branch list marks the default branch (#658). Every branch read default: false.
    • bb diff pr --name-only prints each path as it is, no longer as dst://path, and names binary files. bb diff refs --stat counts the change the diff shows; it counted the reverse. --path on bb diff commit and bb diff refs prints a unified diff; it printed JSON.
    • bb deployment get reports the commit that was deployed as toCommit. fromCommit is the commit the previous deployment deployed, which is what Bitbucket means by it.
    • bb api --json carries a body that is not text as base64 and says so in meta.encoding. It used to replace every byte that was not valid text.
    • bb clone reports "meta": {"command": "repo clone"}, the command it is an alias of, as every alias does. It reported clone.

Deprecation

  • bb update --json: scheduled, staged, paths.staged and paths.swapResult are deprecated and are removed in v6.0.0 (ADR-084, ADR-092).
    • bb update installs the new binary itself before it exits, on every operating system, so these fields are always false or empty. Read applied instead.
  • bb ai mcp serve --yolo and --allow-writes, bb ai mcp tools --safe-only, and the safe and exposure fields of bb ai mcp tools --json are deprecated and are removed in v6.0.0 (ADR-084, ADR-098).
    • Every tool is exposed without --yolo, so the flags do nothing, --safe-only lists every tool, safe is always true and exposure always SAFE. Pass --read-only for a server that only reads, and read asks and writes instead of the fields.
  • --matcher-display on bb branch restriction create and update and on bb project branch-restriction create and update, and --include-unique on bb build status stats, get and set, are deprecated and are removed in v6.0.0 (ADR-084).
    • Neither ever changed a result. Bitbucket works out a matcher's display name from the matcher and ignores the one it is sent, and bb printed the same build counts with --include-unique and without it. Both are still accepted and print a warning on stderr; remove them from scripts. bb build status get lists each build with its state.
  • --limit and --all on bb build required delete are deprecated and are removed in v6.0.0 (ADR-084).
    • They bounded the checks the preview looked through, and it looks through all of them now. Both are still accepted and print a warning on stderr; remove them from scripts.

The complete list of breaking changes, commit references, and full change ledger is itemized below.

Changes since v4.1.0.

Compare: v4.1.0...v5.0.0

⚠ Breaking Changes

  • let --yes apply only to a repository named on the command line (2a9e249) — a destructive command given --yes with its repository from BITBUCKET_PROJECT_KEY and BITBUCKET_REPO_SLUG exits 2; pass --repo.
  • store a credential in plaintext only when asked to (d681004)
  • tools that decide a merge ask the person through the client (4ba9aa1) — bb ai mcp serve lists every tool, and a client that cannot show an elicitation gets error -32021 for the tools that ask instead of not seeing them. --yolo no longer makes them run unasked.
  • --describe describes the whole document in every mode (7141b0a) — --describe --json answers in description rather than data, and command, described, schema and reason are gone; without --json it prints an outline rather than JSON Schema.
  • --dry-run answers with a verdict, in its own member (0064ca0) — under --json, --dry-run answers in preview rather than data; dryRun, planningMode, capability, summary and the per-item intent, predictedAction, supported, confidence, requiredState and blockingReasons are gone. A text dry run that finds the run would fail exits with the real run's code rather than 0. bb ai mcp serve rejects --dry-run.
  • exit as gh pr checks does when a build failed or is running (000b68a) — bb pr checks and bb pr build status without --json exit 1 when a build failed and 8 when one is in progress or has no result, as gh pr checks does, where they exited 0. A script that ran them for their output and relied on exit 0 adds || true or passes --json, which still exits 0.
  • remove bb bulk, and the skill that taught agents to use it (1d79484) — bb bulk (plan, apply and status) no longer exists, nor do the bb-bulk agent skill (bb ai skill install|show|remove bulk), BB_BULK_STATUS_DIR, or the bulk policy, plan and apply-status schemas. Set permissions, webhooks, default tasks and branch restrictions once on the project with bb project permissions, bb project webhook, bb project default-task and bb project branch-restriction, where Bitbucket cascades them to every repository in it. For a setting Bitbucket scopes only to a repository, loop over bb repo list --project PROJ --json and run the bb repo settings command for each, previewing with --dry-run. Delete the bb-bulk skill wherever an earlier bb installed it -- .agents/skills/bb-bulk and .claude/skills/bb-bulk, in a project or in your home directory; bb doctor names every copy.
All 500 changes

Features

  • auth: store a credential in plaintext only when asked to (d681004)
  • branch: list --details prints the details (bddfdc4)
  • cli: deprecate --matcher-display and --include-unique (5029d82)
  • search: take a period as ISO 8601 writes a date (3f7d731)
  • search: list your pull requests by state and by period (4864bb3)
  • pr: work out pr create's branches and title from the checkout (136df3c)
  • pr: say where a pull request is, and merge with a chosen strategy (e850ef3)
  • mcp: say how to go on when a view is not drawn (dfcebe5)
  • mcp: open a pull request asked for, and show the form for a say (bff970c)
  • mcp: tell agents that views are for a person who is there (7fa884e)
  • mcp: keep the reviewer search beside the form's last chip (b3c35c1)
  • mcp: leave the author out of the form's reviewers, whoever names them (15932cc)
  • mcp: pick the form's branches and reviewers as Bitbucket does (e03204a)
  • mcp: fill in the form's reviewers as Bitbucket's create page does (824da2c)
  • mcp: count a card's builds as its pull request page does (31e07f2)
  • mcp: highlight the lines a comment in the activity is shown among (322a793)
  • mcp: put comments where Bitbucket has them, and drop the file viewer (de5a938)
  • mcp: highlight a template's markup, and its code on request (258c6f2)
  • mcp: highlight the code in diffs and files (12ef8e0)
  • mcp: tokenize code for the views to highlight (3717272)
  • mcp: show the builds a pull request must pass on its card (272a857)
  • mcp: work out the builds a pull request must pass (1034d80)
  • mcp: show a file as what it is (3e2fc35)
  • mcp: hand the person a pull request to finish and submit (78e89de)
  • mcp: approve or request changes from the overview and the diff (169b596)
  • mcp: draw a diff's comments on their lines and comment on one (ea5caef)
  • mcp: reply to a thread and comment from the comments view (9e1aff5)
  • mcp: open a pull request's diff and comments in the same view (99ac9e7)
  • transport: name bb in the User-Agent of every request (f15c587)
  • mcp: check a view in motion every 15 seconds (5b1cb52)
  • mcp: keep a view current while it is on screen (b6d14d1)
  • mcp: list a threads card's comments where they are (679585d)
  • mcp: show a pull request's comment threads as a view (d19ca8e)
  • mcp: read whether a client opens links before asking it to (6f47fc7)
  • mcp: say when a client will not open a link, and ask about fullscreen (f543219)
  • mcp: make the inline views glanceable (ad85c8c)
  • mcp: lay the views out tighter and clearer (7cf803e)
  • mcp: keep views true at any size and draw Markdown descriptions (3052471)
  • mcp: show pull requests, lists and diffs as views in MCP clients (1dfde81)
  • policy: let administrators switch bb off, switch its MCP server off, or make it read-only (67d6c4f)
  • mcp: serve pull requests, diffs, files and commits as resources, with prompts and completions (1e74130)
  • mcp: tools that decide a merge ask the person through the client (4ba9aa1)
  • describe: --describe describes the whole document in every mode (7141b0a)
  • outline: one sentence per field, on lines up to 120 columns (5d5ff71)
  • outline: print a JSON Schema as an outline of fields (491d523)
  • dry-run: --dry-run answers with a verdict, in its own member (0064ca0)
  • jsonoutput: encode a document as YAML that means the same as its JSON (80265b4)
  • output: --yaml prints the document --json prints, as YAML (b4e94f9)
  • mcp: list bzip2-compressed tar archives (7608828)
  • mcp: convert BMP and TIFF images to PNG or JPEG (77c25c4)
  • mcp: turn a photograph upright from its EXIF orientation (7d4e85a)
  • mcp: return short audio and video as media, and describe the rest (753aaa0)
  • mcp: extract the text of Word, PowerPoint and Excel files, and list archives (ba7c66e)
  • mcp: return an image file as an image, scaled to fit, and say so (3712330)
  • mcp: read a file in numbered windows, and describe what is not text (1e92978)
  • update: deprecate the --json fields of a swap left for later (60a436e)
  • pr: exit as gh pr checks does when a build failed or is running (000b68a)
  • doctor: report a skill this bb no longer carries (03c736e)
  • bulk: remove bb bulk, and the skill that taught agents to use it (1d79484)
  • doctor: report shell completion and agent skills (eb12b5d)
  • skill: install the skill where Claude Code reads it too (a656e9a)
  • completion: set shell completion up with bb completion install (cb07323)
  • completion: describe every branch by its latest commit (219b929)
  • completion: offer the bulk runs saved on this machine (fa5dc13)
  • completion: complete the values that come from a fixed vocabulary (cbbbc9f)
  • completion: follow --matcher-type when completing --matcher-id (a2047e7)
  • completion: complete the ids a person cannot remember (7d7c268)
  • completion: complete the keys on a commit and on your account (6eae307)
  • completion: complete a path one segment at a time (2352859)
  • completion: complete repositories and projects (1e24130)
  • completion: offer the people a slot can actually name (abbc55b)
  • completion: complete branches, tags, refs and commit-ish values (6160e8a)
  • completion: complete the values that need nothing asked (dd5223c)
  • completion: declare what every argument and flag accepts (767ae8e)
  • compat: make an older Bitbucket release answer as the newest does, or refuse what it cannot do (5e8d7ca)
  • errors: report what a Bitbucket release cannot do as unsupported, exit 14 (6ff86e0)

Fixes

  • release: keep the release body under GitHub's limit, and stop before the tag when it is not (89036c3)
  • cli: refuse a malformed --repo before asking to confirm a delete (a080963)
  • cli: let --yes apply only to a repository named on the command line (2a9e249)
  • network: hand a body cut short back cut short under the error recorder (75eb470)
  • cli: infer the repository with the host and flags the command was given (b5356f5)
  • clone: register bb clone as the alias of bb repo clone (d897907)
  • clone: refuse the token prompt under --no-input (71801a7)
  • auth: answer git from no stored credential under BB_DISABLE_STORED_CONFIG (cbd583e)
  • config: refuse a plaintext credential to git and a clone under the keyring requirement (599a39a)
  • repo: suggest only what names the repository when --yes is refused (e8e3c84)
  • clone: use a token the keyring cannot hold for that clone, not fail it (6c132b6)
  • config: never let a workspace host profile release a credential (ff88306)
  • webhook: report a webhook a create finds already there (b47cbfd)
  • cli: declare the status field the output carries (7f1ed99)
  • mcp: audit the question a tool that asks puts, answered or not (3c6bd5a)
  • mcp: redact credentials in audit arguments and resources as free text (ff69a7d)
  • auth: pin the login git authenticates as in the setup-git helper line (9aee5a6)
  • config: never send a credential stored for https over plain http (db21902)
  • git: keep the credential off git's command line in a fetch (53bea88)
  • build: find a required check past --limit in the delete preview (8d1ba3a)
  • cli: keep the checkout out of a scope named with --project (70559e8)
  • auth: report a failed user lookup in bb auth token by its cause (7467e71)
  • pr: merge, decline and reopen again when the version just moved (faed97f)
  • mcp: fill in the default reviewers on the pull request form (5071e8c)
  • repo: show a clone host only the client certificate meant for it (273a606)
  • transport: say when an https:// URL meets a plain-HTTP server (164a91e)
  • repo: ask a clone host about forks with its own credential (cf3d28e)
  • auth: let token-url name its host before any login (f52a0e2)
  • api: refuse a credential in a URL, and never repeat one in an error (d38cab2)
  • api: refuse a header that carries a credential (79f5a36)
  • api: refuse an endpoint URL's second host before a dry run (ce2dbdf)
  • api: send an endpoint URL only its own host's credential (34ff3f5)
  • mcp: count a task once on the pull request card (1286238)
  • pr: count a resolved comment thread as resolved (33872fa)
  • pr: report a pull request's reviewers, not everyone who took part (c0ff9d0)
  • mcp: hold auto-merge to the version shown, and let a late refusal stand (42d290c)
  • repo: refuse a project key or slug that would leave its path segment (e0f5a6a)
  • git: a clone runs while it makes progress, and a stopped git says why (b9d8ecb)
  • describe: bb update's dry-run schema holds its report (0bd9bc6)
  • describe: wrap the prose around an outline at its width (49945ad)
  • describe: a preview whose verdict is predicted predicts (8788746)
  • describe: bb api's dry run carries data, and its description says so (4831d79)
  • update: a dry run names the binary it would replace (59383c8)
  • dry-run: predict the failure a real run meets where no-op was predicted (f04d86f)
  • output: meta.command names the canonical command for a shallow alias (f0a9360)
  • dry-run: declare the tier each stateful command's preview reaches (6e66584)
  • dry-run: refuse a project name already in use (481ec33)
  • dry-run: stop refusing a duplicate webhook, and name a missing task (96355ed)
  • dry-run: follow who Bitbucket lets change a comment (c6c5d2a)
  • dry-run: check reviewer groups the way Bitbucket does (44a37f1)
  • dry-run: predict what Bitbucket does with a reviewer condition (155c70e)
  • dry-run: give each pull request effect the reason a verdict prints (0e45307)
  • dry-run: write branch delete's verdict through the preview writer (80d1932)
  • dry-run: predict the upsert a matching restriction create is (225043f)
  • dry-run: name the kind a refused pull request change fails with (1b13c4f)
  • output: hint about a gh field list only when the command took it as one (a320afc)
  • api: carry a body that is not text as base64 under --json (61ba58b)
  • mcp: stop converting a file when the call is cancelled (15d4bf9)
  • browse: escape a file path once, so a name with a space opens its page (4a72922)
  • api: write a body that is not text byte for byte (d4b07d4)
  • repo: stream bb repo cat and browse raw, and report a failed write (fcd54ee)
  • repo: stream bb repo archive without a deadline, and leave no partial file (5a46ae3)
  • update: download a release without a deadline on the transfer, capped and retried (ad49cb9)
  • update: replace the file a symbolic link to bb names, and keep the link (9d71e3c)
  • update: replace the running bb.exe before bb update exits (3c052ad)
  • update: replace the binary on Linux and macOS with one rename (650f96f)
  • update: say that a mirror wanting a login is not supported (f83f52e)
  • update: keep bb update on its mirror, with the TLS and trust it was given (3ee9b7e)
  • errors: send again an idempotent request whose answer Bitbucket failed to write (89545a7)
  • webhook: show the secret --reveal-secret asks for as text (78efb9d)
  • webhook: publish the webhook a read returns after a create or update (de37163)
  • update: fail a dry run whose mirror serves an older release (d091183)
  • update: verify the release a mirror serves on every dry run (4f43f25)
  • branch: mark the default branch in bb branch list (0669e1b)
  • keep a repository's commands off what its project defines (3465be4)
  • repo: list every default task, not the first 25 (2510b8e)
  • skill: take the skill's emptied directory out on remove (72c979a)
  • doctor: count a quoted path to bb as completion set up by hand (6a1a740)
  • completion: stop waiting for a shell that does not answer (816a6e9)
  • completion: change a startup file where it is rather than replace it (7730a61)
  • completion: read a Windows SHELL path the same on every OS (0a8d46d)
  • doctor: find a project's skills from anywhere in its repository (6f10061)
  • completion: take out a PowerShell profile that held only bb's block (7d3cc67)
  • completion: say when a branch category is switched off (4ddb900)
  • completion: describe an instance logged in with a token (e6333ca)
  • completion: keep fish from adding a space after a list element (660abcb)
  • completion: describe what each log level adds, not what the flag is for (537680b)
  • completion: cut a description between characters, not bytes (8839dbd)
  • completion: let an argument that takes a path ask the shell for one (d759750)
  • docs-lint: fold the version wrapper into the function that takes one (f9e20ad)
  • completion: make a tab press behave in PowerShell (16088f7)
  • completion: stop refusing every positional completion (9355e13)
  • default-task: say which kind of ref each matcher of a default task matches (fb318d2)
  • deployment: report the commit a deployment deployed (f86ccad)
  • commit: let bb commit get read a branch whose name has a slash in it (03d2aee)
  • repo: let auto-decline set --enabled=false switch the policy off (746b157)
  • comment: report a draft comment as pending and an inline comment as anchored (46dfc7c)
  • restriction: refuse a restriction id that is not a number instead of failing as transient (5219d1f)
  • diff: name changed files by their path in bb diff pr --name-only, not as dst://path (f65e4ee)
  • diff: print a unified diff from bb diff commit --path and bb diff refs --path (41604bb)
  • diff: bb diff refs --stat counts the change the diff shows, not its reverse (9733cd6)
  • project: report access to a project whose name is part of another project's name (0d52c1c)
  • project: refuse a dry-run project create to an account that may not create projects (53cca7b)
  • restriction: keep a restriction when its update is refused (1e3f506)
  • restriction: make --user and --access-key-id work on branch restrictions (ec4ed7a)

Refactors

  • jsonoutput: remove EnvelopeSchemaFor, which only tests used (bbbc0e6)
  • jsonoutput: derive the published meta member from EnvelopeMeta (ab0dee1)
  • config: drop the system-file CA fallback nothing could reach (5e3833f)
  • auth: write setup-git's helper through the git backend factory (e1eea16)
  • jsonoutput: derive the published error member from EnvelopeError (0c33164)
  • reviewer: remove SelectMembers (8c5fcb0)
  • completion: list projects, repositories and directories from one place (53a09c2)
  • transport: add a downloader that waits on silence, not on the whole body (7750442)
  • completion: read the checkout's remotes through the invocation (f6874a0)
  • cli: name each positional argument after what it accepts (d89f671)

Docs

  • security: update threat model for v5.0.0 release (#724) (4545212)
  • release: say the --yes change refuses, and what to do about it (adc8ea7)
  • release: name the credential, clone and inference fixes in the v5 notes (daaca75)
  • state the rule in the transport and openapi-spec package comments (bb562b4)
  • adr: list every governance test in ADR-067 (c2c276f)
  • adr: merge four groups of records that state one rule (1a0f452)
  • adr: say each thing once, and restore the rules the review found missing (c9363b4)
  • adr: refuse a record that names what replaced it, and say each thing once (0df41a4)
  • adr: restore what the rewrite dropped, and trim (e9c7e5e)
  • adr: state the process and release records as the rules that hold now (33e6c4c)
  • adr: restore what the rewrite dropped, and trim (2037639)
  • say linear history is enforced, and fix comments that name what is gone (2e9ad9c)
  • adr: state the testing and quality records as the rules that hold now (814da38)
  • adr: restore three points the MCP rewrite dropped (a82779f)
  • adr: restore what the rewrite dropped, and trim (1ac7d21)
  • harness: name no Bitbucket release in the Dockerfile's comments (fbf1dae)
  • adr: state the release, transport and distribution records as the rules that hold now (7add7df)
  • adr: restore what the rewrite dropped, and trim (418504f)
  • drop stale CRLF advice and name the comment decoder that exists (c03566b)
  • adr: state the interactivity and command-tree records as the rules that hold now (46dac44)
  • adr: restore what the rewrite dropped, and trim (04b4b93)
  • adr: say a workspace host profile releases no credential (96d6d54)
  • stop describing a --token flag in comments (ade9599)
  • adr: state the auth and configuration records as the rules that hold now (a9cf34e)
  • adr: restore what the rewrite dropped, and trim (dcbab35)
  • drop the --token flag and the history from two comments (933b813)
  • adr: state the output, error and dry-run records as the rules that hold now (dbc0a68)
  • name no release in the README and skill output examples (96b9fd2)
  • adr: state the MCP records as the rules that hold now (53db452)
  • release: place what next fixed since the restructure (d95f53b)
  • adr: stop describing bb bulk, which v5 removed (0928d5c)
  • adr: keep the decision records as Markdown pages (99ee98e)
  • release: announce that a stored credential goes only to its own host (faeabb0)
  • reference: name each MCP tool for people, and keep the model's text as it is (ca2364f)
  • split the hardening guide into the four things it covers (243bf6d)
  • state the security pages' claims as facts, not guarantees (38d86f9)
  • say what a token lets bb do, and what a refused one looks like (32bb0e8)
  • help: say where bb api --raw-field puts its parameter (0fbb919)
  • help: shorten bb doctor's help, and stop bb api's repeating its flags (df544d5)
  • agents: give coverage artifacts and the gates a section each (b1f9bd4)
  • quickstart: say how to keep bb up to date (22685f4)
  • one example host and project across the pages (1b38b42)
  • contributing: make the rules CONTRIBUTING and AGENTS.md both state agree (693b942)
  • explain each topic on the page that owns it, and link from the rest (aafda60)
  • reference: one page for where every setting comes from (58032f1)
  • threat-model: say when the analysis was made, and what changed since (193eefe)
  • help: say what takes, and shorten bb ai mcp serve's help (e12c971)
  • help: describe --repo, --start and --host the same way wherever they mean the same (2a1f1c0)
  • help: say what each command group lets you do (3f40a81)
  • describe what is, where the docs told how it came to be (b914501)
  • skill: offer the MCP server when a view would serve the person better (e9d7212)
  • contributing: tell what is needed from what helps, and how a long branch lands (b433722)
  • say that the MCP server passes a file in a format the AI can ingest (a292dbd)
  • release: gather what administrators need, and show the views (ee5dd3a)
  • release: open the v5.0.0 notes with what is new, and cover the whole milestone (342a032)
  • correct what the docs say that is not so (ac666fd)
  • help: say what is, not what was, and document bb completion install (622e434)
  • help: show what an argument takes, and leave --yes to scripts (6a327df)
  • adr: say why bb has no browser login (4b60af1)
  • help: give every command an example (d3f87c2)
  • reference: give each top-level command a page, and each flag its source (44b64c3)
  • search: say that search prs lists what you are involved in (ff07218)
  • record that a value read from the checkout may stand in for its flag (c7601ab)
  • mcp: say when a tool and when a view, and how views work (ef2b86a)
  • mcp: describe the form as Bitbucket's create page (030402c)
  • adr: record where a card's builds come from, and letter case (29ae99e)
  • mcp: show comments in the overview and the diff, as Bitbucket does (0d78474)
  • mcp: show the views as they are now, and the form and the file viewer (d76326b)
  • adr: record what views are for, what is not refreshed, and sending without forms (272aa5b)
  • release-notes: note the plain-HTTP answer, HTML error titles and the User-Agent (320b865)
  • mcp: say that views keep themselves current (2748c5c)
  • mcp: show the comment threads view in the guide (ec57319)
  • mcp: point the MCP reference at the guide and its examples (ef59d63)
  • mcp: show the views in the MCP server's guide (d9b4dc4)
  • mcp: show the views in the docs and the README (38497f8)
  • mcp: frame ADR-101 as adopting MCP Apps (9921c7c)
  • mcp: say what the views show, how they stay safe, and why show is a tool of its own (bad25d9)
  • policy: give the levers as a table in the v5 notes (355cbfc)
  • policy: say what the three levers do, what they leave, and what they do not govern (4ffb8c8)
  • mcp: tell the story of attaching Bitbucket content in the v5 notes (ddde2a7)
  • mcp: say what attaching Bitbucket content means for a user, with an example (6a8c6b2)
  • adr: record how other MCP servers put resources in tool results (083deda)
  • mcp: say what the resources are for, what the scope does to them, and how they are audited (e2805d6)
  • mcp: say what the new permission model means for a user (b4257d0)
  • mcp: say what a confirmation holds a call to, and which tools were withheld (4b31bc0)
  • mcp: say which tools ask, and what --read-only is for (f51b299)
  • adr: let a record name every record that amends it (2163bbf)
  • describe: show the description document on the machine-mode page (9329b46)
  • release-notes: say where --describe's command and reason went (785c146)
  • dry-run: show the preview document, in the notes and on the machine-mode page (51ce8dc)
  • adr: accept ADR-096, now that --dry-run answers with a verdict (894d4b5)
  • adr: propose the v5 output contract for #606 and #616 (18f9fd1)
  • release: announce the deprecated bb update fields in the v5 notes (98427d9)
  • update: say what update_tuf_url has to point at (697fdc0)
  • adr: record ADR-094, MCP results a model can use without files or a shell (4f6fa74)
  • adr: record ADR-093, one downloader for binary and large bodies (6f628cc)
  • update: record that bb update installs the new binary itself (10c24a6)
  • release: add the bb bulk removal to the v5 upgrade checklist (f24f718)
  • dry-run: hold ADR-034 and ADR-070 to the registries that exist (635c934)
  • dry-run: say a command that changes this machine is previewed (bc9c302)
  • release: tell v5 upgraders that bb pr checks gates on CI (5d4e148)
  • webhook: drop the paragraph announcing the read-back (552d14f)
  • update: say what a dry run verifies, and when it fails (7c86dce)
  • adr: drop ADR-036's instruction for the bulk apiVersion (c19cf7f)
  • skill: make Cline's skill directory before writing the skill into it (4237461)
  • completion: say that bb doctor checks completion and the skill (3a27688)
  • completion: lead with bb completion install, and record who sets up what (e6565ce)
  • completion: say how to turn it on, and what to do when it offers nothing (f3f43d1)
  • adr: renumber the completion decision to 089 (4cd88ea)
  • completion: say where the shells differ (3c25154)
  • say what tab completion offers and how it behaves (79a9785)
  • docker: say again that releases run side by side (307a8ab)
  • openapi: point the fix registry at where a release difference is recorded instead (2d4fac1)
  • say which Bitbucket releases bb serves, and where an older one differs (a0e111c)
  • reviewer-group: say bb reviewer-group users lists only the members who can see the repository (d7305e2)
  • name v4.1.0 in the examples that show bb's version (88092f2)

Tests

  • cli: make the non-repository inference case reach git (a47b56d)
  • testsupport: seal the variables that say nobody is there (c4525eb)
  • cli: name the repository with --repo where a test passes --yes (00f8229)
  • cli: prove the default loaders without publishing BITBUCKET_URL (7b11d5c)
  • cli: keep tests inside the process and off the real stdout (67936a9)
  • cli: assert the failure each test is about, not one a missing host shares (df56959)
  • outcome: let the refused handshake's alert reach the client (2f4a1d8)
  • network: restore BB_BLOCK_EXTERNAL_NETWORK after TestSafeTransport (65afe52)
  • config: stop setting BB_DISABLE_STORED_CONFIG=1 where the seal has (b9b367b)
  • testsupport: anchor the seal detector on internal/config, not a count (89746a8)
  • testsupport: seal every variable bb reads (39872b7)
  • repo: pass configuration through the seams, not the environment (738550f)
  • api: pass configuration through the seams, not the environment (91c95d4)
  • auth: pass configuration through the seams, not the environment (3bd76d9)
  • browse: pass configuration through the seams, not the environment (919af87)
  • project: pass configuration through the seams, not the environment (0028d25)
  • insights: pass configuration through the seams, not the environment (63acbee)
  • pr: pass configuration through the seams, not the environment (061359e)
  • diff: pass configuration through the seams, not the environment (71e2af2)
  • commit: pass configuration through the seams, not the environment (18f1070)
  • branch: pass configuration through the seams, not the environment (7d3a406)
  • tag: pass configuration through the seams, not the environment (9a7c3e4)
  • bb: pass configuration through the seams, not the environment (3306f5d)
  • pullrequest: pass configuration through the seams, not the environment (c73ca0c)
  • config: pass configuration through the seams, not the environment (c549ba2)
  • config: drop clears the seal already makes (9b556bd)
  • cli: pass configuration through the seams, not the environment (c3a9a1e)
  • testsupport: keep a sealed test away from the developer's configuration (bee5323)
  • live: hold repo admin create, fork and delete to the canonical output (d341c47)
  • live: end the live TestMain in gittest.Guard (08a239d)
  • git: fail rather than skip without git, a checkout or a shell (04d57da)
  • quality: let the oldest release served be older than the oldest tested (3c55e2c)
  • live: run the search by state and period test on its own (9cd03c6)
  • hold the hand-written configuration and exit-code tables to the code (933ec75)
  • live: complete labels in a test that does not run in parallel (e5dc486)
  • webhook: expect the preview of a webhook already there to be no-op (fe57084)
  • mcp: prove the audit trail redacts what Bitbucket echoes back (6bc4d2a)
  • auth: cover setup-git with no configuration file to name (487bb8f)
  • config: run the host-credential cases away from any .env (8e86348)
  • keep every unit test binary off the network (8a63b92)
  • mcp: expect every kind a server shows among a view's offers (b2f7d1f)
  • mcp: number a comment on a line on the side Bitbucket numbers it (7b94bee)
  • mcp: give Chrome a minute to start in the browser tests (ff0c394)
  • mcp: cover the stand-in host's page outside a browser (9c6751f)
  • mcp: call show in the live conformance sweep (2767198)
  • live: wait for the rescope before reading the version a refused rebase keeps (5994850)
  • live: list what a read-only server exposes, and everything under --safe-only (b8e5e41)
  • git: every test that relies on git's own answer keeps the default timeout (3e06773)
  • describe: hold real documents to the schema --describe publishes (210877f)
  • live: read bb api's dry run of a mutation as a verdict (7e15dce)
  • live: prove each dry-run refusal against the real run (81d9df6)
  • live: read dry runs as verdicts, and hold each to its declared tier (bbdf9e2)
  • git: keep the backend's own timeout where git must succeed (380c257)
  • output: run the commands that change this machine before the others (1771194)
  • output: compare the hint's message, not the error value (1816c10)
  • update: update a bb built from this tree from a mirror of a published release (e6d81fb)
  • dry-run: point a local writer at the registry that previews it (ae17dcb)
  • live: keep the machine's shells and the checkout's skills out of the doctor test (dd2eb96)
  • live: read each push's own delivery in the webhook password test (9a82552)
  • skill: compare paths as macOS reports the working directory (9815421)
  • completion: install the .deb and .rpm and check where completion lands (a870df2)
  • completion: prove each shell completes from what install writes (8cc8115)
  • completion: drive bash, zsh, fish and PowerShell against the real scripts (fd2dced)
  • completion: stop the local-kind check reading this machine's config (c1f3414)
  • completion: hold the vocabulary at its edges (07e3508)
  • completion: cover the instances a machine is logged in to (788dbed)
  • completion: cover the failure paths, which are most of a source (8ee37a2)
  • usage: cover the placeholder the vocabulary is keyed by (78c8883)
  • completion: rename a git helper that shadowed the package (15d045c)
  • docs-lint: stop the fixture tests reading the machine's git tags (3da2aca)
  • compat: cover the narrowing and the scope reporting a newer release never reaches (b41a001)
  • live: run the oldest release and the newest by default, not the whole window (a7b185f)
  • live: send a seeding git push again when Bitbucket answers 5xx (b9e17c5)
  • live: prove bulk operations, paged listings and the git round trip store and return exactly what was sent (ad8abe2)
  • live: prove the flags alias, browse, clone and search commands send are the ones their answers reflect (df5e6c9)
  • live: prove the states dry-run predictions are read from were stored, and the changes they predict were not made (2973b2f)
  • live: prove every MCP write tool stores its arguments and every MCP read answers about what it named (921c94a)
  • live: prove withheld MCP tools change nothing, and MCP reviews, comments and scoped listings keep what was sent (76e55c5)
  • live: prove commit comments, build statuses, reports and a refused duplicate branch keep what was sent (c38f02b)
  • live: prove reviewer conditions, reviewer group renames and group grants keep what was sent (5783f23)
  • live: prove build statuses, code insights and required builds keep what was sent (e251f60)
  • live: prove webhook secrets, endpoint credentials and TLS settings are stored as sent (7f505b6)
  • live: prove a webhook create stores the name, url and events it sends (1138449)
  • live: prove webhook test pings the webhook and url it names (2527cdb)
  • live: prove policy-scoped listings and clones reach the project and repository they name (5b1332e)
  • live: prove an access token's name, permissions, expiry, rename and revocation are stored (fa85bc0)
  • live: prove a GPG key reaches Bitbucket intact and remove and clear take it away (865f766)
  • live: prove SSH key labels, key text and access key permissions are stored as sent (158ba8b)
  • live: prove a deployment keeps every field, and get and delete find only it (1b23e31)
  • live: prove a tag is made at its start point and keeps its message (d265b39)
  • live: prove build statuses and code insights keep what they are set with (619462a)
  • live: prove repo edit, archive and default tasks store what they send (8b6d831)
  • live: prove repo sync DISCARD makes the fork's master upstream's again (47bdc43)
  • live: prove webhook fields and granted permissions are stored, not just printed (9fc726d)
  • live: prove repository settings services store the permissions, webhooks and pull request settings they write (489599c)
  • live: prove repository create, rename, fork and delete by reading the repository back (37c7744)
  • live: prove repository auto-merge is stored, and gone after its delete (64267ef)
  • live: prove pr default-reviewers sends each repository id for its own side (13f7613)
  • live: prove governance writes are stored and their dry runs change nothing (ed4c895)
  • live: prove the code owners a pull request is given are the reviewers Bitbucket stores (d854945)
  • live: prove default reviewer conditions and the reviewers they assign are stored (e310769)
  • live: prove reviewer group members, names and descriptions are stored on both scopes (3159a8b)
  • live: prove the reviewer condition and reviewer group lifecycles keep what they send (c167247)
  • live: prove the pull requests the harness opens for the review tests come from the branch they name (21157f2)
  • live: prove the review tests open their pull requests with the title and branches they send (2a76384)
  • live: prove the overclaim fixture is one ordinary open comment and the partial tally reads zero tasks (b8f70da)
  • live: count the review visibility threads exactly and read back what each was created with (9961dfa)
  • live: prove the review surfaces are read from reviewers, comments and anchors stored as sent (0ee9bad)
  • live: prove a refused review completion leaves the status, the drafts and the comments as they were (d9ae5f5)
  • live: check the review status no-op under a token alone, and read back the reviewer and the token (7fbd57f)
  • live: prove pending reviews, reactions, replies, suggestions and blockers are stored as sent (e5281de)
  • live: prove branch restrictions are stored on the project or repository they were sent to (14467e0)
  • live: prove branch and branch restriction commands store what they send and dry runs change nothing (3e9a6c4)
  • live: prove project default tasks and branch restrictions store what bb sends (1dc4a7d)
  • live: prove project create, update, delete and the --name filter reach Bitbucket (d455792)
  • live: prove branch restrictions store the matcher type and exactly the exemptions sent (043ac65)
  • live: read back the diffs, build statuses, insights, tags, pull request filters and credentials the command coverage tests send (d1b6f92)
  • live: prove the pull requests comment tests open keep their title and branch (cde650c)
  • live: prove bb pr comment add keeps the line type and parent it is given (b739731)
  • live: prove repo comment anchors, limits, replies and commit comment versions are what Bitbucket keeps (9c40a8d)
  • live: prove comment text, severity, state, reactions and deletes are what Bitbucket keeps (7256229)
  • live: prove commit list, get, compare and ref resolve use the values they send (945dd68)
  • live: prove bb diff uses both refs it is given and the pull request it names (0f12495)
  • live: prove the draft flag, description and reviewer pr create sends before pr ready relies on them (57bb25b)
  • live: say why pr jira's empty answer cannot identify the pull request it read (aa95617)
  • live: prove auto-merge without --strategy merges no-ff by the commit it makes (5e76a6f)
  • live: prove pr status leaves out what others opened and what the caller already approved (3137c98)
  • live: state precisely why the activity and --state all listing checks can fail (384978e)
  • live: prove the read access pull request tests grant their reviewers is the access held (8c8cac6)
  • live: prove build statuses, pull request inspection and checkout against exact read-backs (227774f)
  • live: prove pr ready, auto-merge settings and the auto-merge strategy by reading them back (d891624)
  • live: prove pull request state changes, previews and listing filters by what reads back (98667a9)
  • live: prove pr create and pr update store the title, refs, description and reviewers they send (fa5b7de)
  • live: correct what two comments in the repo cli tests say (229b45d)
  • live: prove pr watch and unwatch change whether the pull request is watched (184161e)
  • live: prove pull request comments keep a removed or context line, and comment, activity and permission listings honour --limit (f53a3bb)
  • live: prove commit prs and participant search filter, and comment and rebase dry runs change nothing (ef045fe)
  • live: prove pull request dry runs preview changes a real run would make and leave them unmade (db97e3b)
  • live: prove repository permissions, webhooks and pull request settings store what bb sends (ac940b3)
  • live: prove repo comments store their text, anchor, parent and version, and repo list honours --project and --limit (615647d)
  • live: prove permissions show looks past a project named like the one asked about (b056e8d)
  • live: read back the pull request a refused comment update is aimed at (6757919)
  • live: prove each permission boundary with a licensed account and read back what it refused (a3febe8)
  • live: keep the refused reviewer-group delete proven when its subtest runs alone (90adfb4)
  • live: prove the version a pull request update names reaches Bitbucket (be43f1b)
  • live: prove the branch decoys fill the first page the existence check reads (ed9e5e5)
  • live: prove a rebase at a stale version is reported as a conflict (a2948cf)
  • live: prove every value the mutating coverage tests send is stored (3a5df77)
  • live: prove a build required only for the merge queue leaves pull requests mergeable (77cbecb)
  • live: point the auth status test at the instance under test (b98c057)
  • docs-lint: check the output-example fixtures against the release they name (8aacacc)

Build

  • error-registry: keep the registry beside the live suite that produces it (8756bce)
  • call the product Bitbucket Data Center in package metadata and the config schema (f495a04)
  • docs-lint: read a quoted message that begins with bb as a message (d86624d)
  • stack: prune only instances that have stopped (4037352)
  • docs-lint: leave a release's notes to the release they describe (ee21f71)
  • stack: take stopped instances down, so they give their network back (8228a9d)
  • release: set PowerShell completion and the agent skill up from Scoop (541eb3c)
  • release: install shell completion with the .deb, .rpm and Homebrew (7d752fc)
  • docs-lint: check a documented completion request against what it completes (bbf0238)
  • quality: hold the window of Bitbucket releases to what the code and the page say (8528fd8)
  • format the Go tree the same way under every gofmt release (b7a5d99)
  • record the participants operation the permission tests read approvals through (9b735ee)
  • stack: restart an instance for its licence's age from Git Bash on Windows too (dc2895f)
  • stack: run the stack and the live suite against another Bitbucket release (8d3ac72)

CI

  • release-flow: refuse every pull request into main (dd75ef3)
  • release: refuse a pushed commit CI has not passed (98a3906)

Chores

  • deps: Bump urllib3 in /docs in the uv group across 1 directory (c407602)
  • deps: Bump github.com/dlclark/regexp2/v2 (f76353b)
  • mcp: preview the form with drafted reviewers (d9c8179)
  • quality: count the pull request file diff the views now read (a122dab)
  • mcp: read a preview frame's kind without trusting its type (955f8e8)
  • mcp: preview the overview in place, and drive a preview from a script (1493d64)
  • mcp: preview some kinds only, and a long view whole (5fb51d3)
  • mcp: preview the pull request form, the file viewer and the views' buttons (50c3613)
  • deps: Bump the gomod-minor-patch group with 5 updates (2e716a3)
  • view-preview: capture each view alone, in either theme (02f21fc)
  • stack: serve https from Bitbucket itself, not from a proxy (a0a3b37)
  • stack: serve the instance over https for clients that open only https links (bd8dbb9)
  • view-preview: capture every frame from one steady layout (a5f8c09)
  • deps: Bump the gomod-minor-patch group with 2 updates (dab2170)
  • deps: Bump astral-sh/setup-uv from 10.1.0 to 10.2.0 (656bce6)
  • deps: Bump codecov/codecov-action from 7.0.0 to 7.1.1 (62b8d93)
  • deps: Bump the gomod-minor-patch group across 1 directory with 4 updates (862e1e9)
  • quality: record the operations the id completions reach (2bce854)
  • quality: record the commit-changes call the comment completion makes (d8350ab)
  • quality: record the browse endpoint the path completion reaches (919f16a)
  • deps: Bump actions/attest from 4.1.0 to 4.2.2 (eb5c096)

Other

  • mcp: gofmt the pull request form and the live view tests (52c08af)
  • gofmt bb api's imports (d3813a8)
  • release: space the Homebrew formula's base_url assignment (0804d88)
  • completion: drop two conversions of a type that is already a string (b268b8a)
  • cli: drop a blank line the refactor left (7e2a9c1)