Back to skills
SKILL.md
Direnv Pattern
CSecurityImplements 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.
- 4 stars
- 0 votes
- 0 copies
- 1 view
- Added September 12, 2026
Works with
Security analysis
63/100- Modifies startup scripts or system services for persistence
- Modifies startup scripts or system services for persistence
- Sends environment variables or credentials to an external URL
Pro scans all 2 files and shows the line behind each finding
npx -y skills add aibot88/sec_skill_store --skill direnv-pattern --agent claude-codeAre you the author of Direnv Pattern?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/aibot88-direnv-pattern)---
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
1. **Datums specify WHICH** - `~/.dotfiles/_b00t_/*.ai.toml` files specify required variable names
2. **`.env` contains VALUES** - Actual API keys and secrets (gitignored)
3. **`direnv` loads automatically** - No manual `source` or `export` needed
4. **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
```bash
# macOS
brew install direnv
# Ubuntu/Debian
sudo apt-get install direnv
# Add to shell (choose one):
# bash:
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
# zsh:
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc
# fish:
echo 'direnv hook fish | source' >> ~/.config/fish/config.fish
```
### 2. Create .envrc
```bash
# b00t direnv configuration
# This file demonstrates the b00t pattern: direnv → .envrc → dotenv → .env
# Load project .env file (contains API keys)
dotenv
# Optionally load home directory .env for global keys
# dotenv ~/.env
# Optionally load environment-specific configs
# dotenv .env.local
# dotenv .env.development
```
### 3. Create .env with API Keys
```bash
# OpenRouter (200+ models via single API)
OPENROUTER_API_KEY=sk-or-v1-abc123...
# Anthropic (Claude)
ANTHROPIC_API_KEY=sk-ant-api03-xyz789...
# OpenAI
OPENAI_API_KEY=sk-proj-def456...
# HuggingFace
HF_TOKEN=hf_ghi789...
# Groq (ultra-fast inference)
GROQ_API_KEY=gsk_jkl012...
```
### 4. Allow direnv
```bash
direnv allow
```
### 5. Verify Setup
```bash
# Check environment variables are loaded
echo $OPENROUTER_API_KEY
# Test with Python
python3 -c "import os; print('✅ Loaded' if os.getenv('OPENROUTER_API_KEY') else '❌ Not loaded')"
```
## .envrc.example Template
```bash
# b00t direnv configuration
# Setup:
# 1. Copy: cp .envrc.example .envrc
# 2. Copy: cp .env.example .env
# 3. Edit .env with your actual API keys
# 4. Enable: direnv allow
# Load project .env file (contains API keys)
dotenv
# Optionally load home directory .env for global keys
# dotenv ~/.env
# Optionally load environment-specific configs
# dotenv .env.local
# Layout python - ensures direnv works with Python virtual environments
# Uncomment if using a venv:
# layout python python3.12
```
## .env.example Template
```bash
# b00t Environment Configuration
# ==========================================
# API keys are loaded via direnv → .envrc → dotenv → .env pattern.
#
# Setup:
# 1. Copy: cp .env.example .env
# 2. Fill in your actual API keys in .env
# 3. Enable: direnv allow (after copying .envrc.example to .envrc)
#
# The b00t pattern:
# - Datums (~/.dotfiles/_b00t_/*.ai.toml) specify WHICH vars are required
# - This .env file contains the actual VALUES
# - direnv loads them automatically when entering the directory
# OpenAI (gpt-4, gpt-3.5-turbo, etc.)
# OPENAI_API_KEY=sk-proj-...
# Anthropic (claude-3.5-sonnet, claude-3-opus, etc.)
# ANTHROPIC_API_KEY=sk-ant-api03-...
# Google Gemini
# GOOGLE_API_KEY=...
# Groq (llama-3.1, mixtral, etc.)
# GROQ_API_KEY=gsk_...
# OpenRouter (200+ models via single API)
# OPENROUTER_API_KEY=sk-or-...
# HuggingFace
# HF_TOKEN=hf_...
# Ollama (local models)
# OLLAMA_BASE_URL=http://localhost:11434
```
## Integration with Datums
### Provider Datum Example
```toml
[env]
# Required: Must be present in .env file
required = ["OPENROUTER_API_KEY"]
# Optional: Default values for non-secret configuration
defaults = { OPENROUTER_API_BASE = "https://openrouter.ai/api/v1" }
```
### Validation in Python
```python
import b00t_py
import os
# Ensure direnv loaded the environment
assert os.getenv('OPENROUTER_API_KEY'), "Run 'direnv allow' first!"
# Validate via datum system
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:
```bash
# .envrc
# Load global keys from home directory
dotenv ~/.env
# Load project-specific keys (can override global)
dotenv
```
### Environment-Specific Configuration
```bash
# .envrc
# Load base environment
dotenv
# Load environment-specific overrides
if [ "$ENVIRONMENT" = "production" ]; then
dotenv .env.production
elif [ "$ENVIRONMENT" = "staging" ]; then
dotenv .env.staging
else
dotenv .env.development
fi
```
### Custom Validation in .envrc
```bash
#!/usr/bin/env bash
# Load environment
dotenv
# Validate required keys are present
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
```gitignore
# Environment files (secrets)
.env
.envrc
.env.local
.env.*.local
# Keep examples (templates)
!.env.example
!.envrc.example
```
## Troubleshooting
### Variables Not Loading
```bash
# Check if direnv is hooked
direnv status
# Re-allow .envrc
direnv allow
# Check what direnv loaded
direnv export bash | grep API_KEY
```
### Missing Required Variables
```python
import b00t_py
# List available providers
providers = b00t_py.list_ai_providers("~/.dotfiles/_b00t_")
print(f"Available: {providers}")
# Check specific provider
validation = b00t_py.check_provider_env("openrouter", "~/.dotfiles/_b00t_")
if not validation["available"]:
print(f"Missing: {validation['missing_env_vars']}")
```
### Permission Denied
```bash
# Re-allow
direnv allow
# Check .envrc syntax
bash -n .envrc
```
## CI/CD Integration
For environments where direnv isn't available:
```yaml
# .gitlab-ci.yml
variables:
OPENROUTER_API_KEY: ${CI_OPENROUTER_API_KEY}
test:
script:
- python3 -m pytest
```
```yaml
# .github/workflows/test.yml
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
1. **Install direnv** and add shell hook
2. **Copy templates**: `.envrc.example` → `.envrc`, `.env.example` → `.env`
3. **Edit .env** with actual API keys
4. **Run `direnv allow`**
5. **Verify** with `echo $API_KEY` or Python
### Adding New Keys
1. **Add to .env.example** (commented, as template)
2. **Add to .env** (actual value)
3. **Update datum** to specify required key
4. **Run `direnv allow`** if .envrc changed
### Per-Project Configuration
1. **Navigate to project**: `cd /path/to/project`
2. **Create .envrc**: Reference `.envrc.example`
3. **Create .env**: Reference `.env.example`
4. **Allow**: `direnv allow`
5. **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:
1. **DRY**: Single source of truth for requirements (datums)
2. **Secure**: Secrets in `.env` (gitignored), not in code
3. **Automatic**: `direnv` loads environment on `cd`
4. **Validated**: Rust checks required vars before execution
5. **Flexible**: Supports multiple `.env` files, local/global keys
Files in this skill
- SKILL.md
- source.json
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.