npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mgcrea/bitbucket-cli

v0.5.0

Published

A Bitbucket equivalent of GitHub's gh — a typed Bitbucket Cloud client and the `bb` CLI

Readme

@mgcrea/bitbucket-cli

bb — a Bitbucket CLI in the shape of GitHub's gh, plus the typed Bitbucket Cloud client it is built on.

$ bb pr list
ID  TITLE                     BRANCH             STATE
42  Add OAuth support         feature/oauth      OPEN
39  Cache workspace lookups   perf/ws-cache      OPEN
12  Fix pagination edge case  fix/pagination     MERGED

Why this exists

Atlassian ships a first-party CLI, acli, and it covers Jira but not Bitbucket. The TypeScript ecosystem has no maintained Bitbucket CLI either. Three things here that the alternatives don't have:

Server-side field projection. Bitbucket's fields= parameter lets the server do the projection, so bb repo list --json fullName,isPrivate asks for two fields and gets two fields. gh structurally cannot do this — GitHub's REST API has no partial-response parameter, so it fetches whole objects and throws most of them away client-side. Measured against a real workspace, listing 50 repositories:

| | bytes over the wire | |---|---| | unprojected | 162,330 | | --json fullName,isPrivate | 3,683 |

44x less data, identical output.

--jq and --template with gh's helper set, and no jq binary required.

An importable typed client — something a Go binary cannot offer.

Install

Not published yet. To run the working tree:

pnpm install
make install          # builds, then symlinks `bb` onto your PATH

make uninstall removes it, make link-status shows where bb resolves. See Development for details.

Getting started

bb auth login

Prompts for everything, including the part that trips people up — Bitbucket needs an API token created with scopes, not the classic unscoped kind. For CI, pipe it:

bb auth login --with-token --email [email protected] < token.txt
# or skip storage entirely and just set BB_TOKEN + BB_EMAIL

Then:

bb workspace list                 # which workspaces your token can reach
bb repo list -W acme
bb pr list
bb pr view 42
bb pr diff 42 --patch | git apply
bb pipeline list

Working on a branch:

bb pr create --fill               # title and body from your commits
bb pr checkout 42                 # cross-fork pull requests too
bb pr review --approve
bb pr merge --squash --delete-branch
bb pr status                      # yours, and the ones awaiting your review

bb repo clone hands git a credential per operation through bb auth git-credential, so your token never ends up in .git/config or a remote URL the way it does when you clone https://user:[email protected]/….

Commands that take a pull-request number default to the one for the current branch, so bb pr merge usually needs no argument.

Commands

| | | |---|---| | bb auth | login · logout · status | | bb pr | list · view · diff · status · create · checkout · merge · close · ready · review · comment | | bb repo | list · view · clone | | bb workspace | list | | bb pipeline | list · view · log · run · stop | | bb browse | open the repo, a pull request, a file or the pipelines page | | bb alias | set · list · delete | | bb config | get · set · list | | bb completion | bash · zsh · fish · powershell | | bb api | any endpoint, with --paginate / --flatten |

Everything not wrapped yet is reachable through bb api:

bb api /repositories/{workspace}/{repo}/pullrequests --paginate --flatten
bb api /user --jq .display_name

{workspace} and {repo} resolve from your git remote.

Output

Every list command speaks four formats, and piped output is TSV — no header, no padding, no colour, no truncation — so it composes with ordinary shell tools:

bb pr list | awk -F'\t' '{print $1}'                   # just the ids
bb pr list --json                                       # discover the field names
bb pr list --json id,title --jq '.[] | "\(.id) \(.title)"'    # a list is an array
bb pr view 42 --json title --jq .title                    # a view is an object
bb pr list --template '{{range .}}{{tablerow .id .title}}{{end}}{{tablerender}}'

--jq runs real jq 1.8.2 compiled to WebAssembly, loaded only when you use it. --template implements a subset of Go's text/template with gh's helpers — tablerow, tablerender, timeago, truncate, color, autocolor, hyperlink, join, pluck, timefmt, plus the usual builtins — so existing gh --template snippets paste in and work.

--jq and --template imply --json, so you rarely need both.

As a library

import { createBitbucketClient } from "@mgcrea/bitbucket-cli";

const bb = createBitbucketClient();

for await (const pr of bb.pullRequests.list({ workspace: "acme", repository: "api", limit: 20 })) {
  console.log(pr.id, pr.title);
}

Resources return async iterables, so break genuinely stops the HTTP chain — limit: 5 costs one request, not forty. Auth, retry with jitter, rate-limit parsing and the two pagination envelope shapes are all handled underneath.

Environment

| | | |---|---| | BB_TOKEN BB_EMAIL BB_TOKEN_TYPE | credential; always wins over stored, never written to disk | | BB_ACCESS_TOKEN | repository/project/workspace access token | | BB_REPO BB_WORKSPACE | override the git-remote inference | | BB_CONFIG_DIR BB_API_BASE_URL | config location, API root | | BB_DEBUG=api | request tracing on stderr | | BB_FORCE_TTY NO_COLOR | force or suppress terminal rendering |

