audit-env-variables
- Discovery - Find all env files and code references
- Usage Analysis - Identify which variables are used vs unused
- Service Detection - Recognize services (Stripe, AWS, Supabase, etc.) and their permission implications
- Code Path Mapping - Document where each variable is used in the codebase
- Report Generation - Output a structured markdown document
- Cleanup (optional) - Safely remove unused variables with user confirmation
- Regression Prevention - Validate no regressions via build/test validation with automatic rollback
<quick_start> Audit only (default):
- Scan for
.env*files in project root - Grep codebase for
process.env.,import.meta.env., and destructured env patterns - Cross-reference declared vs used variables
- Identify services by naming patterns and categorize permissions
- Generate markdown report using the template
With cleanup (--cleanup flag):
6. Check for dynamic access patterns that might hide usage
7. Present unused variables and get user confirmation
8. Create backups, remove confirmed variables
9. Run build/tests to detect regressions
10. Auto-rollback if regressions detected
</quick_start>
Find all env-related files:
find . -maxdepth 2 -name ".env*" -o -name "env.d.ts" | grep -v node_modules
Common files:
.env- Local development.env.local- Local overrides.env.development/.env.production- Environment-specific.env.example- Template for required variables
Step 2: Extract Declared Variables
Parse each env file for variable declarations:
Grep pattern: ^[A-Z][A-Z0-9_]+=
Build a list of all declared variables with their source file.
Step 3: Find Code References
Search for environment variable usage patterns:
Direct access:
process.env.VARIABLE_NAME
import.meta.env.VARIABLE_NAME
process.env["VARIABLE_NAME"]
Destructured patterns:
const { API_KEY, DATABASE_URL } = process.env
Framework-specific:
// Next.js public vars
NEXT_PUBLIC_*
// Vite
VITE_*
Use Grep tool with patterns:
process\.env\.([A-Z][A-Z0-9_]+)
import\.meta\.env\.([A-Z][A-Z0-9_]+)
Step 4: Cross-Reference Usage
For each declared variable:
- Used: Found in code references
- Unused: Declared but no code references found
- Undeclared: Referenced in code but not in any env file
Flag potential issues:
- Unused variables (cleanup candidates)
- Undeclared variables (missing from .env.example)
- Variables only in .env but not .env.example (documentation gap)
Step 5: Detect Services and Infer Permissions
Match variable names against known service patterns. See references/service-patterns.md for the complete list.
Categories:
- Database - Connection strings, credentials
- Authentication - JWT secrets, OAuth credentials
- Payment - Stripe, payment processor keys
- Cloud Services - AWS, GCP, Azure credentials
- Third-party APIs - Various service integrations
- Feature Flags - Toggle configurations
- Application Config - URLs, ports, modes
Permission levels:
- Critical - Full account access, billing, admin operations
- High - Read/write access to user data
- Medium - Limited API access, specific operations
- Low - Public keys, non-sensitive configuration
Step 6: Map Code Paths
For each used variable, document:
- File path where it's used
- Function/component context
- Purpose (inferred from surrounding code)
Example:
STRIPE_SECRET_KEY
├── src/lib/stripe.ts:15 - Stripe client initialization
├── src/api/webhooks/stripe.ts:8 - Webhook signature verification
└── src/api/checkout/route.ts:23 - Create checkout session
Step 7: Generate Report
Use the template in templates/env-audit-report.md to generate the final document.
Output to: ENV_AUDIT.md in project root (or user-specified location)
Step 8: Cleanup Unused Variables (Optional)
Trigger: User passes --cleanup flag or explicitly requests cleanup after reviewing the audit report.
8.1 Present Cleanup Candidates
Display unused variables with context:
UNUSED VARIABLES (candidates for removal):
1. OLD_API_KEY (.env, .env.local)
- Last modified: [file date]
- No code references found
2. DEPRECATED_SERVICE_URL (.env)
- Last modified: [file date]
- No code references found
8.2 Dynamic Access Check
Before confirming removal, search for dynamic access patterns that grep may have missed:
// These patterns indicate variables might be used dynamically:
process.env[variableName] // Dynamic key access
process.env[`${prefix}_KEY`] // Template literal access
Object.keys(process.env) // Iteration over all env vars
{ ...process.env } // Spread operator
Use Grep with patterns:
process\.env\[
Object\.keys\(process\.env\)
Object\.entries\(process\.env\)
\.\.\.process\.env
If dynamic access patterns found: Flag affected variables for manual review and warn user.
8.3 User Confirmation
Use AskUserQuestion to confirm each removal:
The following variables appear unused. Select which to remove:
[ ] OLD_API_KEY - Remove from .env, .env.local
[ ] DEPRECATED_SERVICE_URL - Remove from .env
[ ] Skip cleanup
⚠️ Variables will be backed up before removal.
Safety rules:
- NEVER auto-delete without explicit user confirmation
- NEVER remove variables from
.env.example(it serves as documentation) - Create backup before any modifications
8.4 Create Backups
Before modifying any file:
# Create timestamped backup directory
mkdir -p .env-backups/$(date +%Y%m%d_%H%M%S)
# Backup each env file being modified
cp .env .env-backups/$(date +%Y%m%d_%H%M%S)/.env.backup
cp .env.local .env-backups/$(date +%Y%m%d_%H%M%S)/.env.local.backup
8.5 Remove Confirmed Variables
For each confirmed variable:
- Use Edit tool to remove the line from each env file
- Preserve comments associated with the variable (line immediately above if it starts with #)
- Log the removal
8.6 Document Cleanup
Append cleanup summary to ENV_AUDIT.md:
## Cleanup Log
**Date:** [timestamp]
**Backup Location:** .env-backups/[timestamp]/
### Removed Variables
| Variable | Removed From | Reason |
|----------|--------------|--------|
| OLD_API_KEY | .env, .env.local | Unused - no code references |
### Preserved (Manual Review Required)
| Variable | Reason |
|----------|--------|
| DYNAMIC_VAR | Dynamic access pattern detected |
Step 9: Regression Prevention
Purpose: Validate that removing unused variables doesn't break the application.
9.1 Pre-Cleanup Baseline
Before removing any variables, capture baseline state:
# Check if project builds successfully
npm run build 2>&1 | tee .env-backups/pre-cleanup-build.log
echo $? > .env-backups/pre-cleanup-build-status
# Run tests if available
npm test 2>&1 | tee .env-backups/pre-cleanup-test.log
echo $? > .env-backups/pre-cleanup-test-status
Store exit codes:
0= Success (baseline is green)- Non-zero = Already failing (warn user but proceed if they confirm)
9.2 Dynamic Access Detection
Search for patterns that indicate runtime env var access:
High-risk patterns (require manual review):
// Config objects that spread env
const config = { ...process.env }
// Dynamic key construction
const key = `${SERVICE}_API_KEY`
process.env[key]
// Iteration patterns
Object.entries(process.env).filter(([k]) => k.startsWith('FEATURE_'))
// External config loaders
require('dotenv').config({ path: customPath })
Detection commands:
Grep: process\.env\[(?!['"][A-Z])
Grep: Object\.(keys|values|entries)\(process\.env\)
Grep: \.\.\.process\.env
Grep: dotenv.*config
If detected: List affected files and require explicit user acknowledgment before proceeding.
9.3 Post-Cleanup Validation
After removing variables, run validation:
# Verify build still succeeds
npm run build 2>&1 | tee .env-backups/post-cleanup-build.log
POST_BUILD_STATUS=$?
# Verify tests still pass
npm test 2>&1 | tee .env-backups/post-cleanup-test.log
POST_TEST_STATUS=$?
9.4 Regression Detection
Compare pre and post states:
| Check | Pre-Cleanup | Post-Cleanup | Status |
|---|---|---|---|
| Build | ✅ Pass | ✅ Pass | OK |
| Tests | ✅ Pass | ✅ Pass | OK |
If regression detected:
- Immediately alert user
- Offer automatic rollback:
⚠️ REGRESSION DETECTED Build/tests failed after removing variables. Options: 1. Rollback all changes (restore from backup) 2. Rollback specific variables 3. Investigate failure (show diff) 4. Proceed anyway (not recommended)
9.5 Automatic Rollback
If user requests rollback:
# Restore from backup
cp .env-backups/[timestamp]/.env.backup .env
cp .env-backups/[timestamp]/.env.local.backup .env.local
# Verify restoration
npm run build && npm test
9.6 Git Integration (Optional)
If in a git repository, offer branch-based cleanup:
# Create cleanup branch
git checkout -b env-cleanup/$(date +%Y%m%d)
# After cleanup, changes can be reviewed via PR
git add .env .env.local
git commit -m "chore: remove unused environment variables
Removed:
- OLD_API_KEY (unused)
- DEPRECATED_SERVICE_URL (unused)
Backup: .env-backups/[timestamp]/"
Benefits:
- Easy rollback via
git checkout - - Changes visible in PR review
- CI/CD will validate before merge
<reference_index> Service Patterns: references/service-patterns.md - Known services and their variable naming conventions </reference_index>
<success_criteria> Audit is complete when:
- All .env files discovered and parsed
- All code references found
- Variables categorized as used/unused/undeclared
- Services detected and permission levels assigned
- Code paths documented for each variable
- Markdown report generated with all sections
- Report saved to specified location
Cleanup is complete when (if --cleanup requested):
- Dynamic access patterns checked
- User confirmed variables to remove
- Backups created in .env-backups/
- Variables removed from env files (not .env.example)
- Cleanup log appended to report
Regression prevention is complete when:
- Pre-cleanup build/test baseline captured
- Post-cleanup validation run
- No regressions detected OR rollback performed
- Git branch created (if opted in) </success_criteria>