Skip to content
Back to skills

Direnv Pattern

CSecurity

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.

  • 4 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 12, 2026
developmentpythonrustgoshellbashgitapici/cdsecurity

Works with

  • api

Security analysis

C63/100
  • criticalModifies startup scripts or system services for persistence
  • criticalModifies startup scripts or system services for persistence
  • criticalSends environment variables or credentials to an external URL

Pro scans all 2 files and shows the line behind each finding

Scanned September 12, 2026

npx -y skills add aibot88/sec_skill_store --skill direnv-pattern --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Direnv Pattern?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Direnv Pattern
[![Security: C — Skills Directory](https://www.skillsdirectory.com/api/skills/aibot88-direnv-pattern/badge)](https://www.skillsdirectory.com/skills/aibot88-direnv-pattern)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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.md9.6 KB
  • source.json755 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.