Bitwarden CLI automation: session keys, unlock, and scripts

The Bitwarden CLI (bw) is the standard way to get vault items into scripts, CI pipelines, and agent workflows. It is also interactive by default: every call wants a master password unless you give it a session key. Automation therefore has one real problem to solve — unlock — and every script you write is shaped by how you solve it. Get unlock wrong and you get hangs, leaked keys, and jobs that fail at 3am. Get it right and bw get becomes as boring as any other command.

How the session model works

Unlocking the CLI decrypts the vault and returns a session key. That key is a bearer credential: any call that carries it can read the vault until the session expires. You pass it through the BW_SESSION environment variable. The rule that matters for automation: the session key belongs in the environment, never in arguments, because command lines are visible to other processes, to process supervisors, and to anything that logs invocations.

Unlocking non-interactively

For a human at a terminal, bw unlock prompts for the master password and that is fine. For automation, three patterns work:

  • Use a service identity where possible. Log in with API credentials scoped to the application instead of a human’s master password, so the automation has its own identity and its own rotation lifecycle.
  • Unlock once, reuse for the job. Capture the session key from the unlock step, hold it in a 0600 file or a variable scoped to the run, and export BW_SESSION for the duration of the job — never per command.
  • Treat the key as short-lived. Sessions expire, so the unlock step belongs inside the job, not in a shell profile. A session key sitting in .bashrc is a standing credential nobody remembers to revoke.

Keep the key out of shell history: prefer reading it from a file or resolving it inside the script over typing the unlock command into an interactive shell.

Scripts that fail closed

The failure mode that breaks automation is the interactive prompt. An expired session makes the CLI ask for a password, the script blocks, the job times out, and the log shows nothing useful. The fix is to treat an invalid session as an error:

  • Check the exit status of the unlock step.
  • Bail out with a clear message — “re-unlock required” — instead of letting the process hang.
  • Never fall back to interactive prompting in an unattended context. A cron job or agent cannot answer a password prompt, and surfacing one in a log file is how master passwords end up in the wrong place.

Fail-closed behavior also gives you a signal: failed unlocks become visible events you can alert on, instead of mysteries you discover after the deadline.

The pattern for scripts and agents

The durable pattern is the same everywhere: unlock with a dedicated identity, carry the session key only in the environment of the consuming process, expire it with the job, and make failures loud. The difference with AI agents is amplification — agent output gets logged, replayed, and pasted, so a leaked session key travels further than it would in a human’s terminal.

trustless, a credential broker CLI for AI agents, follows exactly this pattern for its Bitwarden backend: the session key is read from the BW_SESSION environment variable only, never from arguments, and an invalid session fails closed instead of prompting. Details are in the architecture page.

Which of your scripts would hang — instead of failing loudly — the next time its session expires?