README
ΒΆ
capture
A static analysis CLI tool that identifies mismatches between environment variables declared in .env files and those referenced in source code.
Features
- π Detects environment variable usage in JavaScript, TypeScript, Go, Python, Ruby, PHP, Java, and Kotlin
- π Detects possible hardcoded secrets (API keys, tokens, private keys, and hardcoded credentials)
- π³ Analyzes Dockerfiles for ENV/ARG declarations and variable usage
- π§© Parses Docker Compose files (
docker-compose*.yml,compose.yml) for environment declarations, substitutions, andenv_filereferences - π Cross-checks variables between .env, Dockerfile, and source code
- π― Pattern-based detection without AST parsing for simplicity and speed
- β‘ Parallel source-file scanning with configurable workers (
--workers) - β‘ Incremental scanning with git-aware caching (
--incremental,.capture/cache.json) - π Watch mode with automatic re-scan on file changes (
--watch) - π οΈ Auto-fix missing env variables with backup support (
--fix,--dry-run,--yes) - π§Ύ Generate
.env.exampletemplates from detected source usage (template --output) - π Deterministic output for reliable CI/CD integration
- β‘ Memory-efficient streaming file processing
- π« Configurable directory ignore patterns
- π Clear reporting of unused and missing variables with file locations
Installation
Download Pre-built Binary
Download the latest release for your platform from the releases page.
Linux (x86_64):
curl -L https://github.com/yhaliwaizman/capture/releases/latest/download/capture_Linux_x86_64.tar.gz | tar xz
sudo mv capture /usr/local/bin/
macOS (Intel):
curl -L https://github.com/yhaliwaizman/capture/releases/latest/download/capture_Darwin_x86_64.tar.gz | tar xz
sudo mv capture /usr/local/bin/
macOS (Apple Silicon):
curl -L https://github.com/yhaliwaizman/capture/releases/latest/download/capture_Darwin_arm64.tar.gz | tar xz
sudo mv capture /usr/local/bin/
Windows:
Download capture_Windows_x86_64.zip from the releases page and extract.
Using Go Install
go install github.com/yhaliwaizman/capture/cmd/capture@latest
From Source
# Clone the repository
git clone https://github.com/yhaliwaizman/capture.git
cd capture
# Build the binary
go build -o capture ./cmd/capture
# Or use make
make build
# Install to GOPATH/bin
make install
Usage
Basic Scan
capture scan --dir ./project --env-file .env
Multiple Env Files (Last File Wins)
capture scan --dir ./project \
--env-file .env \
--env-file .env.local \
--env-file .env.production
With Ignore Patterns
capture scan --dir ./project --env-file .env --ignore vendor,tmp,cache
Incremental Scan
capture scan --dir ./project --env-file .env --incremental
Use --no-cache with --incremental to force a full scan.
Watch Mode
capture scan --dir ./project --env-file .env --watch
Watch mode runs an initial scan, then re-runs automatically on changes with a 500ms debounce.
Auto-fix Missing Variables
capture scan --dir ./project --env-file .env --fix --yes
--fix appends missing variables to the first --env-file and creates <env-file>.backup before writing.
Use --dry-run to preview changes without modifying files.
Generate .env.example Template
capture template --root . --output .env.example
The generated file groups variables by prefix (API_, DATABASE_, etc.) and sorts variables alphabetically within each group.
With Configuration File
# Auto-detects .capture.yaml/.capture.yml/.capture.json in current directory
capture scan
# Use explicit config file path
capture scan --config .capture.prod.yaml
Example Output
No mismatches:
No environment mismatches found.
With mismatches:
Declared but unused:
- OLD_API_KEY
- DEPRECATED_URL
Used but not declared:
- DATABASE_URL (src/db.go:15)
- REDIS_HOST (src/cache.js:8)
Code uses variables not in Dockerfile or .env:
- MISSING_VAR (src/app.js:10)
Dockerfile declares but code doesn't use:
- BUILD_VERSION
- NODE_ENV
Dockerfile uses undeclared variables:
- UNDEFINED_VAR (Dockerfile:15)
Possible hardcoded secrets:
- Stripe Key (src/config.js:10)
Suggestion: Move the value to an environment variable and load it at runtime.
Command-Line Options
scan command
--dir(required): Directory to scan for source files--env-file(required, repeatable): Path to an env file. When repeated, later files override earlier ones for declaration source.--ignore(optional): Comma-separated list of directories to ignore--format(optional): Output format -text(default),json, orsarif--workers(optional): Number of parallel workers for source file scanning (default: CPU count; set1for sequential)--incremental(optional): Only scan changed files using git change detection and cache results in.capture/cache.json--no-cache(optional): Disable cache usage and force a full scan (useful with--incremental)--watch(optional): Watch files and re-run scans automatically on change (500ms debounce)--fix(optional): Add missing variables to the first--env-filewith empty values (KEY=)--dry-run(optional): Preview--fixchanges without writing files (requires--fix)--yes(optional): Skip confirmation prompt when using--fix--config(optional): Path to config file. If not set,capturelooks for.capture.yaml, then.capture.yml, then.capture.jsonin the current directory.
template command
--root(optional): Directory to scan for source files (default:.)--output(optional): Output file path for generated template (default:.env.example)--ignore(optional): Comma-separated list of directories to ignore
Exit Codes
- 0: No mismatches detected (success)
- 1: Mismatches found (unused or missing variables)
- 2: Configuration error (missing file, invalid flags, permissions)
If one of multiple --env-file values is unreadable, capture prints a warning and continues with readable files.
If none of the provided/default env files are readable, capture exits with code 2.
Configuration File
Supported filenames (auto-discovery order):
.capture.yaml.capture.yml.capture.json
Supported keys:
root: .
env_files:
- .env
ignore:
- node_modules
format: text
workers: 8
incremental: true
no_cache: false
watch: false
fix: false
dry_run: false
yes: false
Command-line flags always override config file values.
Supported Languages
| Language | Patterns Detected |
|---|---|
| JavaScript | process.env.VAR, process.env["VAR"], process.env['VAR'] |
| TypeScript | process.env.VAR, process.env["VAR"], process.env['VAR'] |
| Go | os.Getenv("VAR"), os.LookupEnv("VAR") |
| Python | os.getenv("VAR"), os.environ["VAR"], os.environ['VAR'] |
| Ruby | ENV["VAR"], ENV['VAR'], ENV.fetch("VAR"), ENV.fetch('VAR') |
| PHP | $_ENV["VAR"], $_ENV['VAR'], $_SERVER["VAR"], $_SERVER['VAR'], getenv("VAR"), getenv('VAR') |
| Java | System.getenv("VAR"), System.getenv().get("VAR") |
| Kotlin | System.getenv("VAR"), System.getenv()["VAR"] |
| Dockerfile | ENV KEY=value, ARG KEY=default, $VAR, ${VAR} |
Dockerfile and Docker Compose Analysis
The tool automatically detects and analyzes Dockerfiles and Docker Compose files in your project:
- Detected files:
Dockerfile,Dockerfile.*,*.dockerfile - Declarations: Extracts
ENVandARGinstructions - Usage: Detects
$VARand${VAR}references in RUN, CMD, etc. - Cross-checks: Compares Dockerfile variables with .env and source code
- Compose files: Detects
docker-compose.yml,docker-compose.yaml,docker-compose.*.yml,compose.yml,compose.yaml - Compose declarations: Extracts service
environmententries from list and map syntax - Compose substitutions: Detects
${VAR}and${VAR:-default}patterns in compose values - Compose env_file: Detects missing
env_filereferences
Dockerfile Patterns
Declarations:
ENV API_KEY=default_value
ENV DATABASE_URL postgres://localhost
ENV A=1 B=2 C=3
ARG BUILD_VERSION
ARG NODE_ENV=production
Usage:
RUN echo "Version: $BUILD_VERSION"
RUN echo "API: ${API_KEY}"
Multi-Stage Dockerfiles
The tool analyzes all stages in multi-stage builds:
FROM node:18 AS builder
ENV BUILD_ENV=production
ARG BUILD_VERSION
FROM node:18-alpine AS runtime
ENV RUNTIME_ENV=production
RUN echo "Build: $BUILD_ENV"
All ENV and ARG declarations from all stages are collected and cross-checked.
Development
Build
make build
Run Tests
# Run all tests
make test
# Run tests with coverage
make test-coverage
Clean Build Artifacts
make clean
CI/CD Integration
The tool is designed for CI/CD pipelines with deterministic output and standard exit codes:
Text Format (Human-Readable):
# GitHub Actions example
- name: Check environment variables
run: |
./capture scan --dir . --env-file .env
JSON Format (Machine-Readable):
# GitHub Actions with JSON parsing
- name: Check environment variables
run: |
OUTPUT=$(./capture scan --dir . --env-file .env --format json)
echo "$OUTPUT" | jq '.summary.mismatches_found'
# GitLab CI example with JSON
check-env:
script:
- ./capture scan --dir . --env-file .env
SARIF Format (GitHub Code Scanning):
# GitHub Actions with SARIF upload
- name: Run capture scan
run: capture scan --dir . --env-file .env --format sarif > results.sarif
- name: Upload SARIF results
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
See docs/SARIF_OUTPUT.md for the full SARIF output format documentation.
How It Works
- Parse .env file: Extracts declared variable names matching `^[A-Z][A-Z0-9_]*# capture
- Walk directory tree: Recursively finds source files (.js, .ts, .go, .py, .rb, .php) and Dockerfiles
- Analyze Dockerfiles: Extracts ENV/ARG declarations and variable usage
- Detect usage: Applies regex patterns to find environment variable references in source code
- Compare sets: Identifies mismatches:
- Unused: declared in .env but not used in code
- Missing: used in code but not declared in .env
- Code uses variables not in Dockerfile or .env
- Dockerfile declares variables unused in code
- Dockerfile uses undeclared variables
- Generate report: Outputs deterministic, sorted results
License
MIT
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Quick Start for Contributors
# Setup development environment
git clone https://github.com/yhaliwaizman/capture.git
cd capture
./scripts/setup-hooks.sh
# Make changes and commit using conventional commits
git commit -m "feat: add new feature"
# Push and create PR
git push origin feature-branch
We use:
- Conventional Commits for commit messages
- Release Please for automated releases
- Pre-commit hooks for code quality
See docs/DEVELOPMENT.md for detailed development guide.