Install
$ agentstack add skill-brpaz-agent-skills-direnv Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Destructive filesystem operation.
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
direnv - Environment Variable Manager
Use this skill when working with .envrc files, project-specific environment configuration, or integrating development tools that need automatic environment activation.
When to Use
- Creating or updating a
.envrcfile for a project - Setting up automatic environment activation for nix, devenv, asdf, or mise
- Troubleshooting environment variable loading or
direnv allowissues - Optimising
.envrcperformance with caching or watch files
Philosophy
direnv automatically loads and unloads environment variables based on your current directory. Core benefits:
- Automatic activation - No manual sourcing required
- Secure by default - Requires explicit approval before executing
.envrc - Shell-agnostic - Works with bash, zsh, fish, etc.
- Language-neutral - Integrates with nix, asdf, mise, devenv, etc.
- Per-directory isolation - Each project has its own environment
Quick Start
Installation
# macOS
brew install direnv
# Ubuntu/Debian
apt install direnv
# Nix
nix-env -i direnv
Shell Integration (REQUIRED)
Add to your shell config:
# ~/.bashrc or ~/.bash_profile
eval "$(direnv hook bash)"
# ~/.zshrc
eval "$(direnv hook zsh)"
# ~/.config/fish/config.fish
direnv hook fish | source
CRITICAL: Restart your shell after adding the hook.
Basic .envrc
# .envrc
export DATABASE_URL="postgres://localhost:5432/myapp"
export API_KEY="dev-key-12345"
export NODE_ENV="development"
Allow the .envrc
cd /path/to/project
direnv allow
The environment is now loaded. When you cd away, it's automatically unloaded.
.envrc Patterns
Loading .env files
# .envrc
dotenv
Loads .env file in the same directory (dotenv format: KEY=value).
# Load from custom path
dotenv .env.local
dotenv config/.env.production
Extending PATH
# .envrc
PATH_add bin
PATH_add node_modules/.bin
PATH_add scripts
Prepends directories to PATH. Automatically creates absolute paths.
Layout Commands (Language Tools)
direnv provides "layouts" for common language environments:
# .envrc
# Node.js (uses project's node_modules)
layout node
# Python virtualenv
layout python
layout python python3.11
# Ruby
layout ruby
# Go
layout go
# Perl
layout perl
Custom Layout Functions
# .envrc
layout_custom() {
export PROJECT_ROOT="$PWD"
export TEMP_DIR="$PWD/.tmp"
mkdir -p "$TEMP_DIR"
PATH_add "$PROJECT_ROOT/bin"
}
layout custom
Nix Integration
# .envrc
use nix
Loads packages from shell.nix or default.nix in current directory.
With flakes:
# .envrc
use flake
Loads from flake.nix.
Specific flake output:
# .envrc
use flake .#devShell
devenv Integration
# .envrc
eval "$(devenv direnvrc)"
use devenv
Integrates with devenv.sh (see devenv skill for details).
asdf Integration
# .envrc
use asdf
Loads tool versions from .tool-versions.
Specific tools:
# .envrc
use asdf nodejs 20.11.0
use asdf python 3.12.1
mise (rtx) Integration
# .envrc
use mise
Loads from .mise.toml or .tool-versions.
Conditional Logic
# .envrc
# OS-specific
if [[ "$OSTYPE" == "darwin"* ]]; then
export BROWSER="open"
else
export BROWSER="xdg-open"
fi
# Check file existence
if [ -f .env.local ]; then
dotenv .env.local
fi
# Check command availability
if has docker; then
export DOCKER_AVAILABLE=true
fi
Source Other Files
# .envrc
source ./scripts/env-setup.sh
source_env ../shared/.envrc # Relative to current dir
source_env_if_exists .envrc.local # Won't fail if missing
Watching Files (Auto-reload on Change)
# .envrc
watch_file config/settings.yaml
watch_file .env.production
# Reload .envrc when these files change
Secrets Management
# .envrc
# Load secrets from 1Password
export OP_SERVICE_ACCOUNT_TOKEN=$(cat ~/.op-token)
export API_KEY=$(op read "op://dev/api-key/password")
# Load from pass (password store)
export DB_PASSWORD=$(pass show myapp/db)
# Load from vault
export VAULT_TOKEN=$(vault print token)
Rule: Never commit secrets to .envrc - load from secure stores or use .envrc.local (gitignored).
Working with Multiple Environments
# .envrc
ENV="${ENV:-development}"
case "$ENV" in
production)
source_env .envrc.production
;;
staging)
source_env .envrc.staging
;;
*)
source_env .envrc.development
;;
esac
Usage: ENV=staging direnv allow
Project Root Detection
# .envrc
export PROJECT_ROOT="$PWD"
export SRC_ROOT="$PROJECT_ROOT/src"
export BUILD_DIR="$PROJECT_ROOT/build"
Strict Mode
# .envrc
strict_env # Exit on errors in .envrc
set -euo pipefail
Logging and Debugging
# .envrc
log_status "Loading project environment..."
log_error "Failed to load secrets"
# Debug mode
export DIRENV_LOG_FORMAT="$(date) - %s"
stdlib Reference
direnv provides built-in functions in .envrc:
| Function | Purpose | |----------|---------| | dotenv [path] | Load .env file (default: .env) | | PATH_add | Prepend directory to PATH | | path_add | Prepend to any PATH-like variable | | load_prefix | Load include/ lib/ from prefix | | layout | Load predefined layout | | use | Load integration (nix, asdf, etc.) | | watch_file | Reload .envrc when file changes | | source_env | Source another .envrc | | source_env_if_exists | Source if exists | | source_up [path] | Load parent directory .envrc | | has | Check if command exists | | log_status | Print info message | | log_error | Print error message | | expand_path | Convert to absolute path | | find_up | Search up directory tree | | direnv_layout_dir | Get layout dir path (.direnv/) | | user_rel_path | Get path relative to $HOME | | strict_env | Enable strict error handling |
Security Model
Approval Required
direnv requires explicit approval before executing .envrc:
direnv allow # Approve current .envrc
direnv allow /path # Approve specific path
direnv deny # Revoke approval
After editing .envrc, you MUST re-approve with direnv allow.
What Gets Checked
- SHA256 hash of
.envrccontents - Stored in
~/.config/direnv/allow/ - Approval is per-directory + content hash
Allowed Paths
# ~/.config/direnv/direnv.toml
[whitelist]
prefix = [ "/home/user/projects" ]
exact = [ "/opt/project" ]
Auto-approve paths matching these patterns.
Block List
# ~/.config/direnv/direnv.toml
[global]
hide_env_diff = true
disable_stdin = true
[whitelist]
prefix = [] # Block everything except explicit allows
Configuration
Global config: ~/.config/direnv/direnv.toml
[global]
# Hide environment diff output
hide_env_diff = false
# Disable reading stdin (security)
disable_stdin = false
# Timeout for direnv execution
load_dotenv = true
# Warn if .envrc takes longer than X seconds
warn_timeout = "5s"
[whitelist]
# Auto-approve these paths
prefix = [ "/home/user/projects", "/opt/work" ]
exact = [ "/etc/myapp" ]
Performance Optimization
Cache Layout Directories
# .envrc
layout_dir=$(direnv_layout_dir)
export VENV_DIR="$layout_dir/venv"
if [ ! -d "$VENV_DIR" ]; then
python -m venv "$VENV_DIR"
fi
Layout dir: .direnv/ (gitignored, persistent across .envrc reloads)
Lazy Loading
# .envrc
# Don't run expensive operations on every load
if [ ! -f .direnv/initialized ]; then
log_status "First-time setup..."
pnpm install
touch .direnv/initialized
fi
Conditional Activation
# .envrc
# Skip activation in CI
if [ -n "$CI" ]; then
return
fi
# Skip in containers
if [ -f /.dockerenv ]; then
return
fi
watch_file for Cache Invalidation
# .envrc
layout_dir=$(direnv_layout_dir)
watch_file package.json
if [ ! -f "$layout_dir/.deps-installed" ] || \
[ package.json -nt "$layout_dir/.deps-installed" ]; then
pnpm install
touch "$layout_dir/.deps-installed"
fi
Reinstalls only when package.json changes.
Integration Examples
With Docker Compose
# .envrc
export COMPOSE_PROJECT_NAME="myapp"
export COMPOSE_FILE="docker-compose.yml:docker-compose.dev.yml"
export DOCKER_BUILDKIT=1
With Terraform
# .envrc
export TF_VAR_environment="dev"
export TF_DATA_DIR="$PWD/.terraform"
export AWS_PROFILE="dev-account"
With Kubernetes
# .envrc
export KUBECONFIG="$PWD/kubeconfig.yaml"
export KUBECTL_CONTEXT="dev-cluster"
With Make
# .envrc
export MAKEFLAGS="-j$(nproc)"
export BUILD_TYPE="debug"
With Homebrew
# .envrc
if [[ "$OSTYPE" == "darwin"* ]] && has brew; then
eval "$(brew shellenv)"
PATH_add "$(brew --prefix)/opt/postgresql@15/bin"
fi
Monorepo Patterns
Root .envrc
# /project/.envrc
export PROJECT_ROOT="$PWD"
export WORKSPACE="monorepo"
# Load global deps
PATH_add "$PROJECT_ROOT/bin"
Service .envrc
# /project/services/api/.envrc
source_up # Load parent .envrc first
export SERVICE_NAME="api"
export SERVICE_PORT=3001
# Service-specific PATH
PATH_add "$PWD/scripts"
# Load service env
dotenv .env.api
Workspace .envrc
# /project/.envrc
export WORKSPACE_ROOT="$PWD"
# Detect current service
if [[ "$PWD" == *"/services/"* ]]; then
SERVICE=$(basename "$PWD")
export SERVICE_NAME="$SERVICE"
fi
Troubleshooting
Check direnv status
direnv status
Shows:
- Current allowed paths
- Found .envrc files
- Whether environment is loaded
Debug mode
direnv exec . env | grep -v '^_' # Show exported vars
direnv export json # JSON output
Force reload
direnv reload
Clear all approvals
rm -rf ~/.config/direnv/allow/
Check hook installation
echo $DIRENV_DIR # Should be set when in project
type direnv # Should show function, not binary
If direnv is a binary (not a shell function), the hook is not installed.
Performance profiling
time direnv exec . true
If > 1 second, optimize your .envrc:
- Remove expensive commands
- Use layout directories for caching
- Add conditional checks to skip unnecessary work
Common Issues
| Problem | Solution | |---------|----------| | Changes not applied | Run direnv allow after editing .envrc | | "Command not found" after cd | Check shell hook is installed | | Slow activation | Profile with time direnv exec . true, optimize .envrc | | Variables remain loaded | Check for conflicting shell configs setting same vars | | .envrc not found | Ensure no typos, check direnv status | | Permission denied | Check file permissions, run direnv allow |
Rules
- ALWAYS commit
.envrcto version control (but NOT.envrc.localif it contains secrets). - ALWAYS gitignore
.direnv/- it's a cache directory. - NEVER put secrets directly in
.envrc- load from secure stores or use.envrc.local. - ALWAYS run
direnv allowafter editing.envrc- it won't activate without approval. - ALWAYS test
.envrcchanges by cd-ing in/out of the directory. - Use
source_upin nested directories to inherit parent environment before extending. - Use
layoutcommands instead of manual PATH manipulation when available. - Use
watch_filefor cache invalidation based on file changes. - Use
.envrc.local(gitignored) for personal/secret overrides. - Profile slow
.envrcfiles withtime direnv exec . trueand optimize. - Document non-obvious .envrc logic with comments - future you will thank you.
- Use
hasto check command existence before using tools that might not be installed.
Quick Reference
# Approve .envrc
direnv allow
# Deny/revoke
direnv deny
# Force reload
direnv reload
# Check status
direnv status
# Edit safely (auto-reloads)
direnv edit [path]
# Show current environment diff
direnv export json
# Execute command in environment
direnv exec
Resources
Inputs
- Project root directory with an existing or new
.envrcfile - Integration target (nix flake, devenv, asdf, mise, or plain env vars)
Outputs
- A
.envrcfile (and optionally a.envrc.localfor personal overrides) that automatically loads the project environment on directory entry
Examples
# .envrc — use a devenv environment
use devenv
# .envrc — load env vars and add local bin to PATH
dotenv .env
PATH_add bin
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: brpaz
- Source: brpaz/agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.