{"_id":"@ahmadawais/eeenv","name":"@ahmadawais/eeenv","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@ahmadawais/eeenv","version":"0.0.1","description":"Hide your project .env files in a per-project global vault so coding agents can't read them. Move, copy, hide, restore.","type":"module","bin":{"eeenv":"dist/cli.js"},"engines":{"node":">=18"},"scripts":{"build":"tsup","dev":"tsup --watch","start":"node dist/cli.js","test":"vitest run","test:watch":"vitest","lint":"biome check .","lint:fix":"biome check --write .","format":"biome format --write .","typecheck":"tsc --noEmit","check":"pnpm typecheck && pnpm lint && pnpm test && pnpm build","prepublishOnly":"pnpm check"},"keywords":["env","dotenv","secrets","security","ai","agents","prompt-injection","vault","cli"],"license":"MIT","author":{"name":"Ahmad Awais","url":"https://ahmadawais.com"},"repository":{"type":"git","url":"git+https://github.com/ahmadawais/eeenv.git"},"homepage":"https://github.com/ahmadawais/eeenv#readme","bugs":{"url":"https://github.com/ahmadawais/eeenv/issues"},"dependencies":{"commander":"^12.1.0","figlet":"^1.7.0","minimatch":"^10.2.5","ora":"^8.1.0","picocolors":"^1.0.1","zod":"^3.23.8"},"devDependencies":{"@biomejs/biome":"^1.8.3","@types/figlet":"^1.5.8","@types/node":"^20.14.0","tsup":"^8.2.0","typescript":"^5.5.4","vitest":"^2.0.0"},"gitHead":"4f1d1e3656a53b05cb9a3590db428d574f735ccf","_id":"@ahmadawais/eeenv@0.0.1","_nodeVersion":"24.18.0","_npmVersion":"12.0.1","dist":{"integrity":"sha512-ZzZUGdkCtPmu6WP1Ba24sSYJweZ6kwUKsfE1wUB+BJ80GUM4B3Yhg0+YgatpnKy4sG17BQZCv1wI/CCJMLHsgw==","shasum":"f9e667745600b0b508af7ae2e8e384cfa6ac7e98","tarball":"https://registry.npmjs.org/@ahmadawais/eeenv/-/eeenv-0.0.1.tgz","fileCount":4,"unpackedSize":35603,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBvNQNPFtLzyrOzP7LzX1raDVrqHfAmqYnbiUNQjxzh9AiAoqa0lxZVpnwuEsaaT5hYnxpXtts9KyX/Qp9G+erKl7Q=="}]},"_npmUser":{"name":"ahmadawais","email":"me@ahmadawais.com"},"directories":{},"maintainers":[{"name":"ahmadawais","email":"me@ahmadawais.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/eeenv_0.0.1_1784180120083_0.4803625429526299"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-16T05:35:19.924Z","0.0.1":"2026-07-16T05:35:20.216Z","modified":"2026-07-16T05:35:20.746Z"},"maintainers":[{"name":"ahmadawais","email":"me@ahmadawais.com"}],"description":"Hide your project .env files in a per-project global vault so coding agents can't read them. Move, copy, hide, restore.","homepage":"https://github.com/ahmadawais/eeenv#readme","keywords":["env","dotenv","secrets","security","ai","agents","prompt-injection","vault","cli"],"repository":{"type":"git","url":"git+https://github.com/ahmadawais/eeenv.git"},"author":{"name":"Ahmad Awais","url":"https://ahmadawais.com"},"bugs":{"url":"https://github.com/ahmadawais/eeenv/issues"},"license":"MIT","readme":"![eeenv](https://github.com/ahmadawais/eeenv/blob/main/.github/image.png?raw=true)\n\n# eeenv\n\nHide your project `.env` files from coding agents. Encrypts real values into\n`~/.eeenv/vault/`, then replaces local files with random tokens. Your passphrase\nis stored in the OS keychain — AI agents can't access it without your biometrics.\n\n## Install\n\n```sh\nnpm install -g @ahmadawais/eeenv\n```\n\n## Quick start\n\n```sh\n# From your project root — recursively finds every .env* / .dev.vars* file:\neeenv hide\n# First run: set a passphrase (stored in your OS keychain)\n\n# Coding agents now see random tokens instead of real values.\n# Work safely. When you're done:\n\neeenv restore\n# If passphrase not in keychain: prompts you to enter it\n```\n\n## How it works\n\n1. **Encryption**: Real values are encrypted with AES-256-GCM using your passphrase\n2. **Keychain**: Your passphrase lives in the OS keychain (macOS `security`, Linux `secret-tool`, Windows Credential Manager)\n3. **Redaction**: Local files get random tokens like `eeenv_redacted_abc123...`\n4. **Protection**: AI agents can't read the keychain without your system password/biometrics\n\n## Commands\n\n### `eeenv status`\n\nShow what's tracked and what's discoverable.\n\n```\n$ eeenv status\nProject: /Users/you/project\nVault:   ~/.eeenv/vault/Users/you/project\nKeychain: passphrase in keychain\n\n  hidden .env (2026-04-28T12:00:00.000Z)\n  hidden packages/api/.env (2026-04-28T12:00:00.000Z)\n\nUntracked env files:\n  · .env.production\n\nSkipped via .eeenv.json ignoreFiles:\n  · .env.local\n  · packages/legacy/.env\n```\n\n### `eeenv hide`\n\nEncrypts every discovered env file into `~/.eeenv/vault/<absolute-project-path>/`,\nthen rewrites local files with redacted random tokens.\n\n**First run** — prompts you to set a passphrase:\n```\n$ eeenv hide\nSet a vault passphrase: ********\nConfirm passphrase: ********\n✓ Passphrase saved to OS keychain.\n✓ hidden .env — vaulted real values, redacted 14 key(s) locally.\n✓ hidden packages/api/.env — vaulted real values, redacted 3 key(s) locally.\n• Run eeenv restore to put real values back.\n```\n\n**Subsequent runs** — uses existing passphrase from keychain:\n```\n$ eeenv hide\n✓ hidden .env — vaulted real values, redacted 14 key(s) locally.\n```\n\n**Double-hide protection** — blocks if files already redacted:\n```\n$ eeenv hide\n✗ Cannot hide — some files appear to already be redacted:\n  .env — already tracked in vault (run eeenv restore first)\n```\n\n**Before:**\n```\nSTRIPE_KEY=sk_live_supersecret\nNODE_ENV=production\n```\n\n**After:**\n```\nSTRIPE_KEY=eeenv_redacted_c87f3a1b2c4d5e6f7a8b9c0d1e2f3a4b\nNODE_ENV=production\n```\n\n### `eeenv restore`\n\nDecrypts files from the vault and restores them to their original locations.\n\n**Passphrase in keychain** — seamless restore:\n```\n$ eeenv restore\n✓ restored .env\n✓ restored packages/api/.env\n```\n\n**Passphrase not in keychain** — prompts to unlock:\n```\n$ eeenv restore\nVault is locked. Enter passphrase to unlock: ********\n✓ Vault unlocked.\n✓ restored .env\n✓ restored packages/api/.env\n```\n\n## What gets discovered\n\n`eeenv` walks your project **recursively** and picks up:\n\n| Pattern                 | Example                     |\n|-------------------------|-----------------------------|\n| `.env`                  | `.env`                      |\n| `.env.<anything>`       | `.env.local`, `.env.staging`|\n| `.dev.vars`             | `.dev.vars`                 |\n| `.dev.vars.<anything>`  | `.dev.vars.production`      |\n\n### Never touched\n\n| Category     | Examples                                                                                    |\n|-------------|---------------------------------------------------------------------------------------------|\n| Templates    | `.env.example`, `.dev.vars.example`, `.env.sample`, `.env.template`, `.env.dist`            |\n| Noise dirs   | `node_modules`, `.git`, `dist`, `build`, `.next`, `.turbo`, `.cache`, `coverage`, `vendor`, `.venv`, `.pnpm-store`, `.yarn`, `target`, `__pycache__` — [full list below](#skipped-directories) |\n| Symlinks     | Symlinked directories are never followed                                                    |\n\n## Config: `.eeenv.json`\n\nPlace this at your project root. All fields are optional.\n\n```json\n{\n  \"skipKeys\": [\"NODE_ENV\", \"DEBUG\", \"PORT\", \"CI\"],\n  \"ignoreFiles\": [\".env.local\", \"packages/legacy/**\"]\n}\n```\n\n### `skipKeys`\n\nCase-sensitive env key names that **keep their real values** locally after\n`eeenv hide`. The file is still vaulted — `eeenv restore` brings everything\nback. Useful for non-sensitive vars that apps need at runtime.\n\n### `ignoreFiles`\n\n[minimatch][] globs matched against the **project-relative path**\n(e.g. `apps/web/.env`). Files matching any pattern are **never vaulted and\nnever redacted**. `matchBase` is enabled, so a plain filename like\n`.env.local` matches everywhere in the tree.\n\n[minimatch]: https://github.com/isaacs/minimatch#readme\n\n### Built-in defaults\n\nEven without a `.eeenv.json`, these files are skipped:\n\n- `.env.local`\n- `.env.development`\n- `.env.test`\n\nOverride by setting `ignoreFiles` explicitly.\n\n## How the vault works\n\n```\n~/.eeenv/vault/\n└─ <absolute-project-path>/\n   ├─ manifest.json          # tracks which files are hidden\n   ├─ .env                   # encrypted real values (AES-256-GCM)\n   ├─ apps/\n   │  └─ web/\n   │     └─ .env             # encrypted\n   └─ packages/\n      └─ api/\n         ├─ .env             # encrypted\n         └─ .dev.vars        # encrypted\n```\n\nThe vault mirrors your project tree exactly. Files are encrypted with\nAES-256-GCM using your passphrase. The passphrase is stored in your OS\nkeychain — AI agents cannot access it without your system password/biometrics.\n\n## Security\n\n- **AES-256-GCM encryption**: Real values are encrypted, not just copied\n- **OS keychain**: Passphrase lives in macOS Keychain, Linux Secret Service,\n  or Windows Credential Manager — requires your biometrics/system password\n- **Double-hide protection**: Blocks `hide` if files already redacted or tracked\n- **Random tokens**: Each redacted value is a fresh 24-hex-char random token.\n  No deterministic mapping, no length leak.\n- **Permission-locked**: Vault files are created with mode `0o600`\n  (owner read/write only).\n- **Comment-preserving**: Comments, blank lines, and `export` statements are\n  preserved during redaction. Only the `VALUE` part of `KEY=VALUE` is\n  replaced.\n\n## Monorepos\n\nWorks automatically. Run from any directory — `eeenv` walks the tree\nfrom the current directory downward. A `.env` at `packages/api/.env` and\nanother at `apps/web/.env` are tracked separately under their relative\npaths. The vault mirrors the same structure. No collisions across packages.\n\n## Cloudflare Workers\n\n`.dev.vars` and `.dev.vars.*` files are discovered and processed identically\nto `.env` files. Same encryption, same redaction, same restore. Templates like\n`.dev.vars.example` are excluded.\n\n## Skipped directories\n\nRecursion skips these directories by name:\n\n`.git` `.hg` `.svn`\n`node_modules` `.pnpm-store` `.yarn` `.npm` `bower_components` `vendor`\n`dist` `build` `out` `output` `.output`\n`.next` `.nuxt` `.turbo`\n`.cache` `.parcel-cache`\n`.svelte-kit` `.astro`\n`.vercel` `.netlify` `.serverless` `.wrangler`\n`.eslintcache` `.rollup.cache` `.vite`\n`coverage` `.nyc_output`\n`.eeenv` `.idea` `.vscode-test`\n`target` `__pycache__` `.venv` `venv`\n\n## Reset everything\n\n```sh\n# Restore all vaulted files for the current project:\neeenv restore\n\n# Or nuke the entire vault:\nrm -rf ~/.eeenv\n```\n\n## Uninstall\n\n```sh\nnpm uninstall -g @ahmadawais/eeenv\nrm -rf ~/.eeenv\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-ec6f2511bb918f10f993fdd160d622fe"}