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_SESSIONfor 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
.bashrcis 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?