Configuration¶
bj follows the same split the GitHub CLI uses: non-sensitive settings live in a
YAML file; secrets (API tokens) go to the OS keyring.
bj works with Bitbucket Cloud and Jira Cloud. Bitbucket and Jira Server or Data
Center are not supported yet.
Location¶
The config directory is $BJ_CONFIG_DIR, else $XDG_CONFIG_HOME/bitbucket-jira-cli,
else ~/.config/bitbucket-jira-cli. Files are written with 0600 permissions.
config.yml: non-sensitive settings (below).credentials.yml: only present if you logged in with--insecure-storage.
config.yml¶
Written by bj auth login (the bitbucket.email,
jira.site and jira.email fields) and
bj repo set-default (the default
bitbucket.workspace); you can also edit it by hand. Inside a Bitbucket clone
the workspace is read from the origin remote, so setting a default is only
needed for commands run outside a clone (like bj repo list).
version: 1
git_protocol: https # https | ssh, used by `bj repo clone`
bitbucket:
workspace: myteam # default workspace when not in a clone
email: you@example.com # Atlassian account email (basic auth)
auth_mode: basic # basic (email:token) | bearer (access token)
jira:
site: https://your-domain.atlassian.net
email: you@example.com
auth_mode: site # site (unscoped) | gateway (scoped API token)
cloud_id: null # set automatically in gateway mode
branch_key:
enabled: true
pattern: ([A-Za-z][A-Za-z0-9]+-\d+)
project_prefixes: [] # e.g. [PROJ, ABC] to ignore stray matches
transitions:
on_pr_create: In Progress # ticket state after `bj pr create`
on_pr_merge: Done # ticket state after `bj pr merge`
Token storage¶
bj never writes tokens to config.yml. At read time it resolves each backend's
token in this order:
- Environment variable (
BJ_BITBUCKET_TOKEN/BJ_JIRA_TOKEN), never persisted. - The OS keyring (service
bitbucket-jira-cli). credentials.yml(only if--insecure-storagewas used).
Bitbucket and Jira use separate tokens; a token for one will not authenticate
the other. See Environment for the full variable list and
bj auth for the login flow.
Tokens¶
Both tokens are created at id.atlassian.com.
Bitbucket scoped API token¶
Use "Create API token with scopes", app Bitbucket. For full command coverage, grant all of these (Bitbucket's granular scopes do not imply each other, so tick every box you want):
read:user:bitbucket: the current-user checkbj auth loginrunsread:workspace:bitbucket: list workspace members (reviewer selection)read:repository:bitbucket,write:repository:bitbucket,admin:repository:bitbucket,delete:repository:bitbucketread:pullrequest:bitbucket,write:pullrequest:bitbucketread:pipeline:bitbucket,write:pipeline:bitbucket,admin:pipeline:bitbucketread:ssh-key:bitbucket,write:ssh-key:bitbucket,delete:ssh-key:bitbucketread:snippet:bitbucket,write:snippet:bitbucket,delete:snippet:bitbucket
Which scope each command family needs:
| Commands | Scope |
|---|---|
| everyday reads, PRs, clone | read:*, read/write:pullrequest, read:repository |
repo create / edit / rename / fork |
write:repository:bitbucket |
ruleset list (branch restrictions) |
admin:repository:bitbucket |
repo delete |
delete:repository:bitbucket |
variable (pipeline variables) |
admin:pipeline:bitbucket |
ssh-key add / repo deploy-key add |
write:ssh-key:bitbucket |
ssh-key delete / deploy-key delete |
delete:ssh-key:bitbucket |
snippet list / view |
read:snippet:bitbucket |
snippet create |
write:snippet:bitbucket |
snippet delete |
delete:snippet:bitbucket |
The delete:* and admin:* scopes are separate on purpose: a token with only
write:repository:bitbucket can create and edit repos but not delete them.
Jira: two token modes¶
bj auth login asks which you're using:
- Unscoped (simplest): the plain "Create API token" button (no scope
selection).
bjsends it as Basic auth (email + token) against your*.atlassian.netsite host, like thejiraandgo-jiraCLIs. This becomesjira.auth_mode: siteinconfig.yml. - Scoped (least privilege): "Create API token with scopes", app
Jira, scopes
read:jira-work,write:jira-work,read:jira-user, andmanage:jira-project. Scoped Jira tokens are only accepted on Atlassian'sapi.atlassian.com/ex/jira/{cloudId}gateway (they 401 against the site host), sobjresolves your site's cloudId from{site}/_edge/tenant_infoat login, stores it asjira.cloud_id, and targets the gateway. This becomesjira.auth_mode: gateway.
write:jira-work covers issue create/edit, comments, transitions and remote
issue links; read:jira-work covers search and reads; read:jira-user covers
the current-user check; manage:jira-project covers bj release (Jira
versions). Write does not imply read, so grant both.
bj board (agile boards/sprints) is the one exception: Atlassian rejects scoped
API tokens on the Jira agile API ("Unauthorized; scope does not match"),
regardless of which agile scopes you tick. It works only with an unscoped
Jira token (jira.auth_mode: site), which is not scope-limited. Verified
against a scoped token carrying read:board-scope:jira-software,
read:sprint:jira-software, and read:project:jira — still rejected.