BWS is a separate Bitwarden product from the vault. It exists for the values that need to flow into a tool — without ever sitting on disk in plaintext.
What BWS is — and what it isn’t
BWS (Bitwarden Secrets Manager) is the programmatic-access cousin of the Bitwarden vault. Different product, different storage tier, different access path. Values in BWS are reachable by a service account; values in the Bitwarden vault are not. The local pattern uses BWS as a bridge: a Python helper fetches the BWS access token from the macOS Keychain (never from disk), uses it to callbws secret get, and returns a value to a caller — typically a launcher script for an AI tool that needs an OAuth token.
Why we use it (alongside Doppler)
Doppler is the canonical home for AI provider keys. BWS shows up when:- An OAuth token is issued by a provider that doesn’t fit cleanly into Doppler’s config-injection model (e.g.
CLAUDE_CODE_OAUTH_TOKENfor a session-bound credential). - A token must be fetchable by a local script outside any CI context.
- The team wants a Bitwarden-managed audit log for AI credentials, not just a Doppler audit log.
The bridge pattern
1
Read references from disk
bws_helper.py loads ~/.config/bws/.env — BWS secret IDs and keychain references only. No values here.2
Fetch the BWS access token from the keychain
security find-generic-password retrieves BWS_ACCESS_TOKEN from the automation-tier keychain. The token never reaches disk.3
Call BWS
bws secret get <id> returns the value into helper memory.4
Pipe straight into the child process
The value goes directly into the requesting subprocess’s env. It never touches the parent shell, shell history, or disk.
Config shape
.env:
- The file contains references, not values. Secret IDs are not secrets.
- The BWS access token itself is in the keychain, fetched at runtime — never inlined here.
- The file is gitignored at the dotfiles level. Even with references-only, no advantage to sharing it.
The Python helper
bws_helper.py does three things:
load_env()— reads the~/.config/bws/.envfor secret IDs and keychain refs.get_bws_token()— callssecurity find-generic-password(allowed read-only by Claude Code) to fetch the BWS access token from the automation-tier keychain.get_secret(name)— callsbws secret getand returns the value to the caller.
Best practices
- Treat the BWS access token like any other automation-tier credential: 90-day rotation, automation keychain only.
- Use BWS only for AI-specific tokens. Long-term plan: as Doppler matures coverage of these cases, BWS shrinks.
- Audit: enable BWS access logging in Bitwarden’s web console. Review on every rotation.
- Never echo
get_secret()output to stdout for debugging. Use a tracer that masks values by length.
Status
The helper is local-dev tooling, invoked directly from the Python module referenced above rather than distributed as a packaged overlay.See also
- Bitwarden vault — the human-only sibling product. Not interchangeable with BWS.
- Doppler — preferred for AI provider keys where it fits.
- macOS Keychain — where the BWS access token actually lives.
- Local AI isolation — the subprocess-scoping guarantee that lets BWS bridge values into a claude session safely.