Cross-project .env scanner, auditor, and drift detector.
Know what secrets live where β without exposing them.
Install β’ Commands β’ CI Integration β’ Why?
Your
.envfiles are scattered across dozens of projects. Some are encrypted, some aren't. Some are gitignored, some aren't. Some have keys that don't exist in production. You don't know which ones AI agents can read.enview gives you a single terminal command to see all of it.
If you're a developer shipping multiple projects, you probably have:
- π Plaintext API keys sitting in
.envfiles that any LLM, build script, or npm postinstall can read - π³οΈ Missing keys between dev and production that cause deploy failures
- π€· No idea which projects use encryption (dotenvx, sops, etc.) and which don't
- π No inventory of what secrets exist across your entire workspace
enview is a zero-config CLI that scans your project directories and tells you the truth.
npx @pickbitsai/enview scan ~/code # try it instantly
npm install -g @pickbitsai/enview # or install globallyThe package is scoped, but the command it installs is plain enview β every
example below works as written once it's on your PATH.
Recursively discover all .env files across your projects. See encryption status, gitignore coverage, and modification dates at a glance.
enview scan ~/code ~/projects ~/freelanceπ‘οΈ enview scan β 4 projects, 6 env files
ββββββββββββββββ¬ββββββββββββββββββ¬βββββββββββββ¬βββββββ¬βββββββββββββββββ¬βββββββββββββ¬βββββββββββ
β Project β File β Env β Keys β Encrypted β .gitignore β Modified β
ββββββββββββββββΌββββββββββββββββββΌβββββββββββββΌβββββββΌβββββββββββββββββΌβββββββββββββΌβββββββββββ€
β echoforge β .env β developmentβ 4 β π‘ dotenvx 2/4 β β
yes β 3d ago β
β β .env.production β production β 4 β π dotenvx β β
yes β 1w ago β
ββββββββββββββββΌββββββββββββββββββΌβββββββββββββΌβββββββΌβββββββββββββββββΌβββββββββββββΌβββββββββββ€
β my-saas β .env β developmentβ 12 β π none β β NO β 2mo ago β
ββββββββββββββββΌββββββββββββββββββΌβββββββββββββΌβββββββΌβββββββββββββββββΌβββββββββββββΌβββββββββββ€
β side-project β .env β developmentβ 3 β π none β β
yes β today β
ββββββββββββββββ΄ββββββββββββββββββ΄βββββββββββββ΄βββββββ΄βββββββββββββββββ΄βββββββββββββ΄βββββββββββ
Find plaintext secrets, missing .gitignore entries, partial encryption, and environment drift β all in one pass.
enview audit ~/code
enview audit --strict ~/code # exit code 1 on critical findings (for CI)π‘οΈ enview audit β 6 findings
ββββββββββββ¬βββββββββββββ¬βββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββ
β Level β Project β File β Finding β
ββββββββββββΌβββββββββββββΌβββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββ€
β CRITICAL β my-saas β .env β Plaintext .env file is NOT gitignored β
ββββββββββββΌβββββββββββββΌβββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββ€
β CRITICAL β my-saas β .env β 3 sensitive keys in plaintext: β
β β β β STRIPE_SECRET_KEY, DATABASE_PASSWORDβ¦ β
ββββββββββββΌβββββββββββββΌβββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββ€
β WARN β echoforge β .env β Partial encryption β 2/4 keys encrypted β
ββββββββββββΌβββββββββββββΌβββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββ€
β WARN β echoforge β .env β .env.prod β 1 key in .env missing from .env.production β
ββββββββββββ΄βββββββββββββ΄βββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββ
β οΈ 2 critical issue(s) require immediate attention
List every key name across every project. Values are never shown. Encrypted keys get π, plaintext secrets get
enview keys ~/codeπ enview keys β key inventory (values never shown)
π echoforge
.env (development)
π ANTHROPIC_API_KEY
π DATABASE_URL
π OLLAMA_HOST
π APP_NAME
.env.production (production)
π ANTHROPIC_API_KEY
π DATABASE_URL
π REDIS_URL
π APP_NAME
Find keys that exist in one environment but not another. Catches the "works on my machine" deploy failures.
enview drift ~/codeποΈ enview drift β environment key comparison
π echoforge
βββββββββββββββ¬βββββββ¬ββββββββββββββββββ
β Key β .env β .env.production β
βββββββββββββββΌβββββββΌββββββββββββββββββ€
β OLLAMA_HOST β β β β missing β
βββββββββββββββΌβββββββΌββββββββββββββββββ€
β REDIS_URL β β β β β
βββββββββββββββ΄βββββββ΄ββββββββββββββββββ
A working-tree scan answers "what is exposed right now". It cannot answer the expensive question: what did I commit last year and forget? Deleting a .env and gitignoring it changes nothing about the copy in every clone, fork and CI cache β the credential is published until it is rotated.
enview history ~/codeπ°οΈ enview history β 4 risky paths across 3 repos
βββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββ¬ββββββββββββββ¬ββββββββββββββββ
β Repo β Path in history β Kind β Keys β Still tracked β
βββββββββββββββββΌβββββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββΌββββββββββββββΌββββββββββββββββ€
β CoachMark β .env β environment file β 4 sensitive β no β
β PantryPlanner β android/app/release-keystore.jks β private key or keystore β β β no β
βββββββββββββββββ΄βββββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββ΄ββββββββββββββ΄ββββββββββββββββ
Walks --all, so a secret on an abandoned branch still counts. Scoped to risky paths β env files, private keys, keystores, .npmrc, service-account JSON β rather than grepping every blob, because a scan slow enough to be switched off protects nothing. Key names are recovered from historical blobs; values are never returned.
The one place enview handles values. Everything else β CLI, library, any dashboard reading them β sees names and status only.
enview ui ~/codeMasked values with reveal and copy, add/edit/delete/rename, and one-click remediation for what the scan found: generate a .env.example with values stripped, add a file to .gitignore. Every write makes a timestamped .bak first.
A revealed value re-masks itself after 30 seconds, with the countdown on the button β screen shares and recordings are a likelier way to lose a credential than an attacker is. The mask is a fixed width and no length is ever returned, so a short value and a long one look the same.
Security model β one user, one machine. Binds 127.0.0.1; validates Host and Origin on every request, which is what defeats DNS rebinding; requires a token printed once in your terminal; no CORS, restrictive CSP, no telemetry, no external requests. Only files found by the scan can be touched β an allowlist, not path sanitising. Do not put it behind a tunnel, port-forward or reverse proxy; it has no multi-user concept.
Values cross the wire one key at a time, only when you ask, and are never cached or logged.
Working-tree audit plus history scan, exiting non-zero on anything critical. Built for cron, Task Scheduler or CI β a guard that always exits 0 is decoration.
enview protect ~/code # exits 1 if anything critical
enview protect ~/code --quiet # silent unless there is something to say
enview protect ~/code --no-history # much faster; skips the history walk
enview protect ~/code --json # for automationπ‘οΈ enview protect β 4 critical findings
2 on disk Β· 2 in git history
Findings deduplicate across the two scans: when history has the real answer, the working-tree inference is dropped rather than reported twice.
Run it on a schedule
# cron β 9am daily
0 9 * * * npx @pickbitsai/enview protect ~/code --quiet
# Windows Task Scheduler
schtasks /create /tn "enview protect" /tr "npx @pickbitsai/enview protect C:\code --quiet" /sc daily /st 09:00Use --json for machine-readable output and --strict to fail builds:
# GitHub Actions
- name: Audit secrets
run: npx @pickbitsai/enview audit --strict --json . > audit-results.json# GitLab CI
audit:secrets:
script:
- npx @pickbitsai/enview audit --strict .
allow_failure: false| Detection | Description |
|---|---|
| Plaintext secrets | API keys, tokens, passwords stored without encryption |
| Missing .gitignore | .env files that could be committed to version control |
| Partial encryption | Files where some keys are encrypted but others aren't |
| Environment drift | Keys present in dev but missing in production (or vice versa) |
| Encryption type | Identifies dotenvx, SOPS, age, and other encryption schemes |
| Sensitive key patterns | Flags keys matching *_API_KEY, *_SECRET, *_PASSWORD, *_TOKEN, etc. |
AI coding agents (Claude Code, Cursor, Copilot, Aider) run in your terminal with access to your filesystem. A plaintext .env file is trivially readable by any process β including AI agents, npm postinstall scripts, and supply chain attacks.
enview helps you answer: "Which of my projects have secrets that an AI agent could read right now?"
Pair it with dotenvx to encrypt everything it flags.
| Flag | Description |
|---|---|
--json |
Output as JSON (all commands) |
--strict |
Exit code 1 on critical findings (audit only) |
-d, --depth <n> |
Max directory depth (default: 6) |
enview automatically identifies:
- dotenvx β
encrypted:prefix withDOTENV_PUBLIC_KEYheader - SOPS β
ENC[AES256_GCM,...]values orsopsmetadata - age β
age-encryption.orgmarkers
node_modules,.git,vendor,dist,build,target, etc..env.example,.env.sample,.env.template.env.keys(dotenvx private key files β never scanned)
PRs welcome. Some ideas:
-
enview rotateβ Track key rotation history via git log -
enview initβ Bootstrap dotenvx encryption for unprotected projects -
enview watchβ File watcher that alerts on new plaintext secrets - TUI dashboard mode (blessed/ink)
- 1Password / Bitwarden vault cross-reference
- Pre-commit hook integration
-
.enviewrcconfig file for custom scan roots
MIT