Shell Plugins
The dotsecenv shell plugins automatically load secrets from .secenv files when you cd into a directory. When you leave, secrets are automatically unloaded—keeping your environment clean and secure.
How It Works
Section titled “How It Works”- On
cdinto a directory: The plugin checks for.envand.secenvfiles - Security check: Files must be owned by you (or root) and not world-writable
- Trust prompt: For
.secenvfiles, you’re prompted to allow loading (can be remembered) - Auto-load: Plain variables from
.envare loaded, then secrets are fetched from your vault - On
cdout: Variables are automatically unset
~/project $ cd myapp/dotsecenv: found .secenv in /home/user/myappLoad secrets? [y]es / [n]o / [a]lways: ydotsecenv: loaded 2 secret(s) from .secenv: DATABASE_URL, API_KEY
~/project/myapp $ cd ..dotsecenv: unloaded 2 secret(s): DATABASE_URL, API_KEYInstallation
Section titled “Installation”Oh-My-Zsh:
git clone https://github.com/dotsecenv/plugin.git \ ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/dotsecenvThen add dotsecenv to your plugins in ~/.zshrc:
plugins=(... dotsecenv)Antigen:
antigen bundle dotsecenv/pluginManual:
source /path/to/dotsecenv.plugin.zshAdd to your ~/.bashrc:
source /path/to/dotsecenv.plugin.bashOr use the installer:
curl -fsSL https://raw.githubusercontent.com/dotsecenv/plugin/main/install.sh | bashFisher:
fisher install dotsecenv/pluginManual:
source /path/to/conf.d/dotsecenv.fishProvided Commands & Aliases
Section titled “Provided Commands & Aliases”The plugins provide several convenience commands:
| Command | Description |
|---|---|
dse | Shorthand for dotsecenv |
secret NAME | Shorthand for dotsecenv secret get NAME |
copysecret NAME | Copy a secret directly to clipboard |
reloadsecenv | Reload secrets in the current directory |
pinsecenv | Pin current secrets to persist across directory changes |
dse — Quick CLI Access
Section titled “dse — Quick CLI Access”Use dse as a shorthand for the dotsecenv command:
# Instead of:dotsecenv vault describe
# Use:dse vault describesecret — Quick Secret Retrieval
Section titled “secret — Quick Secret Retrieval”Retrieve a secret with minimal typing:
# Instead of:dotsecenv secret get DATABASE_PASSWORD
# Use:secret DATABASE_PASSWORDcopysecret — Copy to Clipboard
Section titled “copysecret — Copy to Clipboard”Copy a secret directly to your clipboard without displaying it:
copysecret API_KEY# Output: dotsecenv: secret copied to clipboardClipboard support:
- macOS: Uses
pbcopy(built-in) - Wayland: Uses
wl-copy - X11: Uses
xcliporxsel
reloadsecenv — Reload Current Directory
Section titled “reloadsecenv — Reload Current Directory”Re-trigger secret loading for the current directory without leaving and re-entering:
reloadsecenvThis is useful when:
- You’ve added new secrets to your vault
- You’ve modified the
.secenvfile - A secret fetch failed and you want to retry
pinsecenv — Pin Secrets
Section titled “pinsecenv — Pin Secrets”Pin the current directory’s environment variables so they persist even after you cd away.
pinsecenv# Output:# dotsecenv: pinned secrets: DATABASE_URL, API_KEY# dotsecenv: pinned env vars: NODE_ENV, PORT# dotsecenv: these variables will persist when you leave this directory# dotsecenv: you must unset them manually, e.g.: `unset VARIABLE_NAME`The Pin Use Case
Section titled “The Pin Use Case”By default, dotsecenv automatically unloads secrets when you leave a directory. This is a security feature—secrets don’t linger in your environment longer than needed.
However, there are scenarios where you want secrets to persist:
Running Background Processes
Section titled “Running Background Processes”cd ~/myapp# Secrets loaded: DATABASE_URL, API_KEY
# Start a background server that needs these env varsnpm run dev &
# Pin secrets before leavingpinsecenv
cd ~/other-project# Normally secrets would be unloaded, but they're pinned!# Your background server continues workingMulti-Directory Workflows
Section titled “Multi-Directory Workflows”cd ~/project-a# Secrets loaded for project-a
pinsecenv # Pin them
cd ~/project-b# Project-a secrets still available# Project-b secrets also loaded (if .secenv exists)Long-Running Terminal Sessions
Section titled “Long-Running Terminal Sessions”If you’re working across multiple projects but need consistent access to certain secrets:
cd ~/main-projectpinsecenv
# Now work anywhere while keeping main-project secrets availablecd ~/scripts./deploy.sh # Can use pinned DATABASE_URLTrust System
Section titled “Trust System”The plugin uses a trust system to prevent malicious .secenv files from auto-loading secrets:
Trust Prompt Options
Section titled “Trust Prompt Options”When you cd into a directory with an untrusted .secenv:
dotsecenv: found .secenv in /path/to/projectLoad secrets? [y]es / [n]o / [a]lways:| Option | Behavior |
|---|---|
| y / yes | Load secrets for this session only |
| n / no | Skip loading for this session |
| a / always | Permanently trust this directory |
Persistent Trust
Section titled “Persistent Trust”Directories trusted with “always” are saved to:
~/.config/dotsecenv/trusted_dirsTo remove trust:
# Edit the file and remove the directory pathvim ~/.config/dotsecenv/trusted_dirsSecurity Checks
Section titled “Security Checks”Before loading any file, the plugin performs security checks:
- Ownership: File must be owned by you or root
- Permissions: File must not be world-writable
If a file fails these checks:
dotsecenv: refusing to load /path/.secenv - not owned by current user or rootdotsecenv: refusing to load /path/.env - world-writable.secenv File Format
Section titled “.secenv File Format”The .secenv file defines which secrets to load as environment variables:
# Load secret with matching nameDATABASE_PASSWORD={dotsecenv}
# Load secret with different nameDB_PASS={dotsecenv/DATABASE_PASSWORD}
# Plain values work too (loaded from .secenv, not encrypted)NODE_ENV=production
# Load from a namespaceAPI_KEY={dotsecenv/production::API_KEY}See Your First Secret for more details on .secenv syntax.
Loading Order
Section titled “Loading Order”When both .env and .secenv exist in a directory:
- Phase 1: Load plain variables from
.env - Phase 2: Load plain variables from
.secenv - Phase 3: Load secrets from
.env(if any{dotsecenv}patterns) - Phase 4: Load secrets from
.secenv
If a variable is defined in both files, .secenv wins with a warning:
dotsecenv: warning: DATABASE_URL from .secenv overrides value from .envTroubleshooting
Section titled “Troubleshooting”Secrets not loading on cd
Section titled “Secrets not loading on cd”-
Check the plugin is loaded:
Terminal window type reloadsecenv # Should show it's a function -
Verify
.secenvexists and has correct permissions:Terminal window ls -la .secenv -
Try manual reload:
Terminal window reloadsecenv
“No TTY for trust prompt”
Section titled ““No TTY for trust prompt””The trust prompt requires an interactive terminal. This happens when:
- Running in a script
- Running in a non-interactive shell
Solution: Pre-trust the directory:
echo "/path/to/project" >> ~/.config/dotsecenv/trusted_dirsSecret fetch errors
Section titled “Secret fetch errors”If a secret fails to fetch, you’ll see:
dotsecenv: error fetching secret 'SECRET_NAME' for VAR:<error details>Common causes:
- Secret doesn’t exist in vault
- GPG agent not running
- Vault locked
Next Steps
Section titled “Next Steps”- Your First Secret — Learn
.secenvfile syntax - CLI Reference — Full command documentation
- Security Model — Understand the trust model