| name | direnv-pattern |
| description | Implements the b00t environment management pattern: direnv → .envrc → dotenv → .env
where datums specify WHICH environment variables are required and .env contains
the actual secret VALUES. Ensures automatic environment loading per-project.
|
| version | 1.0.0 |
| allowed-tools | Read, Write, Edit, Bash |
What This Skill Does
The b00t direnv pattern provides secure, automatic environment variable management for projects. This skill helps you:
- Set up direnv + .envrc + .env configuration
- Follow the b00t pattern: WHICH (datums) vs VALUES (.env)
- Validate environment variables before execution
- Support multiple environments (dev, staging, prod)
- Integrate with b00t datum system
When It Activates
Activate this skill when you see phrases like:
- "setup environment variables"
- "configure direnv"
- "create .envrc file"
- "add API keys"
- "environment not loading"
- "missing environment variables"
- "configure .env file"
- "setup direnv pattern"
The b00t Pattern Flow
Developer enters directory
↓
direnv detects .envrc file
↓
.envrc calls: dotenv
↓
dotenv loads .env file
↓
Environment variables available
↓
Rust validates via datum
↓
✅ Agent runs
Key Principles
- Datums specify WHICH -
~/.dotfiles/_b00t_/*.ai.toml files specify required variable names
.env contains VALUES - Actual API keys and secrets (gitignored)
direnv loads automatically - No manual source or export needed
- Rust validates - Via PyO3 bindings, DRY approach
File Structure
project/
├── .envrc # ← Loaded by direnv (calls dotenv)
├── .env # ← Contains actual API keys (GITIGNORED!)
├── .envrc.example # ← Template for .envrc (committed)
├── .env.example # ← Shows required keys (committed)
└── .gitignore # ← Must include .env and .envrc
Setup Instructions
1. Install direnv
brew install direnv
sudo apt-get install direnv
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc
echo 'direnv hook fish | source' >> ~/.config/fish/config.fish
2. Create .envrc
dotenv
3. Create .env with API Keys
OPENROUTER_API_KEY=sk-or-v1-abc123...
ANTHROPIC_API_KEY=sk-ant-api03-xyz789...
OPENAI_API_KEY=sk-proj-def456...
HF_TOKEN=hf_ghi789...
GROQ_API_KEY=gsk_jkl012...
4. Allow direnv
direnv allow
5. Verify Setup
echo $OPENROUTER_API_KEY
python3 -c "import os; print('✅ Loaded' if os.getenv('OPENROUTER_API_KEY') else '❌ Not loaded')"
.envrc.example Template
dotenv
.env.example Template
Integration with Datums
Provider Datum Example
[env]
required = ["OPENROUTER_API_KEY"]
defaults = { OPENROUTER_API_BASE = "https://openrouter.ai/api/v1" }
Validation in Python
import b00t_py
import os
assert os.getenv('OPENROUTER_API_KEY'), "Run 'direnv allow' first!"
validation = b00t_py.check_provider_env("openrouter", "~/.dotfiles/_b00t_")
if validation["available"]:
print("✅ OpenRouter environment ready")
else:
print(f"❌ Missing: {validation['missing_env_vars']}")
print("Add them to your .env file and run 'direnv allow'")
Advanced Patterns
Multiple Environment Files
Load both global and project-specific keys:
dotenv ~/.env
dotenv
Environment-Specific Configuration
dotenv
if [ "$ENVIRONMENT" = "production" ]; then
dotenv .env.production
elif [ "$ENVIRONMENT" = "staging" ]; then
dotenv .env.staging
else
dotenv .env.development
fi
Custom Validation in .envrc
#!/usr/bin/env bash
dotenv
required_vars=("OPENROUTER_API_KEY" "ANTHROPIC_API_KEY")
for var in "${required_vars[@]}"; do
if [ -z "${!var}" ]; then
echo "❌ Missing: $var"
echo " Add it to your .env file"
return 1
fi
done
echo "✅ All required environment variables loaded"
Security Best Practices
✅ DO
- ✅ Add
.env to .gitignore
- ✅ Add
.envrc to .gitignore (committed: .envrc.example)
- ✅ Use
.env.example as template (committed to git)
- ✅ Store API keys only in
.env files
- ✅ Use
direnv allow to load environment per-project
- ✅ Validate environment variables before use
❌ DON'T
- ❌ Commit
.env files to git
- ❌ Commit
.envrc with secrets to git
- ❌ Hard-code API keys in source code
- ❌ Store secrets in datum TOML files
- ❌ Share
.env files via chat/email
- ❌ Use production keys in examples
.gitignore Configuration
# Environment files (secrets)
.env
.envrc
.env.local
.env.*.local
# Keep examples (templates)
!.env.example
!.envrc.example
Troubleshooting
Variables Not Loading
direnv status
direnv allow
direnv export bash | grep API_KEY
Missing Required Variables
import b00t_py
providers = b00t_py.list_ai_providers("~/.dotfiles/_b00t_")
print(f"Available: {providers}")
validation = b00t_py.check_provider_env("openrouter", "~/.dotfiles/_b00t_")
if not validation["available"]:
print(f"Missing: {validation['missing_env_vars']}")
Permission Denied
direnv allow
bash -n .envrc
CI/CD Integration
For environments where direnv isn't available:
variables:
OPENROUTER_API_KEY: ${CI_OPENROUTER_API_KEY}
test:
script:
- python3 -m pytest
env:
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: python3 -m pytest
Workflow
Initial Setup
- Install direnv and add shell hook
- Copy templates:
.envrc.example → .envrc, .env.example → .env
- Edit .env with actual API keys
- Run
direnv allow
- Verify with
echo $API_KEY or Python
Adding New Keys
- Add to .env.example (commented, as template)
- Add to .env (actual value)
- Update datum to specify required key
- Run
direnv allow if .envrc changed
Per-Project Configuration
- Navigate to project:
cd /path/to/project
- Create .envrc: Reference
.envrc.example
- Create .env: Reference
.env.example
- Allow:
direnv allow
- Test: Python imports should have env vars
Related Skills
- datum-system: Specifies WHICH env vars are required
- dry-philosophy: Rust validates env, Python just uses it
- justfile-usage: Add environment setup commands
References
b00t-j0b-py/docs/ENVIRONMENT_SETUP.md - Complete guide
b00t-j0b-py/.envrc.example - Template
b00t-j0b-py/.env.example - API keys template
b00t-py/src/lib.rs - PyO3 validation functions
Summary
The b00t direnv pattern provides:
- DRY: Single source of truth for requirements (datums)
- Secure: Secrets in
.env (gitignored), not in code
- Automatic:
direnv loads environment on cd
- Validated: Rust checks required vars before execution
- Flexible: Supports multiple
.env files, local/global keys