// DevOps

Bitwarden CLI: Managing passwords from the terminal and automating CI/CD

Published on 2026-09-22

Bitwarden CLI — the official command-line utility bw for working with a Bitwarden vault: find a password in the terminal, get a secret in a script, pass it to a CI/CD pipeline. The code is open-source, the utility is free and works with Bitwarden cloud as well as a self-hosted server, including Vaultwarden.

Below — installation, login, main commands and a ready-made CI template. If you don’t have your own server yet, start with the article Vaultwarden in 30 minutes; about choosing a password manager for a company — in the series “Password Managers”.

1. Installation

According to Bitwarden documentation there are several methods:

bash
# npm (any OS; Bitwarden calls this the easiest way to update)
npm install -g @bitwarden/cli

# Snap (Linux)
sudo snap install bw

# Chocolatey (Windows)
choco install bitwarden-cli

# Homebrew (macOS and Linux)
brew install bitwarden-cli

In addition, bitwarden.com publishes ready binaries for Windows, macOS and Linux (x64). You need to place the file in a directory in your PATH, otherwise you’ll have to run commands from the directory containing it. When installing via npm on Linux you may need the build-essential package.

Check:

bash
bw --version

2. Connecting to your server

By default the CLI works with Bitwarden cloud. For a self-hosted server — Vaultwarden or self-hosted Bitwarden — specify the address before login:

bash
bw config server https://vault.example.ru

For Bitwarden European cloud the address is https://vault.bitwarden.eu. If the server services are split across different addresses, the command has separate parameters: --web-vault, --api, --identity and others.

Vaultwarden implements the Bitwarden client API, including a personal API key, so everything described below works with it.

3. Login

Interactive login

bash
bw login

The utility will ask for an email address, master password and, if enabled, two-factor authentication. For organizations with single sign-on use bw login --sso.

Login with API key

For scripts and CI interactive login is not suitable. The personal API key is taken from the web interface: Settings → Security → Keys. It consists of a client_id like user.xxxx and a client_secret.

bash
export BW_CLIENTID="user.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
export BW_CLIENTSECRET="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

bw login --apikey

Important: the API key does not replace the master password. It only authorizes on the server; to decrypt the vault you still need bw unlock. If the key is compromised, it can be reissued — the old key and all sessions opened with it will be invalidated.

4. Unlocking and BW_SESSION

After login the vault data is still encrypted. It is decrypted by the command:

bash
bw unlock

It outputs a session key in the form of the command export BW_SESSION="...". While the BW_SESSION variable is set, bw decrypts data without asking the master password again. The key can also be passed to a single command with the --session flag.

In scripts the master password is taken from an environment variable or a file, and the session key is obtained in one line:

bash
# password in an environment variable
export BW_SESSION=$(bw unlock --passwordenv BW_PASSWORD --raw)

# or in a file (first line is read)
export BW_SESSION=$(bw unlock --passwordfile /run/secrets/bw_master --raw)

The password file must be accessible only to the user who runs bw unlock. The session key is valid until bw lock or bw logout and is not carried over to a new terminal window.

Check current status — whether you are logged in and the vault is unlocked:

bash
bw status

5. Main commands

TaskCommand
Download fresh data from the serverbw sync
Search for itemsbw list items --search "github"
Items in a folder, collection, organizationbw list items --folderid <ID> (--collectionid, --organizationid)
Passwordbw get password "github"
Usernamebw get username "github"
TOTP codebw get totp "github"
Notebw get notes <ID>
Entire item (JSON)bw get item <ID>
Attachmentbw get attachment <filename> --itemid <ID> --output ./
Generate a passwordbw generate --length 24 -uln --special
End sessionbw lock or bw logout

A few practical notes:

  • bw sync only downloads data from the server. Changes made via the CLI are sent to the server immediately. If a password was changed in the browser but the script sees the old one — run bw sync.
  • bw get accepts an ID or a search string. In interactive use a search is convenient, but in scripts IDs are more reliable: the string may match the wrong item or several items at once.
  • Output is JSON, it’s convenient to parse with jq:
bash
bw list items --search "github" | jq -r '.[] | "\(.id)  \(.name)"'

Copy password to clipboard on Linux:

bash
bw get password github | xclip -selection clipboard

6. CI/CD script template

It’s better to create a separate account for CI with access only to the needed items, for example to one organization collection. BW_CLIENTID, BW_CLIENTSECRET and BW_PASSWORD are stored in protected CI variables, not in the repository.

bash
#!/usr/bin/env bash
set -euo pipefail

# 1. Server address (before login)
bw config server https://vault.example.ru

# 2. Login with API key: BW_CLIENTID and BW_CLIENTSECRET come from CI variables
bw login --apikey

# 3. Unlock: master password comes from BW_PASSWORD variable
export BW_SESSION=$(bw unlock --passwordenv BW_PASSWORD --raw)

# 4. Secret by item ID (ID obtained in advance: bw list items --search "my-db")
DB_PASS=$(bw get item "8a562df1-443b-4892-baee-b123456789ab" | jq -r '.login.password')

# 5. Use the secret without printing it to the log
./deploy.sh

# 6. End session
bw logout

In GitHub Actions the value obtained in the step should be masked immediately with the command echo "::add-mask::$DB_PASS" — then it will not appear in the build log even if it ends up in output.

7. Bitwarden Secrets Manager and the bws utility

Bitwarden has a separate product for infrastructure secrets — Secrets Manager with its own CLI bws and its own pricing. In it secrets are grouped into projects, and access is granted to machine accounts by an access token, without a master password:

bash
export BWS_ACCESS_TOKEN="..."
bws secret list
bws secret get <SECRET_ID>
bws run -- ./deploy.sh   # run a command with secrets in environment variables

Vaultwarden does not list Secrets Manager among its features, so for a self-hosted Vaultwarden server use bw as described above.

Security guidelines

  1. Do not store BW_SESSION on disk and do not print it to logs — keep it only in process memory.
  2. End the session with bw lock or bw logout at the end of the script.
  3. Mask secrets in CI and do not pass them as command-line arguments: arguments are visible in the process list.
  4. Limit access. The CI account should have access only to the secrets required by the pipeline.

How to prevent leaking keys from a repository and what to do if a leak has already occurred — in the Secure Development series article “Secrets in code”.

// Reviews

Related reviews

I came with an expensive request to configure a VPS server, but during the consultation Mikhail suggested a much simpler, more affordable solution. In the end I saved time and money. Mikhail — a true expert who works for the client's result, not for the fee. I recommend him!

I came with an expensive request to configure a VPS server, but during the consultation Mikhail suggested a much simpler and more cost-effective solution. In the end I saved budget and time. Mikhail — a true expert who …

kfhzasorin

VPS setup, server setup

2026-05-12 · ★ 5/5

// Contact

Need help?

Get in touch with me and I'll help solve the problem

I reply within one business day (03:00-13:00 GMT)

Или оставьте заявку здесь:

Confirm that you are not a bot.

Write and get a quick reply