# direnv — Automatic Environment Switcher for Your Shell > direnv loads and unloads environment variables when you cd into a directory. Per-project PATH, API keys, and language versions — applied automatically when you enter, cleaned up when you leave. The foundation of reproducible dev environments. ## Install Save as a script file and run: # direnv — Per-Directory Environment Variables ## Quick Use ```bash # Install brew install direnv # Hook into shell (one-time) echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc # or bash, fish, tcsh source ~/.zshrc # In any project directory cat > .envrc < target env] export + unset to reach target | [On leaving directory] undo exports / restore previous values ``` ## Self-Hosting & Configuration ```bash # .envrc — Python project with venv layout python3.12 export FLASK_APP=app.py export FLASK_ENV=development PATH_add ./scripts # .envrc — Node project layout node use nvm 20 export NODE_ENV=development dotenv .env # load KEY=value pairs from .env dotenv_if_exists .env.local # .envrc — Nix flake use flake # .envrc — mix of standard + custom source_up # inherit parent .envrc first export DB_URL=$(op read "op://Dev/local-pg/url") # 1Password secret ``` ```bash # Handy commands direnv status # show what will load direnv reload # re-evaluate direnv deny # revoke approval (temporarily disable) direnv allow # approve after edits ``` ## Key Features - **Per-directory env** — exports scoped to a project, cleaned on leave - **Shell hooks** — bash, zsh, fish, tcsh, elvish, nu, pwsh - **Stdlib helpers** — layout python/node/ruby, use nvm/asdf/nix, PATH_add, dotenv - **Approval model** — changes require `direnv allow` (protects against drive-by repos) - **Source chaining** — source_up, source_env, strict_env - **Secret manager integration** — pull values from op/aws-vault/bitwarden - **Nix + devenv** — first-class support for declarative shells - **Cross-platform** — macOS, Linux, Windows (WSL) ## Comparison with Similar Tools | Feature | direnv | dotenv | mise env | shadowenv | Nix shell | |---|---|---|---|---|---| | Auto-load on cd | Yes | No | Yes (integrated) | Yes | No (enter shell) | | Auto-unload on leave | Yes | No | Yes | Yes | Yes (exit shell) | | Language-agnostic | Yes | Yes | Yes | Yes | Yes | | Approval required | Yes | No | Partial | Yes | No | | Complex helpers | Yes (stdlib) | No | Yes | Limited | Yes (flakes) | | Best For | Universal env switching | Simple KEY=value | mise ecosystem | Shopify-style orgs | Reproducible shells | ## FAQ **Q: direnv vs mise?** A: They overlap and complement. mise manages tool versions + env; direnv is env-only. You can use direnv without mise, or use mise with direnv (so `mise` commands see the right env automatically). **Q: Is it safe?** A: Yes — the approval model stops untrusted repos from running code. Always read `.envrc` before `direnv allow`, the same way you'd read a shell script. **Q: What about secrets?** A: Don't check secrets into `.envrc`. Use `dotenv .env.local` (gitignored) or helpers like `export SECRET=$(op read ...)` / `export SECRET=$(aws-vault exec ... -- env PRINT_SECRET)`. **Q: Does direnv slow my shell?** A: Virtually no. Its overhead is a few milliseconds per prompt. You won't notice it. ## Sources - GitHub: https://github.com/direnv/direnv - Website: https://direnv.net - License: MIT --- Source: https://tokrepo.com/en/workflows/8eaceee5-3814-11f1-9bc6-00163e2b0d79 Author: Script Depot