secrets: rename the vault helpers from env* to op*

They act on 1Password, not on the environment, so the prefix now says so:
opr (read), opc (create/update), opd (delete), opl (list), ops (refresh).
No behavior change. Checked the new names don't collide with any command
or oh-my-zsh alias, and verified opr/opl/ops against the real vault
(values compared, not printed).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-17 16:36:20 +00:00
co-authored by Claude Opus 5
parent c6e5f22acb
commit 1159197e4b
4 changed files with 34 additions and 34 deletions
+5 -5
View File
@@ -61,11 +61,11 @@ Already have a clone? Just run it directly:
The first run prompts for the service-account token (and vault/item), and The first run prompts for the service-account token (and vault/item), and
keeps them in `~/.config/dotfiles/op.env` (0600, not loaded into shells). keeps them in `~/.config/dotfiles/op.env` (0600, not loaded into shells).
Runs after `bin/` (needs `op` and `jq`); bootstrap loads the result so later Runs after `bin/` (needs `op` and `jq`); bootstrap loads the result so later
modules get the keys without prompting. Day to day: `envr NAME` reads a modules get the keys without prompting. Day to day: `opr NAME` reads a
field, `envc NAME [VALUE]` creates or updates one (prompts, hidden, without field, `opc NAME [VALUE]` creates or updates one (prompts, hidden, without
VALUE), `envd NAME` deletes one; both of those refresh the file and this VALUE), `opd NAME` deletes one; both of those refresh the file and this
shell. `envl [VAULT [ITEM]]` shows every field with its current value, and shell. `opl [VAULT [ITEM]]` shows every field with its current value, and
`envs` refreshes after a change made elsewhere. No sudo. `ops` refreshes after a change made elsewhere. No sudo.
opencode is configured by `mcp-config/`: it points at the covert-gpt opencode is configured by `mcp-config/`: it points at the covert-gpt
LiteLLM gateway (`https://llm.covert-gpt.com/v1`) for models. MCP tools do LiteLLM gateway (`https://llm.covert-gpt.com/v1`) for models. MCP tools do
+4 -4
View File
@@ -6,19 +6,19 @@
# field on EVERY new shell. That made each terminal wait on 1Password, broke # field on EVERY new shell. That made each terminal wait on 1Password, broke
# every shell when the network or the service account was down, and meant each # every shell when the network or the service account was down, and meant each
# box carried its own hand-written copy of the loop. Now the vault is read once # box carried its own hand-written copy of the loop. Now the vault is read once
# here (at bootstrap, or on demand with `envs`), and shells read a local file. # here (at bootstrap, or on demand with `ops`), and shells read a local file.
# #
# Layout: one vault per user (default: the login name), holding one item # Layout: one vault per user (default: the login name), holding one item
# (default: also the login name) whose field LABELS are the variable names — # (default: also the login name) whose field LABELS are the variable names —
# GITEA_KEY, LITELLM_KEY, PROXMOX_TOKEN_SECRET, ... Every such field is # GITEA_KEY, LITELLM_KEY, PROXMOX_TOKEN_SECRET, ... Every such field is
# exported. Add a secret by adding a field (`envc NAME`), not by editing # exported. Add a secret by adding a field (`opc NAME`), not by editing
# this repo. # this repo.
# #
# Files, all under ~/.config/dotfiles (0700), none in the repo: # Files, all under ~/.config/dotfiles (0700), none in the repo:
# op.env OP_SERVICE_ACCOUNT_TOKEN, OP_VAULT, OP_ITEM (0600). Kept so a # op.env OP_SERVICE_ACCOUNT_TOKEN, OP_VAULT, OP_ITEM (0600). Kept so a
# refresh needs no prompt. Deliberately NOT sourced by shells: # refresh needs no prompt. Deliberately NOT sourced by shells:
# the token stays out of every process's environment, and only # the token stays out of every process's environment, and only
# the env* helpers in zsh/zshrc load it, in a subshell. # the op* helpers in zsh/zshrc load it, in a subshell.
# secrets.env the exported fields (0600), replaced atomically, so a failed # secrets.env the exported fields (0600), replaced atomically, so a failed
# fetch leaves the previous copy in place. # fetch leaves the previous copy in place.
# #
@@ -115,7 +115,7 @@ _tmp="$(mktemp "$CONF_DIR/secrets.env.XXXXXX")"
trap 'rm -f "$_tmp"' EXIT trap 'rm -f "$_tmp"' EXIT
{ {
printf '# Generated by dotfiles secrets/install.sh from op://%s/%s — do not edit.\n' "$OP_VAULT" "$OP_ITEM" printf '# Generated by dotfiles secrets/install.sh from op://%s/%s — do not edit.\n' "$OP_VAULT" "$OP_ITEM"
printf '# Refresh with: envs (change the vault with: envc NAME / envd NAME)\n' printf '# Refresh with: ops (change the vault with: opc NAME / opd NAME)\n'
printf '%s' "$_json" | jq -r ' printf '%s' "$_json" | jq -r '
.fields[] .fields[]
| select(.purpose != "NOTES") | select(.purpose != "NOTES")
+21 -21
View File
@@ -76,38 +76,38 @@ grmb() {
# Secrets from this user's 1Password vault, written by dotfiles/secrets/install.sh. # Secrets from this user's 1Password vault, written by dotfiles/secrets/install.sh.
# Reading a local 0600 file keeps shell startup off the network: nothing here # Reading a local 0600 file keeps shell startup off the network: nothing here
# calls op. envc/envd refresh the file themselves; after editing the vault # calls op. opc/opd refresh the file themselves; after editing the vault
# anywhere else (the 1Password app, another box), run `envs`. # anywhere else (the 1Password app, another box), run `ops`.
_DOTFILES_CONF="$HOME/.config/dotfiles" _DOTFILES_CONF="$HOME/.config/dotfiles"
[ -f "$_DOTFILES_CONF/secrets.env" ] && source "$_DOTFILES_CONF/secrets.env" [ -f "$_DOTFILES_CONF/secrets.env" ] && source "$_DOTFILES_CONF/secrets.env"
# envr NAME read one field straight from the vault # opr NAME read one field straight from the vault
# envc NAME [VALUE] create or update a field (prompts, hidden, when VALUE is # opc NAME [VALUE] create or update a field (prompts, hidden, when VALUE is
# omitted, which keeps the secret out of shell history), # omitted, which keeps the secret out of shell history),
# then refresh and reload this shell # then refresh and reload this shell
# envd NAME delete a field, refresh, and unset it in this shell # opd NAME delete a field, refresh, and unset it in this shell
# envl [VAULT [ITEM]] show every field and its current value (default: your # opl [VAULT [ITEM]] show every field and its current value (default: your
# vault and item from op.env) # vault and item from op.env)
# envs re-fetch the vault into secrets.env and reload this shell # ops re-fetch the vault into secrets.env and reload this shell
# #
# The service-account token lives in op.env and is loaded only inside these # The service-account token lives in op.env and is loaded only inside these
# subshells, so it never lands in the environment of everything you run. # subshells, so it never lands in the environment of everything you run.
_dotfiles_op() { _dotfiles_op() {
[ -f "$_DOTFILES_CONF/op.env" ] || { print -u2 "no $_DOTFILES_CONF/op.env; run: envs"; return 1; } [ -f "$_DOTFILES_CONF/op.env" ] || { print -u2 "no $_DOTFILES_CONF/op.env; run: ops"; return 1; }
( set -a; source "$_DOTFILES_CONF/op.env"; set +a; "$@" ) ( set -a; source "$_DOTFILES_CONF/op.env"; set +a; "$@" )
} }
_dotfiles_env_name() { _dotfiles_env_name() {
[[ "$1" =~ '^[A-Za-z_][A-Za-z0-9_]*$' ]] && return 0 [[ "$1" =~ '^[A-Za-z_][A-Za-z0-9_]*$' ]] && return 0
print -u2 "$2: '$1' is not a valid variable name"; return 2 print -u2 "$2: '$1' is not a valid variable name"; return 2
} }
envr() { opr() {
_dotfiles_env_name "$1" envr || return _dotfiles_env_name "$1" opr || return
_dotfiles_op sh -c 'op read "op://$OP_VAULT/$OP_ITEM/$1"' envr "$1" _dotfiles_op sh -c 'op read "op://$OP_VAULT/$OP_ITEM/$1"' opr "$1"
} }
envc() { opc() {
emulate -L zsh emulate -L zsh
local name=$1 value local name=$1 value
_dotfiles_env_name "$name" envc || return _dotfiles_env_name "$name" opc || return
if (( $# >= 2 )); then if (( $# >= 2 )); then
value=$2 value=$2
else else
@@ -115,18 +115,18 @@ envc() {
fi fi
# [concealed] makes it a password field; an existing field of that name is updated. # [concealed] makes it a password field; an existing field of that name is updated.
_dotfiles_op sh -c 'op item edit "$OP_ITEM" --vault "$OP_VAULT" "$1[concealed]=$2" >/dev/null' \ _dotfiles_op sh -c 'op item edit "$OP_ITEM" --vault "$OP_VAULT" "$1[concealed]=$2" >/dev/null' \
envc "$name" "$value" && envs opc "$name" "$value" && ops
} }
envd() { opd() {
_dotfiles_env_name "$1" envd || return _dotfiles_env_name "$1" opd || return
_dotfiles_op sh -c 'op item edit "$OP_ITEM" --vault "$OP_VAULT" "$1[delete]" >/dev/null' envd "$1" \ _dotfiles_op sh -c 'op item edit "$OP_ITEM" --vault "$OP_VAULT" "$1[delete]" >/dev/null' opd "$1" \
&& unset "$1" && envs && unset "$1" && ops
} }
envl() { opl() {
_dotfiles_op sh -c ' _dotfiles_op sh -c '
vault=${1:-$OP_VAULT} item=${2:-$OP_ITEM} vault=${1:-$OP_VAULT} item=${2:-$OP_ITEM}
printf "op://%s/%s\n" "$vault" "$item" >&2 printf "op://%s/%s\n" "$vault" "$item" >&2
op item get "$item" --vault "$vault" --reveal --format json' envl "$@" \ op item get "$item" --vault "$vault" --reveal --format json' opl "$@" \
| jq -r ' | jq -r '
[.fields[] | select(.purpose != "NOTES")] as $f [.fields[] | select(.purpose != "NOTES")] as $f
| ([$f[] | .label // "" | length] | max // 0) as $w | ([$f[] | .label // "" | length] | max // 0) as $w
@@ -136,7 +136,7 @@ envl() {
| "\($name) \($lines[0] // "")", | "\($name) \($lines[0] // "")",
($lines[1:][] | (" " * ($w + 2)) + .)' ($lines[1:][] | (" " * ($w + 2)) + .)'
} }
envs() { ops() {
"${DOTFILES_DIR:-$HOME/.dotfiles}/secrets/install.sh" \ "${DOTFILES_DIR:-$HOME/.dotfiles}/secrets/install.sh" \
&& source "$_DOTFILES_CONF/secrets.env" && source "$_DOTFILES_CONF/secrets.env"
} }
+1 -1
View File
@@ -36,7 +36,7 @@
# Nothing to set here. Do NOT loop over `op read` in this file: that ran on # Nothing to set here. Do NOT loop over `op read` in this file: that ran on
# every shell. secrets/install.sh stores the service-account token in # every shell. secrets/install.sh stores the service-account token in
# ~/.config/dotfiles/op.env and writes the vault's fields to secrets.env, which # ~/.config/dotfiles/op.env and writes the vault's fields to secrets.env, which
# the managed ~/.zshrc loads. Use envr / envc / envd (see zsh/zshrc). # the managed ~/.zshrc loads. Use opr / opc / opd (see zsh/zshrc).
# --- Proxmox ------------------------------------------------------------- # --- Proxmox -------------------------------------------------------------
# One pair of credentials, several consumers: the proxmox MCP server # One pair of credentials, several consumers: the proxmox MCP server