{"id":40749803,"url":"https://github.com/forattini-dev/vaulter","last_synced_at":"2026-02-19T19:00:52.153Z","repository":{"id":333560277,"uuid":"1135219319","full_name":"forattini-dev/vaulter","owner":"forattini-dev","description":"Multi-Backend Environment \u0026 Secrets Manager. One CLI to manage all your environment variables.","archived":false,"fork":false,"pushed_at":"2026-02-17T19:11:46.000Z","size":2177,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-17T22:32:29.197Z","etag":null,"topics":["aes-256-gcm","ai","claude","cli","dotenv","encryption","env","environment","k8s","kubernetes","mcp","minio","monorepo","r2","s3","secrets","terraform","terragrunt","variables","vaulter"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/forattini-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-15T19:59:41.000Z","updated_at":"2026-02-17T19:11:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/forattini-dev/vaulter","commit_stats":null,"previous_names":["forattini-dev/vaulter"],"tags_count":63,"template":false,"template_full_name":null,"purl":"pkg:github/forattini-dev/vaulter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forattini-dev%2Fvaulter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forattini-dev%2Fvaulter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forattini-dev%2Fvaulter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forattini-dev%2Fvaulter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/forattini-dev","download_url":"https://codeload.github.com/forattini-dev/vaulter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forattini-dev%2Fvaulter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29623612,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T13:04:20.082Z","status":"ssl_error","status_checked_at":"2026-02-19T13:03:33.775Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes-256-gcm","ai","claude","cli","dotenv","encryption","env","environment","k8s","kubernetes","mcp","minio","monorepo","r2","s3","secrets","terraform","terragrunt","variables","vaulter"],"created_at":"2026-01-21T16:00:19.803Z","updated_at":"2026-02-19T19:00:52.145Z","avatar_url":"https://github.com/forattini-dev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# vaulter\n\n### Multi-Backend Environment \u0026 Secrets Manager\n\n[![npm version](https://img.shields.io/npm/v/vaulter.svg?style=flat-square\u0026color=F5A623)](https://www.npmjs.com/package/vaulter)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178C6?style=flat-square\u0026logo=typescript\u0026logoColor=white)](https://www.typescriptlang.org/)\n[![Node.js](https://img.shields.io/badge/Node.js-22+-339933?style=flat-square\u0026logo=node.js\u0026logoColor=white)](https://nodejs.org/)\n[![MCP](https://img.shields.io/badge/MCP-Claude_AI-7C3AED?style=flat-square\u0026logo=anthropic\u0026logoColor=white)](https://modelcontextprotocol.io/)\n\nOrganizes your `.env` files with structure and best practices.\n\u003cbr\u003e\nPowered by [dotenv](https://github.com/motdotla/dotenv) for parsing. Store secrets anywhere: S3, MinIO, R2, or filesystem.\n\n\u003c/div\u003e\n\n---\n\n## Installation\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/forattini-dev/vaulter/main/install.sh | sh\n# or: npm install -g vaulter\n```\n\n## Quick Start\n\n### Minimal\n\n```bash\nvaulter init                                          # Initialize project\nvaulter key generate --name master                    # Generate encryption key\nvaulter change set DATABASE_URL=\"postgres://...\" -e dev  # Set secret\nvaulter change set PORT::3000 -e dev                     # Set config (plain)\nvaulter change set NODE_ENV=local -e dev                 # Set config (sensitive=false)\nvaulter change move API_KEY --from shared --to api -e dev # Move variable to service\nvaulter change move API_KEY --from shared -e dev -s svc-notifications   # Infer destination service\nvaulter plan -e dev                                      # Preview changes before applying\neval $(vaulter export shell -e dev)                   # Export to shell\n```\n\n### End-to-End (Monorepo, `web` + `api`)\n\nThis flow shows local editing, team sharing, and promotion across multiple environments.\n\n```bash\n# 0) Initialize + discover services\nvaulter init --monorepo\nvaulter key generate --name master\nvaulter services\n\n# 1) Create/override vars locally (offline by default)\n# `local set` writes only to `.vaulter/local/*`; use `-e/--env` only for backend-aware operations.\nvaulter local set NEXT_PUBLIC_APP_NAME=Portal        --shared\nvaulter local set NODE_ENV=local                    --shared\nvaulter local set DATABASE_URL=postgres://...        -s api\nvaulter local set REDIS_URL=redis://...             -s api\nvaulter local set QUEUE_ENABLED::true               -s api\nvaulter local set WORKER_CONCURRENCY::4             -s web\nvaulter local pull --all                             # Generates .env for local run (all outputs)\nvaulter local diff                                # Review local overrides\n\n# 2) Share source of truth with team (backend sync)\nvaulter local push --all -e dev\n\n# 3) Team members pull and generate local envs\nvaulter local sync -e dev\nvaulter local pull --all\n\n# 4) Promote the same managed set to multiple environments\nfor ENV in dev stg prd; do\n  echo \"Deploying to $ENV\"\n  vaulter plan -e \"$ENV\"\n  vaulter apply -e \"$ENV\" $( [ \"$ENV\" = \"prd\" ] \u0026\u0026 echo '--force' )\ndone\n\n# 5) Run your scripts with vaulter-managed variables\nvaulter run -e dev -- pnpm start                  # Local run with local overrides\nvaulter run -e dev -s web -- pnpm --dir apps/web dev\nvaulter run -e dev -s api -- pnpm --dir apps/api lint\nvaulter run -e stg -s api -- pnpm --dir apps/api migrate\nvaulter run -e prd -- docker compose -f ./deploy/docker/docker-compose.yml up\n\n# 6) Export service-specific artifacts per environment\n# Config-like outputs\nvaulter export env -e dev --service api \u003e apps/api/.env\nvaulter export env -e stg --service web \u003e apps/web/.env\nvaulter export shell -e prd --service api \u003e /tmp/api-env.sh\n\n# Kubernetes artifacts\nvaulter export k8s-secret -e dev --service api --name api-secrets\nvaulter export k8s-secret -e dev --service web --name web-secrets\nvaulter export k8s-secret -e stg --service api --name api-secrets\nvaulter export k8s-secret -e prd --service api --name api-secrets\n\n# Deployment formats\nvaulter export k8s-configmap -e prd --service api --name api-configmap\nvaulter export helm -e prd --service api --name api-values\n```\n\n\u003e `--force` is required on `apply -e prd` and other production-like environments.\n\n---\n\n## 🔄 Development Workflow\n\nVaulter follows a **backend-sync** workflow where the backend is the source of truth and local overrides are for personal customization.\n\n### The Golden Rule\n\n\u003e **Backend is the source of truth. Everything syncs via backend.**\n\n| Component | Git Status | Purpose |\n|:----------|:-----------|:--------|\n| **`.vaulter/config.yaml`** | ✅ Committed | Project configuration |\n| **`.vaulter/local/*`** | ❌ Gitignored | Personal local overrides |\n| **`*.env` files** | ❌ Gitignored | Generated outputs |\n\n### Directory Structure\n\n```\n.vaulter/\n├── config.yaml              # ✅ Committed - Project config\n├── local/                   # ❌ Gitignored - Personal overrides\n│   ├── configs.env          # Non-sensitive overrides (DEBUG, PORT)\n│   ├── secrets.env          # Sensitive overrides (test API keys)\n│   └── services/            # Monorepo per-service overrides\n│       └── api/\n│           ├── configs.env\n│           └── secrets.env\n└── dev/                     # ❌ Gitignored - Environment data (--dir mode)\n    ├── configs.env          # Shared non-sensitive vars\n    ├── secrets.env          # Shared sensitive vars\n    └── services/            # Monorepo service vars\n        └── api/\n            ├── configs.env\n            └── secrets.env\n\napps/web/.env                # ❌ Gitignored - Generated output\napps/api/.env                # ❌ Gitignored - Generated output\n```\n\n**Directory modes:**\n- `.vaulter/local/` - Personal overrides (never synced to backend)\n- `.vaulter/{env}/` - Environment data (synced with `--dir` mode)\n\n### .gitignore Setup\n\n```gitignore\n# Vaulter - only commit config.yaml\n.vaulter/local/\n*.env\n.env.*\n```\n\n### Daily Workflow\n\n```bash\n# 1. Start: Pull latest from backend + apply your local overrides\nvaulter local pull\n\n# 2. Work: Add personal overrides (not shared with team)\nvaulter local set DEBUG::true                  # Shared override\nvaulter local set PORT::3001                   # Service-specific (inferred from cwd in monorepo)\n\n# 3. Add new variable for team? Push to backend\nvaulter local set NEW_VAR=value --shared        # Personal scratch pad\nvaulter local push                             # Share scratch locally with team\nvaulter plan -e dev                            # Preview changes (recommended)\nvaulter apply -e dev                           # Apply after approval\n\n# 4. Check: See what's different\nvaulter diff -e dev                             # Local vs backend diff\n\n# 5. Promote: Clone to staging/production\nvaulter clone dev stg --dry-run                # Preview\nvaulter clone dev stg                          # Execute\n```\n\n### Environment Promotion Flow\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                     DEVELOPMENT WORKFLOW                         │\n├─────────────────────────────────────────────────────────────────┤\n│                                                                  │\n│   LOCAL (.vaulter/local/)      ◄── Personal only (gitignored)   │\n│   ├── configs.env                                               │\n│   └── secrets.env                                               │\n│          │                                                       │\n│          │ merged on `vaulter local pull`                       │\n│          ▼                                                       │\n│                                                                  │\n│   BACKEND (S3/MinIO)           ◄── Source of truth (synced)     │\n│   ├── dev/  ──────────────────────────────────────────────┐     │\n│   │   └── all vars (encrypted)                            │     │\n│   │                                                       │     │\n│   ├── stg/  ◄─────── vaulter clone dev stg ──────────────┤     │\n│   │   └── all vars (encrypted)                            │     │\n│   │                                                       │     │\n│   └── prd/  ◄─────── vaulter clone stg prd ──────────────┘     │\n│       └── all vars (encrypted)                                   │\n│                                                                  │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n### Team Collaboration\n\nTeam collaboration assumes one shared truth for each environment (backend) and private, local overrides per developer.\n\n**New team member setup (2 minutes):**\n```bash\ngit clone \u003crepo\u003e                    # Gets .vaulter/config.yaml\nexport VAULTER_KEY_DEV=\u003cfrom-team\u003e  # Get key securely from team\nvaulter local sync -e dev           # Pull remote vars to .vaulter/local/\nvaulter local pull --all            # Generate .env files (offline)\n```\n\n**Why this is stable for teams**\n\n- `vaulter local set` is always a private, working-copy edit. It does **not** change what others consume by itself.\n- `vaulter local push` is how you publish team-visible changes from local overrides.\n- `vaulter local sync` is how others consume published changes.\n- Use environment-specific gates (`status`, `diff`, and `plan/apply`) before merging critical updates.\n\n**Recommended sharing flow (single variable):**\n```bash\n# 1) Add locally first\nvaulter local set --shared NEW_FEATURE::enabled  # Shared config\nvaulter local diff                                 # Verify local change before publishing\n\n# 2) Optional dry-run share preview\nvaulter local push --shared --dry-run -e dev         # Checks what would be pushed\n\n# 3) Share to backend (explicit approval step before running)\nvaulter local push --shared -e dev\n\n# 4) Notify team\n# \"New var published. Run: vaulter local sync -e dev \u0026\u0026 vaulter local pull --all\"\n```\n\n**Monorepo service rule (recommended):**\n\n- Defaults are shared only when genuinely global.\n- Service behavior should live in service scope (`-s svc-*`) unless explicitly cross-service.\n- Keep service ownership rules documented in `.vaulter/config.yaml` (`policy`), so mistakes are prevented early.\n\n**Conflict resolution if two devs edit same key**\n\n```bash\nvaulter local diff -s \u003cservice\u003e          # See your local delta\nvaulter local sync -e dev                # Pull latest from backend\nvaulter local pull --all                  # Rebuild outputs\nvaulter local diff -s \u003cservice\u003e          # Re-check before pushing\n```\n\nIf divergence remains:\n- Ask one owner to pause and re-publish.\n- Prefer `vaulter plan -e dev` + manual review for sensitive or cross-service keys.\n\n**Important:** Most `local` commands are local-only. Passing `-e/--env` is only needed when publishing or syncing with backend.\n\n### MCP Tools for Workflow\n\n| Task | Tool |\n|:-----|:-----|\n| Check health | `vaulter_status action=\"scorecard\"` |\n| Pull with overrides | `vaulter_local action=\"pull\"` |\n| Set shared override | `vaulter_local action=\"shared-set\" key=\"DEBUG\" value=\"true\"` |\n| Set service override | `vaulter_local action=\"set\" key=\"PORT\" value=\"3001\"` |\n| See differences | `vaulter_diff` |\n| Compare environments | `vaulter_search source=\"dev\" target=\"prd\"` |\n\n---\n\n## What is Vaulter?\n\nVaulter is an **opinionated organizer** for your environment variables. It uses [dotenv](https://github.com/motdotla/dotenv) under the hood for parsing `.env` files - we don't reinvent the wheel, we just add structure.\n\n```bash\n# Install in your project\npnpm add vaulter\n# or: npm install vaulter\n```\n\n**What vaulter adds on top of dotenv:**\n\n| Feature | dotenv | vaulter |\n|:--------|:------:|:-------:|\n| Parse `.env` files | ✅ | ✅ (uses dotenv) |\n| Organize by environment (dev/stg/prd) | ❌ | ✅ |\n| Separate local vs deploy files | ❌ | ✅ |\n| Auto-detect environment (local/CI/K8s) | ❌ | ✅ |\n| Encrypted remote storage | ❌ | ✅ |\n| Sync between team members | ❌ | ✅ |\n| Export to K8s, Helm, Terraform | ❌ | ✅ |\n\n**Philosophy**: Your local `.env` stays local (gitignored). Configs are committed. Secrets are encrypted in your own storage.\n\n---\n\n## Quick Start (Local Development)\n\n```typescript\n// app.ts\nimport { config } from 'vaulter'\n\nconfig() // Loads from .vaulter/local/ (configs.env + secrets.env)\n```\n\n```bash\n# Run commands with env vars loaded\nnpx vaulter run -- pnpm dev\n\n# Or pull from backend first\nvaulter local pull\n```\n\nThat's it! For most local development, vaulter is just a structured dotenv.\n\n---\n\n## 🩺 Health Check - Status\n\n**Always start with `vaulter status`** to diagnose your setup:\n\n```bash\nvaulter status -e dev\nvaulter status -e dev --offline\n```\n\nStatus performs **up to 18 checks** online, or a local-first subset in `--offline`.\n\n| Check | What It Does |\n|-------|--------------|\n| ✅ **Connection** | Tests backend connectivity (skipped in `--offline`) |\n| ✅ **Latency** | Measures operation speed |\n| ✅ **Permissions** | Validates read/write/delete access |\n| ✅ **Encryption** | Tests encrypt → decrypt round-trip |\n| ✅ **Sync Status** | Compares local vs remote |\n| ✅ **Security** | Detects .env in git, weak keys |\n| ✅ **Scope Policy** | Checks `shared` vs `service` assignment rules |\n| ✅ **Perf Config** | Suggests cache/warmup/concurrency tuning |\n| ✅ **+8 more** | Config, project, environment, backend, keys, etc. |\n\n**Example output:**\n\n```\n✓ ok: 15 | ⚠ warn: 1 | ✗ fail: 1\n\n✓ connection: connected (24 vars in dev)\n✓ latency: read=45ms, list=67ms\n✓ permissions: read/write/delete OK\n✓ encryption: round-trip successful\n⚠ sync-status: 5 local-only, 3 remote-only, 2 conflicts\n✗ security: 2 .env files tracked in git\n  → Add to .gitignore immediately\n```\n\n**When to use:**\n- 🆕 Initial setup - validate configuration\n- 🐛 Debugging - identify root cause\n- 🚀 Pre-deploy - ensure everything is synced\n- 🔄 Routine - weekly health check\n\n### Runbook local (`scripts/vaulter-verify-dev.sh`)\n\nFor a quick pre-deploy validation in local/dev workflows:\n\n```bash\nVAULTER_VERIFY_ENV=dev pnpm run verify:vaulter\nVAULTER_VERIFY_OFFLINE=0 VAULTER_VERIFY_REQUIRE_CONFIG=1 pnpm run verify:vaulter\n```\n\nThe script runs:\n\n- `vaulter status -e \u003cenv\u003e -v [--offline]` (offline by default)\n- `vaulter diff -e \u003cenv\u003e --values`\n- `vaulter list -e \u003cenv\u003e`\n\nIt writes an execution log under `artifacts/vaulter-health/` for auditability.\n\n**For AI Agents:** Call `vaulter_status action=\"scorecard\"` once at the start of a new session (or when operations fail / environments change) to understand the current state before performing sensitive operations.\n\nSee [docs/DOCTOR.md](docs/DOCTOR.md) for complete guide.\n\n---\n\n## Commands\n\n### Setup\n\n| Command | Description |\n|:--------|:------------|\n| `init` | Initialize project config |\n| `init --split` | Initialize with split mode (configs/secrets dirs) |\n\n### Health\n\n| Command | Description |\n|:--------|:------------|\n| `status -e \u003cenv\u003e` | Full diagnostic report with checks and suggestions |\n\n### Mutations (`change`)\n\n| Command | Description |\n|:--------|:------------|\n| `change set KEY=val -e \u003cenv\u003e` | Set secret (encrypted) |\n| `change set KEY::val -e \u003cenv\u003e` | Set config (plain text) |\n| `change set KEY:=123 -e \u003cenv\u003e` | Set typed secret (number/boolean) |\n| `change delete \u003ckey\u003e -e \u003cenv\u003e` | Delete variable |\n| `change move \u003ckey\u003e --from \u003cscope\u003e --to \u003cscope\u003e -e \u003cenv\u003e` | Move/copy variable between scopes |\n| `change import -f \u003cfile\u003e -e \u003cenv\u003e` | Import variables from file |\n| `list -e \u003cenv\u003e` | List all variables |\n\n**Set syntax**: `=` encrypted secret · `::` plain config · `:=` typed secret\n\nIn monorepo mode, when `--service` is resolved, one of `--from` or `--to` can be omitted and inferred from the active service.\n\n### Plan \u0026 Apply\n\n| Command | Description |\n|:--------|:------------|\n| `plan -e \u003cenv\u003e` | Compute diff local vs backend, generate plan artifact |\n| `apply -e \u003cenv\u003e` | Execute plan, push changes to backend |\n| `diff -e \u003cenv\u003e` | Quick diff without plan artifacts |\n| `plan --dir -e \u003cenv\u003e` | Plan from `.vaulter/{env}/` directory |\n| `plan [--plan-output \u003cfile\u003e] -e \u003cenv\u003e` | Write plan artifact (`.json` + `.md`). If `--plan-output` is omitted, defaults to `artifacts/vaulter-plans/\u003cproject\u003e-\u003cenv\u003e-\u003ctimestamp\u003e.*` |\n\n### Recommended daily path\n\n- `vaulter local pull` → `vaulter local set` → `vaulter local push` (when ready)\n- `vaulter change set` → `vaulter change move` → `vaulter plan -e \u003cenv\u003e` → `vaulter apply -e \u003cenv\u003e`\n- `vaulter plan -e \u003cenv\u003e` → validate → `vaulter apply -e \u003cenv\u003e`\n- `vaulter status -e \u003cenv\u003e` for quick pre-flight health check\n\n### Export\n\n| Command | Description |\n|:--------|:------------|\n| `export shell -e \u003cenv\u003e` | Export for shell `eval $(...)` |\n| `export k8s-secret -e \u003cenv\u003e` | Generate Kubernetes Secret (sensitive vars only) |\n| `export k8s-configmap -e \u003cenv\u003e` | Generate Kubernetes ConfigMap (config vars only) |\n| `export helm -e \u003cenv\u003e` | Generate Helm values.yaml |\n| `export terraform -e \u003cenv\u003e` | Generate Terraform .tfvars |\n| `export docker -e \u003cenv\u003e` | Docker env-file format |\n| `export vercel -e \u003cenv\u003e` | Vercel environment JSON |\n| `export github-actions -e \u003cenv\u003e` | GitHub Actions secrets |\n\n### Services (monorepo)\n\n| Command | Description |\n|:--------|:------------|\n| `services list` | List discovered services |\n| `services` | Same as `services list` |\n\n### Audit \u0026 Rotation\n\n| Command | Description |\n|:--------|:------------|\n| `audit list -e \u003cenv\u003e` | List audit entries |\n| `audit stats -e \u003cenv\u003e` | Show statistics |\n| `rotation list -e \u003cenv\u003e` | Check rotation status |\n| `rotation run -e \u003cenv\u003e` | CI/CD gate for overdue secrets |\n\n### Key Management\n\n| Command | Description |\n|:--------|:------------|\n| `key generate --name \u003cn\u003e` | Generate symmetric key |\n| `key generate --env \u003cenv\u003e` | Generate key for specific environment |\n| `key generate --name \u003cn\u003e --asymmetric` | Generate RSA/EC key pair |\n| `key list` | List all keys |\n| `key export --name \u003cn\u003e` | Export encrypted bundle |\n| `key import -f \u003cfile\u003e` | Import encrypted bundle |\n| `key backup -o \u003cfile\u003e` | Backup keys to encrypted bundle |\n| `key restore -f \u003cfile\u003e` | Restore keys from backup bundle |\n\n### Run (Execute with Env Vars)\n\n| Command | Description |\n|:--------|:------------|\n| `run -- \u003ccommand\u003e` | Execute command with auto-loaded env vars |\n| `run -e prd -- \u003ccommand\u003e` | Execute with specific environment |\n| `run -s api -- \u003ccommand\u003e` | Execute with service-specific vars (monorepo) |\n| `run --verbose -- \u003ccommand\u003e` | Show which files were loaded |\n| `run --dry-run -- \u003ccommand\u003e` | Preview without executing |\n\n**Examples:**\n\n```bash\n# Local development\nnpx vaulter run -- pnpm dev\n\n# CI/CD build with production vars\nnpx vaulter run -e prd -- pnpm build\n\n# Monorepo service\nnpx vaulter run -e dev -s api -- pnpm start\n```\n\n### Run scripts via package.json\n\nUse `vaulter run` directly in your npm scripts to keep variables centralized and explicit.\n\n```json\n{\n  \"scripts\": {\n    \"dev:web\": \"vaulter run -e dev -s web -- pnpm --dir apps/web dev\",\n    \"lint:api\": \"vaulter run -e dev -s api -- pnpm --dir apps/api lint\",\n    \"migrate:api:stg\": \"vaulter run -e stg -s api -- pnpm --dir apps/api run migrate\",\n    \"deploy:api:prd\": \"vaulter run -e prd -s api -- pnpm --dir apps/api build \u0026\u0026 vaulter export k8s-secret -e prd -s api --name api-secrets\"\n  }\n}\n```\n\n```bash\nnpm run dev:web\nnpm run lint:api\nnpm run migrate:api:stg\n```\n\nThe important part is that `vaulter run` stays as the first command so variable resolution and scope resolution\nhappen before your script command.\n\nThe `run` command auto-detects the environment (local, CI, K8s) and loads the appropriate files before executing your command.\n\n\u003e Run `vaulter --help` or `vaulter \u003ccommand\u003e --help` for all options.\n\n---\n\n## Security\n\nEvery secret is encrypted **before** leaving your machine using **AES-256-GCM**.\n\n### Symmetric (Default)\n\n```bash\nvaulter key generate --name master\n```\n\n### Asymmetric (RSA/EC)\n\nFor CI/CD separation: public key encrypts, private key decrypts.\n\n```bash\nvaulter key generate --name master --asymmetric              # RSA-4096\nvaulter key generate --name master --asym --alg ec-p256      # EC P-256\n```\n\n```yaml\n# .vaulter/config.yaml\nencryption:\n  mode: asymmetric\n  asymmetric:\n    algorithm: rsa-4096\n    key_name: master    # ~/.vaulter/projects/\u003cproject\u003e/keys/master[.pub]\n```\n\n**CI/CD**: Give CI only the public key (can write, can't read). Production gets the private key.\n\n### Per-Environment Keys\n\nUse different encryption keys for each environment (dev, stg, prd). This provides **complete isolation** - production secrets can't be decrypted with dev keys.\n\n```bash\n# Generate keys for each environment\nvaulter key generate --env dev\nvaulter key generate --env stg\nvaulter key generate --env prd\n```\n\nKeys are stored in `~/.vaulter/projects/{project}/keys/{env}`.\n\n**Key Resolution Order** (per environment):\n\n| Priority | Source | Example |\n|:---------|:-------|:--------|\n| 1 | Env var `VAULTER_KEY_{ENV}` | `VAULTER_KEY_PRD=my-secret` |\n| 2 | Config `encryption.keys.{env}` | See below |\n| 3 | File `keys/{env}` | `~/.vaulter/projects/myapp/keys/prd` |\n| 4 | Env var `VAULTER_KEY` | Global fallback |\n| 5 | Config `encryption.key_source` | Default config |\n| 6 | File `keys/master` | Default fallback |\n\n**Per-environment config:**\n\n```yaml\n# .vaulter/config.yaml\nencryption:\n  keys:\n    dev:\n      source:\n        - env: VAULTER_KEY_DEV\n        - file: ~/.vaulter/projects/myapp/keys/dev\n    prd:\n      source:\n        - env: VAULTER_KEY_PRD\n      mode: asymmetric  # Optional: different mode per env\n```\n\n**Multi-app isolation:**\n\n```\n~/.vaulter/projects/\n├── app-landing/keys/\n│   ├── dev    # app-landing dev key\n│   ├── stg    # app-landing stg key\n│   └── prd    # app-landing prd key\n├── app-api/keys/\n│   ├── dev    # app-api dev key (DIFFERENT from app-landing)\n│   └── prd\n└── svc-auth/keys/\n    └── prd\n```\n\nEach app has completely isolated secrets - `app-landing/prd` keys cannot decrypt `app-api/prd` secrets.\n\n### Shared Variables Key (Monorepo)\n\nIn monorepos, shared variables need a consistent encryption key. Use `shared_key_environment` to specify which environment's key encrypts shared vars:\n\n```yaml\n# .vaulter/config.yaml\nencryption:\n  shared_key_environment: dev  # Use dev key for all shared vars\n  keys:\n    dev:\n      source:\n        - env: VAULTER_KEY_DEV\n    prd:\n      source:\n        - env: VAULTER_KEY_PRD\n```\n\n**Why this matters:**\n- Shared vars (`__shared__` service) need ONE key to encrypt/decrypt\n- Without `shared_key_environment`, vaulter uses the current environment's key\n- This can cause issues when different environments have different keys\n\n**Example flow:**\n```bash\n# Set shared var (uses dev key because shared_key_environment: dev)\nvaulter change set LOG_LEVEL=debug -e dev --scope shared\n\n# Read shared var from prd (still uses dev key for shared vars)\nvaulter list -e prd --shared  # Works! Uses dev key for shared\n```\n\n---\n\n## Configuration\n\n```yaml\n# .vaulter/config.yaml\nversion: \"1\"\nproject: my-project\n\nbackend:\n  url: s3://bucket/envs?region=us-east-1\n\nencryption:\n  key_source:\n    - env: VAULTER_KEY\n    - file: .vaulter/.key\n  rotation:\n    enabled: true\n    interval_days: 90\n    patterns: [\"*_KEY\", \"*_SECRET\", \"*_TOKEN\"]\n\nenvironments: [dev, stg, prd]\ndefault_environment: dev\n\naudit:\n  enabled: true\n  retention_days: 90\n\nscope_policy:\n  mode: warn\n  inherit_defaults: true\n  rules:\n    - name: api-keys-service\n      pattern: '^API_'\n      expected_scope: service\n      expected_service: svc-app\n      reason: 'API_* vars are service-owned'\n    - name: app-url-shared-default\n      pattern: '^APP_.*_URL$'\n      expected_scope: shared\n      reason: 'URL variables stay shared by default'\n\n# Local development files (see \"Local vs Deploy Structure\" below)\n# local: .vaulter/local/\n\n# CI/CD deploy files (see \"Local vs Deploy Structure\" below)\n# deploy: .vaulter/deploy/\n```\n\n### Backend URLs\n\n| Provider | URL |\n|:---------|:----|\n| AWS S3 | `s3://bucket/path?region=us-east-1` |\n| MinIO | `http://KEY:SECRET@localhost:9000/bucket` |\n| Cloudflare R2 | `https://KEY:SECRET@ACCOUNT.r2.cloudflarestorage.com/bucket` |\n| DigitalOcean | `https://KEY:SECRET@nyc3.digitaloceanspaces.com/bucket` |\n| FileSystem | `file:///path/to/storage` |\n\n### Local vs Deploy Structure\n\nVaulter separates **local development** from **deployment** configurations:\n\n```\n.vaulter/\n├── config.yaml\n├── local/                     # Developer machine (gitignored)\n│   ├── configs.env            # Non-sensitive (sensitive=false)\n│   ├── secrets.env            # Sensitive (sensitive=true)\n│   └── services/              # Monorepo only\n│       └── \u003cservice\u003e/\n│           ├── configs.env\n│           └── secrets.env\n└── deploy/                    # CI/CD pipelines\n    ├── configs/               # Committed to git\n    │   ├── dev.env\n    │   ├── stg.env\n    │   └── prd.env\n    └── secrets/               # Gitignored, pulled from backend\n        ├── dev.env\n        └── prd.env\n```\n\n**Why this structure:**\n\n| Location | Purpose | Git | Contains |\n|:---------|:--------|:----|:---------|\n| `local/configs.env` | Developer's machine | Ignored | Non-sensitive local vars |\n| `local/secrets.env` | Developer's machine | Ignored | Sensitive local secrets |\n| `deploy/configs/*.env` | CI/CD configs | Committed | Non-sensitive (PORT, HOST, LOG_LEVEL) |\n| `deploy/secrets/*.env` | CI/CD secrets | Ignored | Pulled via `vaulter local sync` |\n\n**Gitignore:**\n\n```gitignore\n# Local development\n.vaulter/local/configs.env\n.vaulter/local/secrets.env\n.vaulter/local/services/\n\n# Deploy secrets (pulled in CI)\n.vaulter/deploy/secrets/\n```\n\n---\n\n## CI/CD\n\n### GitHub Action (Recommended)\n\nUse the official Vaulter GitHub Action for seamless CI/CD integration:\n\n```yaml\n- uses: forattini-dev/vaulter@v1\n  id: secrets\n  with:\n    backend: s3://my-bucket/secrets\n    project: my-app\n    environment: prd\n    outputs: env,k8s-secret\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n    VAULTER_PASSPHRASE: ${{ secrets.VAULTER_PASSPHRASE }}\n```\n\n#### Output Formats\n\n| Output | File | Use Case |\n|:-------|:-----|:---------|\n| `env` | `.env` | Docker, Node.js |\n| `json` | `vaulter-vars.json` | Custom scripts |\n| `k8s-secret` | `k8s-secret.yaml` | `kubectl apply` |\n| `k8s-configmap` | `k8s-configmap.yaml` | `kubectl apply` |\n| `helm-values` | `helm-values.yaml` | `helmfile`, `helm` |\n| `tfvars` | `terraform.auto.tfvars` | `terraform`, `terragrunt` |\n| `shell` | `vaulter-env.sh` | `source` in scripts |\n\n#### Full Examples\n\n**kubectl:**\n```yaml\n- uses: forattini-dev/vaulter@v1\n  with:\n    backend: ${{ secrets.VAULTER_BACKEND }}\n    project: my-app\n    environment: prd\n    outputs: k8s-secret,k8s-configmap\n    k8s-namespace: my-namespace\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n    VAULTER_PASSPHRASE: ${{ secrets.VAULTER_PASSPHRASE }}\n\n- run: |\n    kubectl apply -f k8s-secret.yaml\n    kubectl apply -f k8s-configmap.yaml\n```\n\n**Helmfile:**\n```yaml\n- uses: forattini-dev/vaulter@v1\n  with:\n    backend: ${{ secrets.VAULTER_BACKEND }}\n    project: my-app\n    environment: prd\n    outputs: helm-values\n    helm-values-path: ./helm/secrets.yaml\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n    VAULTER_PASSPHRASE: ${{ secrets.VAULTER_PASSPHRASE }}\n\n- run: helmfile -e prd apply\n```\n\n**Terraform/Terragrunt:**\n```yaml\n- uses: forattini-dev/vaulter@v1\n  with:\n    backend: ${{ secrets.VAULTER_BACKEND }}\n    project: infra\n    environment: prd\n    outputs: tfvars\n    # .auto.tfvars is loaded automatically by Terraform!\n    tfvars-path: ./secrets.auto.tfvars\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n    VAULTER_PASSPHRASE: ${{ secrets.VAULTER_PASSPHRASE }}\n\n- run: terragrunt apply -auto-approve\n```\n\n**Docker Build:**\n```yaml\n- uses: forattini-dev/vaulter@v1\n  with:\n    backend: ${{ secrets.VAULTER_BACKEND }}\n    project: my-app\n    environment: prd\n    outputs: env\n    env-path: .env.production\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n    VAULTER_PASSPHRASE: ${{ secrets.VAULTER_PASSPHRASE }}\n\n- run: docker build --secret id=env,src=.env.production -t app .\n```\n\n**Export to GITHUB_ENV:**\n```yaml\n- uses: forattini-dev/vaulter@v1\n  with:\n    backend: ${{ secrets.VAULTER_BACKEND }}\n    project: my-app\n    environment: prd\n    export-to-env: true  # Makes vars available in subsequent steps\n  env:\n    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n    VAULTER_PASSPHRASE: ${{ secrets.VAULTER_PASSPHRASE }}\n\n- run: echo \"Database is $DATABASE_URL\"  # Available!\n```\n\n#### Action Inputs\n\n| Input | Required | Default | Description |\n|:------|:--------:|:--------|:------------|\n| `backend` | ✓ | - | S3 connection string |\n| `project` | ✓ | - | Project name |\n| `environment` | ✓ | - | Environment (dev/stg/prd) |\n| `service` | | - | Service (monorepo) |\n| `outputs` | | `env` | Comma-separated outputs |\n| `k8s-namespace` | | `default` | K8s namespace |\n| `export-to-env` | | `false` | Export to GITHUB_ENV |\n| `mask-values` | | `true` | Mask secrets in logs |\n\n#### Action Outputs\n\n| Output | Description |\n|:-------|:------------|\n| `env-file` | Path to .env file |\n| `k8s-secret-file` | Path to K8s Secret YAML |\n| `k8s-configmap-file` | Path to K8s ConfigMap YAML |\n| `helm-values-file` | Path to Helm values file |\n| `tfvars-file` | Path to .tfvars file |\n| `vars-count` | Number of variables |\n| `vars-json` | JSON array of variable names |\n\n### CLI in CI/CD\n\nYou can also use the CLI directly:\n\n```yaml\n- name: Pull and build\n  env:\n    VAULTER_PASSPHRASE: ${{ secrets.VAULTER_PASSPHRASE }}\n    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}\n    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n  run: |\n    npx vaulter local sync -e prd\n    npx vaulter local pull -e prd\n    npx vaulter run -e prd -- pnpm build\n```\n\n### Other Platforms\n\n```bash\n# GitLab CI\nnpx vaulter run -e ${CI_ENVIRONMENT_NAME} -- pnpm build\n\n# Docker (build with secrets)\nnpx vaulter run -e prd -- docker build -t myapp .\n\n# Terraform\nvaulter export terraform -e prd \u003e secrets.auto.tfvars\n\n# Helm\nvaulter export helm -e prd | helm upgrade myapp ./chart -f -\n\n# Direct export\nnpx vaulter export k8s-secret -e prd | kubectl apply -f -\n```\n\n### Kubernetes Runtime\n\nWhen running in Kubernetes, env vars are already injected via ConfigMap/Secret. Vaulter's `config()` function **automatically skips** loading when it detects K8s:\n\n```typescript\nimport { config } from 'vaulter'\n\nconfig() // Skips in K8s, loads files elsewhere\n```\n\nDetection: `KUBERNETES_SERVICE_HOST` environment variable is set by K8s automatically.\n\n---\n\n## Monorepo Support\n\nAuto-detects NX, Turborepo, Lerna, pnpm, Yarn workspaces, Rush.\n\n```bash\nvaulter service list                       # List discovered services\nvaulter plan -e dev -s api                 # Plan changes for specific service\nvaulter apply -e dev -s api               # Apply planned changes\nvaulter export shell -e dev -s api         # Export with shared inheritance\nvaulter export shell -e dev --shared       # Export only shared variables\n```\n\n### Shared Variables Inheritance\n\nWhen exporting for a specific service, **shared variables are automatically included**:\n\n```bash\n# Shared vars: NODE_ENV=development, LOG_LEVEL=debug\n# API service vars: PORT=3000, LOG_LEVEL=info\n\nvaulter export shell -e dev -s api\n# Output: NODE_ENV=development, LOG_LEVEL=info, PORT=3000\n# (service vars override shared vars with same key)\n\n# To export without inheritance:\nvaulter export shell -e dev -s api --no-shared\n```\n\n---\n\n## Output Targets (Multi-Framework)\n\n**One config → multiple `.env` files.** Works with any framework: Next.js, NestJS, Express, NX, Turborepo, etc.\n\n### The Problem\n\nDifferent apps need different variables in different places:\n\n```\napps/\n├── web/          # Next.js needs .env.local with NEXT_PUBLIC_*\n├── api/          # NestJS needs .env with DATABASE_*, JWT_*\n└── admin/        # Needs everything\n```\n\n### The Solution\n\nDefine outputs once, pull everywhere:\n\n```yaml\n# .vaulter/config.yaml\noutputs:\n  web:\n    path: apps/web\n    filename: .env.local\n    include: [NEXT_PUBLIC_*]      # Only public vars\n\n  api:\n    path: apps/api\n    include: [DATABASE_*, JWT_*]  # Only backend vars\n    exclude: [*_DEV]              # No dev-only vars\n\n  admin: apps/admin               # Shorthand: all vars\n\n# Shared across all outputs (inherited automatically)\nshared:\n  include: [NODE_ENV, LOG_LEVEL, SENTRY_*]\n```\n\n### Pull to All Outputs\n\n```bash\n# Pull to all outputs at once\nvaulter local pull --all\n\n# Result:\n# ✓ web: apps/web/.env.local (5 vars)\n# ✓ api: apps/api/.env (12 vars)\n# ✓ admin: apps/admin/.env (25 vars)\n```\n\n### Pull to Specific Output\n\n```bash\n# Pull only web\nvaulter local pull --output web\n\n# Preview without writing\nvaulter local pull --all --dry-run\n```\n\n### How It Works\n\n```\n┌─────────────────────────────────────────────────────────┐\n│                    Backend (S3)                         │\n│  DATABASE_URL, JWT_SECRET, NEXT_PUBLIC_API, LOG_LEVEL   │\n└────────────────────────┬────────────────────────────────┘\n                         │\n              vaulter local pull --all\n                         │\n         ┌───────────────┼───────────────┐\n         ▼               ▼               ▼\n   ┌──────────┐    ┌──────────┐    ┌──────────┐\n   │   web    │    │   api    │    │  admin   │\n   │ .env.local│   │  .env    │    │  .env    │\n   │          │    │          │    │          │\n   │ LOG_LEVEL│    │ LOG_LEVEL│    │ LOG_LEVEL│  ← shared (inherited)\n   │ NEXT_*   │    │ DATABASE_│    │ ALL VARS │  ← filtered by include/exclude\n   └──────────┘    │ JWT_*    │    └──────────┘\n                   └──────────┘\n```\n\n### Pattern Syntax\n\n| Pattern | Matches |\n|:--------|:--------|\n| `NEXT_PUBLIC_*` | `NEXT_PUBLIC_API_URL`, `NEXT_PUBLIC_GA_ID` |\n| `*_SECRET` | `JWT_SECRET`, `API_SECRET` |\n| `DATABASE_*` | `DATABASE_URL`, `DATABASE_HOST` |\n| `*_URL` | `API_URL`, `DATABASE_URL`, `REDIS_URL` |\n\n### Inheritance\n\nBy default, `shared.include` vars are added to ALL outputs. Override with `inherit: false`:\n\n```yaml\noutputs:\n  isolated-app:\n    path: apps/isolated\n    inherit: false           # No shared vars\n    include: [ISOLATED_*]\n```\n\n---\n\n## Local Overrides (Dev Environment) - OFFLINE FIRST\n\n**`vaulter local pull` and local `.env` generation are 100% OFFLINE** - no backend calls.\n\nWorks entirely from local files in `.vaulter/local/`. This is the primary workflow for day-to-day development: edit local overrides, run `vaulter local pull`, and only sync when needed.\n\n### Quick Reference\n\n| Command | What it does | Backend? |\n|---------|--------------|----------|\n| `vaulter local pull` | Generate .env files from local | ❌ OFFLINE |\n| `vaulter local push --all` | Send local → backend | ✅ Backend |\n| `vaulter local sync` | Download backend → local | ✅ Backend |\n| `vaulter local set` | Write local override to `.vaulter/local/` | ❌ OFFLINE |\n| `vaulter local diff` | Compare local overrides vs base env | ❌ OFFLINE |\n\n### Workflow\n\n```\n┌─────────────────────────────────────────────────────┐\n│              LOCAL DEVELOPMENT                       │\n│  1. Edit .vaulter/local/*.env                       │\n│  2. vaulter local pull       → Generate .env       │\n│  3. Develop...                                       │\n└─────────────────────────────────────────────────────┘\n                         ↓\n┌─────────────────────────────────────────────────────┐\n│              SHARE WITH TEAM                         │\n│  vaulter local push --all  → Upload to backend      │\n└─────────────────────────────────────────────────────┘\n                         ↓\n┌─────────────────────────────────────────────────────┐\n│              NEW TEAM MEMBER                         │\n│  1. git clone \u003crepo\u003e                                │\n│  2. vaulter local sync     → Download from backend  │\n│  3. vaulter local pull      → Generate .env        │\n└─────────────────────────────────────────────────────┘\n```\n\nFor monorepos, use `--service \u003cname\u003e` on `local set`, `local delete`, `local diff`, and `local push` (without `--all`), unless the CLI can infer the service from your current directory (or the monorepo has only one service).\n\n### File Structure\n\n```\n.vaulter/local/\n├── configs.env           # Shared configs (all services)\n├── secrets.env           # Shared secrets (all services)\n└── services/             # Monorepo only\n    ├── web/\n    │   ├── configs.env   # web-specific configs\n    │   └── secrets.env   # web-specific secrets\n    └── api/\n        ├── configs.env\n        └── secrets.env\n```\n\n### Merge Order (Per Output)\n\n**Priority:** `shared vars \u003c service-specific vars`\n\nFor each output target, vaulter merges:\n1. Shared vars from `.vaulter/local/{configs,secrets}.env`\n2. Service-specific vars from `.vaulter/local/services/{service}/*.env`\n\n**Example:**\n- 20 shared vars + 3 service-specific = 23 vars for that service\n- NOT all vars from all services merged together!\n\n### CLI Commands\n\n```bash\n# === EDIT LOCALLY ===\nvaulter local set --shared DEBUG::true     # shared config\nvaulter local set --shared API_KEY=xxx     # shared secret\nvaulter local set PORT::3001                # service config (inferred from cwd in monorepo)\nvaulter local set DB_URL=xxx -s api        # service secret\n# In service directories, `-s` is usually auto-inferred.\n# If the repo has only one service, `-s` is inferred automatically too.\n\n# === GENERATE .ENV FILES [OFFLINE] ===\nvaulter local pull\n# Output: \"svc-auth: 23 vars (21 shared + 2 service)\"\n\n# === SHARE WITH TEAM ===\nvaulter local push --all                   # Upload entire structure\n\n# === GET TEAM'S CHANGES ===\nvaulter local sync                         # Download from backend\nvaulter local pull                        # Generate .env files\n\n# === OTHER ===\nvaulter local diff                         # Show differences\nvaulter local status                       # Show summary\n```\n\n### Section-Aware .env Management\n\nVaulter uses **section-aware mode** by default when writing `.env` files. This preserves your custom variables while managing backend variables separately.\n\n```env\n# Your variables (NEVER touched by vaulter)\nMY_LOCAL_VAR=something\nCUSTOM_DEBUG=true\nMY_PORT_OVERRIDE=3001\n\n# --- VAULTER MANAGED (do not edit below) ---\nDATABASE_URL=postgres://...\nAPI_KEY=sk-xxx\nNODE_ENV=production\n# --- END VAULTER ---\n```\n\n**How it works:**\n\n| Location | Behavior |\n|:---------|:---------|\n| Above marker | **Preserved** - your custom vars, never modified |\n| Between markers | **Managed** - vaulter controls this section |\n| Below end marker | **Preserved** - any trailing content |\n\n**CLI options:**\n\n```bash\n# Section-aware pull (default)\nvaulter local pull\n\n# Overwrite entire file (ignores sections)\nvaulter local pull --overwrite\n```\n\n**Programmatic API:**\n\n```typescript\nimport {\n  syncVaulterSection,\n  getUserVarsFromEnvFile,\n  setInEnvFile\n} from 'vaulter'\n\n// Sync only the managed section (preserves user vars)\nsyncVaulterSection('/app/.env', {\n  DATABASE_URL: 'postgres://...',\n  API_KEY: 'sk-xxx'\n})\n\n// Read only user-defined vars (above the marker)\nconst userVars = getUserVarsFromEnvFile('/app/.env')\n// { MY_LOCAL_VAR: 'something', CUSTOM_DEBUG: 'true' }\n\n// Add var to user section (above marker)\nsetInEnvFile('/app/.env', 'MY_VAR', 'value', true)\n```\n\n**Use cases:**\n\n- **Local debugging:** Add `DEBUG=true` above the marker, it stays after `vaulter local pull`\n- **Port conflicts:** Override `PORT=3001` locally without affecting teammates\n- **Feature flags:** Test with `FEATURE_X_ENABLED=true` without touching backend\n- **Framework vars:** Keep `.env.local` compatible with Next.js/Vite expectations\n\n---\n\n## API Usage\n\n```typescript\nimport { VaulterClient, loadConfig } from 'vaulter'\n\nconst client = new VaulterClient({ config: loadConfig() })\nawait client.connect()\n\nawait client.set({ key: 'API_KEY', value: 'sk-xxx', project: 'my-project', environment: 'prd' })\nconst value = await client.get('API_KEY', 'my-project', 'prd')\nconst vars = await client.list({ project: 'my-project', environment: 'prd' })\n\nawait client.disconnect()\n```\n\n### Smart Config (Auto-Detection)\n\nThe `config()` function auto-detects your environment and loads the appropriate files:\n\n```typescript\nimport { config } from 'vaulter'\n\n// Auto-detect environment and load appropriate files\nconst result = config()\n\n// With options\nconfig({\n  mode: 'auto',        // 'auto' | 'local' | 'deploy' | 'skip'\n  environment: 'dev',  // Override environment (dev, stg, prd)\n  service: 'api',      // For monorepo service-specific vars\n  verbose: true,       // Debug output\n})\n```\n\n**Environment Detection:**\n\n| Environment | Detection | Behavior |\n|:------------|:----------|:---------|\n| **Kubernetes** | `KUBERNETES_SERVICE_HOST` set | Skip loading (vars injected via ConfigMap/Secret) |\n| **CI/CD** | `CI=true`, `GITHUB_ACTIONS`, etc. | Load from `.vaulter/deploy/` |\n| **Local** | Default | Load from `.vaulter/local/` (configs.env + secrets.env) |\n\n**Why this matters:**\n- **K8s**: Env vars are already injected, no file loading needed\n- **CI/CD**: Uses committed configs + secrets pulled from backend\n- **Local**: Developer's machine-specific `.env` file (gitignored)\n\n### Auto-load (dotenv compatible)\n\n```typescript\nimport 'vaulter/load'  // Auto-loads .env into process.env\n```\n\n---\n\n## Runtime Loader (No .env Files)\n\nLoad secrets directly from the backend at application startup - **no .env files, no Kubernetes ConfigMaps/Secrets needed**.\n\n### Quick Start\n\n```typescript\n// Option 1: Simple import (like dotenv/config)\nimport 'vaulter/load'\n\n// Option 2: Side-effect import with full path\nimport 'vaulter/runtime/load'\n\n// Option 3: With options\nimport { loadRuntime } from 'vaulter'\n\nawait loadRuntime({\n  environment: 'prd',\n  service: 'api',        // Optional: for monorepos\n  required: true         // Default: true in prd, false otherwise\n})\n\n// Option 4: Using config() with backend source\nimport { config } from 'vaulter'\n\nawait config({ source: 'backend' })\n\n// Now process.env has all your secrets!\nconsole.log(process.env.DATABASE_URL)\n```\n\n### How It Works\n\n1. Reads `.vaulter/config.yaml` to find backend URL\n2. Loads encryption key (per-environment support)\n3. Fetches secrets from S3/MinIO backend\n4. Populates `process.env`\n\n### Configuration\n\n```yaml\n# .vaulter/config.yaml\nproject: my-app\nbackend:\n  url: s3://my-bucket/secrets\n\n# Runtime detects environment from NODE_ENV or config\ndefault_environment: dev\n```\n\n### Options\n\n| Option | Type | Default | Description |\n|:-------|:-----|:--------|:------------|\n| `environment` | string | `NODE_ENV` or `dev` | Target environment |\n| `project` | string | from config | Project name |\n| `service` | string | - | Service name (monorepo) |\n| `required` | boolean | `true` in prd | Throw on failure |\n| `override` | boolean | `false` | Override existing env vars |\n| `includeShared` | boolean | `true` | Include shared vars (monorepo) |\n| `filter.include` | string[] | `[]` | Glob patterns to include |\n| `filter.exclude` | string[] | `[]` | Glob patterns to exclude |\n| `verbose` | boolean | `false` | Enable logging |\n\n### Per-Environment Keys\n\nRuntime loader automatically uses per-environment keys:\n\n```bash\n# Set env-specific keys\nexport VAULTER_KEY_DEV=\"dev-secret\"\nexport VAULTER_KEY_PRD=\"prd-secret\"\n\n# Or generate key files\nvaulter key generate --env prd\n```\n\n### Use Cases\n\n**Kubernetes without ConfigMaps/Secrets:**\n\n```yaml\n# deployment.yaml - No configMapRef/secretRef needed!\nenv:\n  - name: VAULTER_KEY_PRD\n    valueFrom:\n      secretKeyRef:\n        name: vaulter-key\n        key: prd\n  - name: VAULTER_BACKEND\n    value: \"s3://my-bucket/secrets\"\n```\n\n```typescript\n// app.ts - Secrets loaded at startup\nimport 'vaulter/runtime/load'\n// process.env.DATABASE_URL is now available\n```\n\n**Lambda/Serverless:**\n\n```typescript\nimport { loadRuntime } from 'vaulter'\n\nexport const handler = async (event) =\u003e {\n  await loadRuntime({ environment: 'prd' })\n  // Use secrets from process.env\n}\n```\n\n### Library API\n\n```typescript\nimport { loadRuntime, isRuntimeAvailable, getRuntimeInfo } from 'vaulter'\n\n// Check if runtime config exists\nif (isRuntimeAvailable()) {\n  const info = await getRuntimeInfo()\n  console.log(info.project, info.environment, info.backend)\n}\n\n// Load with callbacks\nconst result = await loadRuntime({\n  environment: 'prd',\n  onLoaded: (r) =\u003e console.log(`Loaded ${r.varsLoaded} vars in ${r.durationMs}ms`),\n  onError: (e) =\u003e console.error('Failed:', e.message)\n})\n```\n\n---\n\n## MCP Server\n\nClaude AI integration via Model Context Protocol. **17 Tools | 4 Resources | 5 Prompts.**\n\n```bash\nvaulter mcp\n```\n\n### Claude Desktop\n\n```json\n{\n  \"mcpServers\": {\n    \"vaulter\": {\n      \"command\": \"vaulter\",\n      \"args\": [\"mcp\", \"--cwd\", \"/path/to/project\"]\n    }\n  }\n}\n```\n\n### Tools (17)\n\n\u003e **Tool Architecture:** Each tool is action-based (one tool per domain with `action` parameter).\n\n| Category | Tool | Actions / Description |\n|:---------|:-----|:---------------------|\n| **Mutation Flow** | `vaulter_change` | set, delete, move, import (writes local state only) |\n| | `vaulter_plan` | Compute diff local vs backend, generate plan artifact |\n| | `vaulter_apply` | Execute plan, push changes to backend |\n| | `vaulter_run` | Execute command with loaded variables |\n| **Read** | `vaulter_get` | Get single var or multi-get via `keys[]` |\n| | `vaulter_list` | List vars with optional filter |\n| | `vaulter_search` | Search by pattern or compare environments |\n| | `vaulter_diff` | Quick diff without plan artifacts |\n| **Status** | `vaulter_status` | scorecard, vars, audit, drift, inventory |\n| **Export** | `vaulter_export` | k8s-secret, k8s-configmap, helm, terraform, env, shell, json |\n| **Keys** | `vaulter_key` | generate, list, show, export, import, rotate |\n| **Local Dev** | `vaulter_local` | pull, push, push-all, sync, set, delete, diff, status, shared-set, shared-delete, shared-list |\n| **Backup** | `vaulter_snapshot` | create, list, restore, delete |\n| | `vaulter_versions` | list, get, rollback |\n| **Setup** | `vaulter_init` | Initialize project |\n| | `vaulter_services` | Discover monorepo services |\n| **Danger** | `vaulter_nuke` | Preview backend deletion (CLI-only execution) |\n\n### Resources (4)\n\nStatic data views (no input required). For actions with parameters, use tools.\n\n| URI | Description |\n|:----|:------------|\n| `vaulter://instructions` | **Read first!** s3db.js architecture + tool overview |\n| `vaulter://tools-guide` | Which tool to use for each scenario |\n| `vaulter://config` | Project configuration (YAML) |\n| `vaulter://services` | Monorepo services list |\n\n### Prompts (5)\n\nPre-configured workflows for common tasks.\n\n| Prompt | Description |\n|:-------|:------------|\n| `setup_project` | Initialize new vaulter project |\n| `deploy_secrets` | Deploy to Kubernetes |\n| `compare_environments` | Compare dev vs prd |\n| `rotation_workflow` | Check/rotate/report on rotation |\n| `local_dev_workflow` | Manage local dev overrides (shared + service) |\n\n\u003e **Full MCP documentation:** See [docs/MCP.md](docs/MCP.md) for complete tool reference with parameters.\n\n---\n\n## Shell (Interactive Terminal)\n\n```bash\nvaulter shell              # Secrets Explorer (default)\nvaulter shell menu         # Menu\nvaulter shell audit        # Audit log viewer\nvaulter shell keys         # Key manager\n```\n\n### SYNC Column (Secrets Explorer)\n\nShows local `.env` sync status vs backend:\n\n| Icon | Status | Meaning |\n|:----:|:-------|:--------|\n| `✓` | synced | Local value = backend value |\n| `≠` | modified | Local value differs from backend |\n| `−` | missing | Exists in backend, not in local .env |\n| `+` | local-only | Exists only in local .env |\n\n### Shortcuts\n\n**Global**: `q` quit · `ESC` back · `↑↓` navigate\n\n| Screen | Shortcuts |\n|:-------|:----------|\n| Menu | `1` `2` `3` quick access to screens |\n| Explorer | `r` refresh · `v` toggle values · `Tab` cycle env · `j/k` vim nav |\n| Audit | `o` filter op · `s` filter source · `/` search · `c` clear |\n| Keys | `r` refresh · `c` toggle config |\n\n---\n\n## Pre-built Binaries\n\nDownload from [Releases](https://github.com/forattini-dev/vaulter/releases):\n\n| Platform | Binary |\n|:---------|:-------|\n| Linux x64/ARM64 | `vaulter-linux-x64`, `vaulter-linux-arm64` |\n| macOS x64/ARM64 | `vaulter-macos-x64`, `vaulter-macos-arm64` |\n| Windows x64 | `vaulter-win-x64.exe` |\n\n---\n\n## License\n\nMIT © [Forattini](https://github.com/forattini-dev)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fforattini-dev%2Fvaulter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fforattini-dev%2Fvaulter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fforattini-dev%2Fvaulter/lists"}