Auto-Loading Bitwarden Secrets as Environment Variables in Zsh
This post showcases a Zsh script that auto-refreshes Bitwarden sessions and exports secrets as environment variables.
Usage
- Save the script as
~/.oh-my-zsh/custom/bw-session.zsh
. - Ensure
bitwarden-cli
,jq
, and the macOSsecurity
utility are installed. - Adjust
BW_ENV_MAPPING
for eachENV_VAR → "item-id#selector"
. - set_secrets when you need tokens
Final Script
# ~/.oh-my-zsh/custom/bw-session.zsh
# ——————————————————————————————————————————————
set +x
emulate -L zsh
### CONFIGURATION ###
: "${BW_KEYCHAIN_SERVICE:=bitwarden-master}" # your master-pwd keychain entry
: "${BW_EMAIL:=you@example.com}"
# ENV_VAR → "item-id#selector" (notes|password|username|totp|field:<name>)
typeset -A BW_ENV_MAPPING=(
GREENPT_API_KEY "fc92e0c4-2b60-452a-8fb9-b3090150ae86#notes"
SUPADATA_API_KEY "c0e2a7b0-444b-4d97-a05b-b32b014f216d#notes"
)
### SESSION MANAGEMENT (in-memory only) ###
_bw_read_master() {
security find-generic-password -s "$BW_KEYCHAIN_SERVICE" -w 2>/dev/null
}
_bw_setup_session() {
# if already set and works, reuse
if [[ -n $BW_SESSION ]]; then # && bw get item "${(k)BW_ENV_MAPPING}[1]" --session "$BW_SESSION" &>/dev/null; then
return 0
fi
# fetch master password
local _pw; _pw=$(_bw_read_master) || return 1
# unlock (or login if first time)
if [[ "$(bw status --raw)" == *\"locked\"* ]]; then
BW_SESSION=$(env BW_MASTER="$_pw" \
bw unlock --passwordenv BW_MASTER --raw) || return 1
else
BW_SESSION=$(env BW_MASTER="$_pw" \
bw login "$BW_EMAIL" \
--passwordenv BW_MASTER --raw) || return 1
fi
unset _pw
export BW_SESSION
bw sync --session "$BW_SESSION" &>/dev/null || true
}
### FETCH & EXPORT ###
_bw_fetch_and_export() {
local var spec item sel json val
for var in "${(@k)BW_ENV_MAPPING}"; do
spec=${BW_ENV_MAPPING[$var]}
item=${spec%%#*}; sel=${spec#*#}
json=$(bw get item "$item" --session "$BW_SESSION")
case $sel in
notes) val=$(print -r -- "$json" | jq -r .notes) ;;
password) val=$(print -r -- "$json" | jq -r .login.password) ;;
username) val=$(print -r -- "$json" | jq -r .login.username) ;;
totp) val=$(bw get totp "$item" --session "$BW_SESSION") ;;
field:*) val=$(print -r -- "$json" \
| jq -r --arg n "${sel#field:}" \
'(.fields//[] | select(.name==$n) | .value)') ;;
esac
[[ -n $val ]] && export "$var=$val"
done
}
function set_secrets() {
_bw_setup_session && _bw_fetch_and_export
}