BITBUCKET_* works as an alias throughout. Because an environment credential is never persisted, CI needs no setup step.

Three things that will surprise you

There is no bb pr reopen. Declining a pull request is final as far as the API is concerned — Bitbucket Cloud exposes no reopen endpoint (Data Center does). bb pr close therefore always asks for confirmation.

There is no bb issue. Atlassian removed the Bitbucket issue tracker API — the endpoints return HTTP 410 and the schema is gone from the published OpenAPI spec. There is no replacement short of Jira. bb issue exists only to say so, because "unknown command" would send you hunting for a flag you didn't get wrong.

App passwords are gone (removed 28 July 2026). Use an Atlassian API token created at id.atlassian.com via "Create API token with scopes", selecting Bitbucket as the app. A plain unscoped token authenticates but every Bitbucket call fails with "API Token provided has no Bitbucket scopes". Bitbucket also has no device-code grant, so there is no browser-based login on a headless box — pasting a token is the path.

Every listing is workspace-scoped. GET /workspaces and the cross-workspace GET /repositories were both removed under CHANGE-2770, which is why bb repo list needs a workspace — from -W, BB_WORKSPACE, your clone, or default_workspace — and why bb workspace list exists at all.

Also worth knowing: repository, project and workspace access tokens are not tied to an Atlassian account, so GET /user fails for them. bb detects that before making a request and tells you which commands are unavailable instead of surfacing a bare 401.

Credential storage

Credentials live in ~/.config/bb/hosts.yml at mode 0600, written atomically — the same as gh. Plainly: that keeps the token out of a screenshare and out of a dotfile sync, and does nothing against a local attacker. An "encrypted" file whose key is derivable on the same machine is obfuscation dressed as security, so this doesn't ship one. OS keychain support is planned as an opt-in, and will be described just as honestly.

Development

pnpm install
pnpm run test     # lint && check && spec && format:check
pnpm run build

Running the working tree as bb

make install      # build, then symlink dist/bin/cli.cjs onto your PATH
make link-status  # show where `bb` currently resolves
make uninstall    # remove the symlink

pnpm run install:local does the same without make. The link points at dist/bin/cli.cjs, so pnpm run build alone picks up a change — no relink. It installs to $(npm prefix -g)/bin, because pnpm's global bin directory is often missing from PATH until pnpm setup has been run. Override with make install BIN_DIR=~/.local/bin.

install refuses to overwrite anything that isn't a symlink, and uninstall refuses to remove a symlink pointing outside this checkout.

Releasing

release-it bumps the version, cuts the tag and creates the GitHub release locally; pushing the tag triggers .github/workflows/release.yml, which runs the gate again and publishes to npm with provenance.

pnpm run release

Publishing authenticates by OIDC trusted publishing, so no long-lived token sits in the repository. npm cannot configure trusted publishing for a package that does not exist yet, so the very first version of a new package needs one of:

# either: publish once by hand, then wire up trust
npm publish --access public --provenance=false
npm trust github @scope/name --file .github/workflows/release.yml --repo owner/name --allow-publish

# or: set an NPM_TOKEN repository secret, which the workflow uses as a fallback

Once trusted publishing is configured, remove the NPM_TOKEN secret — the workflow prefers it when present, and OIDC is the better credential.

Generated types

pnpm run generate:types regenerates src/generated/openapi.ts from Atlassian's published spec. The output is committed so CI never hits the network, and drift is checked on a weekly cron rather than in PR CI — an upstream edit shouldn't redden an unrelated pull request.

Only components.schemas is generated. The spec under-declares query parameters (GET /pullrequests omits q, sort, fields, page and pagelen), so a paths-typed client would reject correct code.

Shortcuts

bb alias set prs 'pr list --state open --limit 50'
bb alias set v 'pr view $1 --json url'      # $1..$9 and $@ are substituted
bb alias set --shell bugs '!bb pr list --json title | grep -i bug'

A built-in always wins, so an alias can never shadow bb pr.

Settings

bb config list                            # every setting, set or not
bb config set default_workspace acme
bb config set git_protocol ssh
bb config set default_workspace ''         # empty unsets

default_workspace is the last resort for bb repo list, behind the --workspace flag, BB_WORKSPACE, and the workspace of the clone you are standing in. Inference beats it deliberately: inside a clone of acme/api, listing should show acme and not whatever default you set months ago.

The key set is closed, so bb config set defualt_workspace acme is an error rather than a line in a file that never gets read.

Shell completion

eval "$(bb completion -s zsh)"      # or bash
bb completion -s fish | source

Generated from the same command tree that dispatches, so it cannot drift.

Not there yet

extensions · OAuth login · Data Center support.

The client is designed behind a resource-level flavor interface so Data Center can be added without a rewrite, but only Bitbucket Cloud is implemented.

License

MIT