direnv Integration

envref integrates with direnv to automatically resolve your environment variables when you cd into a project directory. This is the recommended way to use envref for local development.

Overview

direnv is a shell extension that loads/unloads environment variables based on the current directory. envref acts as a resolution layer — direnv calls envref resolve --direnv and evals the output to inject resolved variables into your shell.

cd my-project/
  -> direnv triggers
  -> .envrc runs: eval "$(envref resolve --direnv)"
  -> envref merges .env files, resolves ref:// from keychain
  -> shell receives resolved KEY=VALUE exports

Setup

Prerequisites

Install direnv if you haven't already:

# macOS
brew install direnv

# Ubuntu/Debian
sudo apt install direnv

# From source
go install github.com/direnv/direnv@latest

Add the direnv hook to your shell (add to ~/.bashrc, ~/.zshrc, etc.):

# Bash
eval "$(direnv hook bash)"

# Zsh
eval "$(direnv hook zsh)"

# Fish
direnv hook fish | source

Initialize with direnv support

envref init --direnv

This creates the standard envref files (.envref.yaml, .env, .env.local) plus an .envrc file:

# .envrc (generated by envref init --direnv)
eval "$(envref resolve --direnv 2>/dev/null)" || true

If direnv is installed, envref init --direnv also runs direnv allow automatically. If direnv is not installed, it prints installation guidance.

Trust the .envrc

If the .envrc wasn't automatically trusted:

direnv allow

This tells direnv to trust and execute the .envrc in this directory.

How it works

The resolve --direnv flag

envref resolve --direnv outputs environment variables in export KEY=VALUE format, compatible with shell eval:

$ envref resolve --direnv
export APP_NAME=my-app
export APP_PORT=3000
export DATABASE_URL=postgres://user:secret@localhost/mydb
export API_KEY=sk-abc123

The 2>/dev/null || true in the .envrc ensures that if envref encounters an error (missing backend, locked vault), the shell still loads without failing.

Performance

envref is optimized for <50ms startup with 100 variables. This matters because direnv calls envref resolve on every cd into the project directory, and slow resolve times would make navigation feel sluggish.

Using profiles with direnv

Set a default profile

envref profile use staging

The active profile in .envref.yaml is used automatically by envref resolve --direnv, so direnv will load the staging profile every time.

Override the profile

To temporarily use a different profile, modify your .envrc:

# .envrc
eval "$(envref resolve --direnv --profile production 2>/dev/null)" || true

Or set a profile per-directory by editing .envref.yaml:

active_profile: staging

Strict mode

For CI environments or when you want to ensure all references resolve successfully, use --strict:

# .envrc for strict environments
eval "$(envref resolve --direnv --strict)"

With --strict, envref resolve exits with a non-zero code and produces no output if any ref:// reference cannot be resolved. This prevents partial environments from being loaded.

Watch mode

During development, you can use envref resolve --watch to automatically re-resolve when .env files change:

envref resolve --watch --direnv

This performs an initial resolve, then watches all .env files (.env, .env.<profile>, .env.local) via filesystem notifications. Changes are debounced (100ms) to handle rapid edits. Press Ctrl+C to stop.

Note: Watch mode is a development convenience for seeing changes in real-time. For normal direnv usage, the standard .envrc setup (without --watch) is sufficient since direnv reloads on file changes automatically.

Troubleshooting

direnv: error .envrc is blocked

Run direnv allow to trust the .envrc file. This is required after any change to .envrc.

Environment not loading

Check that envref can resolve successfully:

envref resolve --direnv

If this produces output, the issue is with direnv. If it errors, fix the envref configuration first.

Secrets not resolving

Verify your secrets are stored:

envref secret list
envref status

The status command shows which references are resolved and which are missing, with actionable hints.

Slow shell startup

If cd into the project feels slow:

  1. Check resolve time: time envref resolve --direnv
  2. Target is <50ms for 100 variables
  3. Ensure you're using the compiled binary, not go run
  4. Check if backend access (keychain prompts) is adding latency

envref: command not found

Ensure envref is on your $PATH. If installed via go install, confirm $GOPATH/bin is in your path. If using a binary, move it to /usr/local/bin or another directory on your path.

Example: full setup

# Install envref
go install github.com/xcke/envref/cmd/envref@latest

# Initialize project with direnv
cd my-project
envref init --project my-app --direnv

# Add secret references to .env
cat .env
# APP_NAME=my-app
# APP_PORT=3000
# DATABASE_URL=ref://secrets/database_url
# API_KEY=ref://secrets/api_key

# Store the secrets
envref secret set database_url --value "postgres://user:pass@localhost/mydb"
envref secret set api_key --value "sk-abc123"

# Verify resolution
envref resolve

# Leave and re-enter the directory to trigger direnv
cd .. && cd my-project
# direnv: loading .envrc
# direnv: export +APP_NAME +APP_PORT +DATABASE_URL +API_KEY

# Confirm
echo $API_KEY
# sk-abc123

See also