Reloading Secrets
Understand why vault updates do not automatically appear in your shell, and learn how to fix it with dse reload and dse up.
Prerequisites
Section titled “Prerequisites”- Getting Started completed (shell plugin installed, at least one secret loaded via
.secenv)
The problem
Section titled “The problem”-
Open two terminals
In Terminal 1, enter your project directory:
Terminal window cd ~/my-projectecho $DATABASE_PASSWORD# Output: s3cr3t-db-pass -
Update the secret in Terminal 2
Terminal window echo "new-rotated-password" | dotsecenv secret store DATABASE_PASSWORD -
Check Terminal 1
Terminal window echo $DATABASE_PASSWORD# Output: s3cr3t-db-pass <-- still the old value!
The fix: dse reload
Section titled “The fix: dse reload”-
Run
dse reloadin Terminal 1Terminal window dse reload# dotsecenv: loaded 1 secret(s) from .secenv: DATABASE_PASSWORD -
Verify the new value
Terminal window echo $DATABASE_PASSWORD# Output: new-rotated-password
When to use dse reload
Section titled “When to use dse reload”- You stored or rotated a secret in another terminal or on another machine (after
git pull) - You edited the
.secenvfile (added or removed a variable) - A secret fetch failed and you want to retry
Bonus: dse up
Section titled “Bonus: dse up”If you open a terminal directly in a subdirectory (for example, an IDE terminal opening in ~/my-project/src/), the parent .secenv was never traversed. Use dse up to walk up the directory tree and load all ancestor .secenv files:
cd ~/my-project/srcecho $DATABASE_PASSWORD# Output: (empty)
dse up# dotsecenv: loaded 1 secret(s) from .secenv: DATABASE_PASSWORD
echo $DATABASE_PASSWORD# Output: new-rotated-password.secenv placeholder syntax
Section titled “.secenv placeholder syntax”A .secenv value can be a plain string or a {dotsecenv...} placeholder the plugin resolves at load time via dotsecenv secret get. There are four placeholder forms:
| Syntax | Resolves to |
|---|---|
KEY={dotsecenv} |
The secret named KEY (same name as the variable) |
KEY={dotsecenv/} |
Same as above; the slash is empty |
KEY={dotsecenv/EXPLICIT_NAME} |
The secret named EXPLICIT_NAME, exported as KEY |
KEY={dotsecenv/namespace::KEY} |
A namespaced secret (namespace::KEY is the canonical key) |
Only one / is allowed inside {dotsecenv/...}; a second / is a parse error. Variable names must match ^[A-Za-z_][A-Za-z0-9_]*$.
# Same-name reference (most common). Both forms are equivalent.DATABASE_PASSWORD={dotsecenv}SLACK_WEBHOOK_URL={dotsecenv/}
# Explicit name: the variable and the secret key differ.STRIPE_API_KEY={dotsecenv/STRIPE_SECRET_KEY}
# Namespaced lookup.PROD_DB_PASSWORD={dotsecenv/prod::DB_PASSWORD}Permissions
Section titled “Permissions”The plugin refuses to load a .secenv that is world-writable or not owned by you (or root). Set permissions explicitly:
chmod 600 .secenvThe first load in a directory prompts you to trust it. Answer a (always) to persist trust across new shells.
Loading order
Section titled “Loading order”The plugin loads .secenv files bottom-up to root, so deeper directories shadow shallower ones for the same key:
~/my-project/.secenv APP_ENV=production DATABASE_URL={dotsecenv}~/my-project/services/api/.secenv SERVICE_NAME=apiEntering ~/my-project/services/api/ loads both files. APP_ENV and DATABASE_URL come from the parent; SERVICE_NAME comes from the child. If the child also set APP_ENV, its value would win because it is closer to the cwd.
Next steps
Section titled “Next steps”- Shell Plugins – trust system, tree-scoped loading, nested
.secenvfiles - Share a Secret – share secrets with teammates
