Documentation
Push and pull AES-256-GCM encrypted .env files using GitHub permissions as access control. Zero infrastructure. No new accounts.
Introduction
boltenv is a CLI tool for sharing encrypted .env files across your team using GitHub as the access layer. There is no new dashboard to learn, no new accounts to create, and no infrastructure to manage.
Every .env file is encrypted locally on your machine with AES-256-GCM before it leaves your computer. The server stores only ciphertext — it mathematically cannot decrypt your secrets. Access control is determined entirely by GitHub repository permissions: if a teammate has write access to the repo, they can pull secrets. Remove them from GitHub, they lose access immediately.
boltenv is designed for small-to-medium engineering teams who are already using GitHub and want encrypted secret sharing without the complexity and cost of dedicated secrets management platforms like Doppler, HashiCorp Vault, or Infisical.
Installation
boltenv requires Node.js 22 or later. Install globally using any Node.js package manager:
# npmnpm install -g @boltenv.dev/cli# pnpmpnpm add -g @boltenv.dev/cli# yarnyarn global add @boltenv.dev/cli# bunbun add -g @boltenv.dev/cliOr use the one-line install script (works on macOS and Linux, no Node.js required):
curl -fsSL https://boltenv.dev/install | shAfter installation, verify it works:
$ boltenv --versionboltenv 4.0.0Quickstart
Get your team synced in under 60 seconds. The person who owns the repository does steps 1–3. Teammates only need steps 4–5.
# Step 1 — authenticate with GitHub (one time per machine)boltenv login# Step 2 — push your .env (auto-detects repo from git remote)boltenv push# Step 3 — export the encryption key and share it securely with teammatesboltenv key exportTeammates run:
# Step 4 — import the key shared by the repo ownerboltenv key import <base64-key># Step 5 — pull and decryptboltenv pullZero-knowledge encryption
boltenv uses a zero-knowledge encryption architecture. This means the server stores your ciphertext but is cryptographically incapable of decrypting it — even if an attacker has full access to the server database.
Encryption algorithm: AES-256-GCMKey derivation: HKDF-SHA256 with domain separation — Encryption subkey: "boltenv-v1-encrypt" — HMAC subkey: "boltenv-v1-hmac"IV: 12 bytes, cryptographically random per pushAuth tag: 16 bytes (GCM authentication tag)Master key: 256 bits (32 bytes), random or PBKDF2-derivedKey stored at: ~/.boltenv/keys/{owner}/{repo}.keyServer stores: ciphertext + IV + auth tag + key fingerprintServer never: sees the master key or plaintextA fresh random IV is generated for every push. This means encrypting the same .env twice produces completely different ciphertext each time — even if only one character changed. The 16-byte GCM authentication tag ensures tamper detection: any modification to ciphertext in transit is detected and rejected on pull.
Key names are stored as HMAC-SHA256 hashes on the server, not in plaintext. The server cannot determine what keys you have stored — only that they exist.
Authentication
boltenv uses GitHub OAuth Device Flow for authentication. No username or password — you authenticate your machine against GitHub once, and boltenv uses the resulting token for all API calls.
# Authenticate this machine with GitHubboltenv login# Prints the currently authenticated userboltenv whoami# Remove stored credentials from this machineboltenv logoutThe GitHub token is stored at ~/.boltenv/auth.json with file permissions 0600 (readable only by you). boltenv requests only the repo scope — the minimum required to verify repository write access.
On every push or pull, boltenv calls the GitHub API (GET /repos/{owner}/{repo}) and reads your permissions.push field. If you don't have write access, the request is rejected before any data is transmitted. This means access control is always enforced in real time — there is no cached permission state that can become stale.
Environments
boltenv uses your current git branch to automatically determine which environment you're targeting. This means switching environments is just switching branches — no extra flags needed for daily usage.
Branch Environment───────────────────────────────main, master → productionstaging → stagingdevelop → developmentrelease/* → staging (configurable)anything else → development (default fallback)Override the auto-detected environment with the -e flag:
# Push to production explicitlyboltenv push -e production# Pull staging secrets while on a feature branchboltenv pull -e stagingCustomize the branch-to-environment mapping in .boltenv.yaml using glob patterns. Wildcard patterns (release/*, hotfix/*) are supported.
# .boltenv.yamlenvironments: production: - main - master staging: - staging - "release/*" - "hotfix/*" development: - develop - "feat/*"Version history
Every push creates a new versioned snapshot. boltenv keeps the last 10 versions on the free tier and 50 versions on the Team plan. Versions are immutable — you can always roll back to any previous state.
# List all versions for the current environmentboltenv ls# Output:# v5 2026-06-13 09:41 alice 12 vars# v4 2026-06-12 17:22 bob 11 vars# v3 2026-06-11 14:05 alice 11 vars# v2 2026-06-10 10:30 alice 10 vars# v1 2026-06-09 08:15 alice 10 vars# Pull a specific version (rollback)boltenv pull --revision 3# Pull the latest version explicitlyboltenv pull --revision latestboltenv push
Encrypts your .env file locally using AES-256-GCM and uploads only the ciphertext to boltenv cloud. The plaintext and encryption key never leave your machine.
# Push .env in current directory (auto-detects repo and environment)boltenv push# Push a different fileboltenv push .env.production# Push to a specific environmentboltenv push -e production# Skip the confirmation prompt (useful in scripts)boltenv push -y# Push to a specific repo (when no .git directory is present)boltenv push -r myorg/myapp# Push multiple filesboltenv push .env .env.localIf this is the first push for a repository, boltenv auto-generates a 256-bit encryption key and saves it to ~/.boltenv/keys/. Share this key with teammates using boltenv key export.
boltenv pull
Downloads ciphertext from boltenv cloud, fetches the encryption key (gated by GitHub permissions), and decrypts the file locally. The server never decrypts anything on your behalf.
# Pull latest .env for the current environmentboltenv pull# Pull from a specific environmentboltenv pull -e staging# Pull a specific version number (rollback)boltenv pull --revision 3# Skip overwrite confirmationboltenv pull -y# Print decrypted output to stdout (don't write file)boltenv pull --stdout# Output as JSON objectboltenv pull --format json# Output as shell export statementsboltenv pull --format shell# Pull from a specific repoboltenv pull -r myorg/myappboltenv key
Manages the local encryption key for a repository. The key is a 256-bit random value stored at ~/.boltenv/keys/{owner}/{repo}.key.
# Export the key as base64 (to share with a teammate)boltenv key export# Import a key from a teammateboltenv key import dGhpcyBpcyBhIDMyIGJ5dGUga2V5IGV4YW1wbGU=# Check key status for the current repoboltenv key status# Show key fingerprint without exporting the raw keyboltenv key fingerprint# Rotate the key (generates a new key, re-encrypts all versions)boltenv key rotateboltenv init
Initializes boltenv in a project directory. Detects your framework, package manager, and existing .env files automatically.
# Interactive setup with promptsboltenv init# Use all defaults (no prompts, safe for CI)boltenv init -yinit creates a .boltenv.yaml config file and adds all detected .env patterns to .gitignore. Commit the config file so your teammates share the same environment-to-branch mapping.
# Generated .boltenv.yamlrepo: myorg/myappfiles: - .env - .env.localenvironments: production: - main staging: - staging development: - developboltenv doctor
Runs a full diagnostic check of your boltenv setup. Each check is run in dependency order — if check 3 fails, checks 4–7 are skipped since they depend on it.
$ boltenv doctor ✓ Git remote myorg/myapp ✓ GitHub token Loaded for alice ✓ GitHub API alice — scopes: repo ✓ Token scope repo scope present ✓ Repo access write access to myorg/myapp ✓ Encryption key 32-byte key (fp: 509f94d5b2d0e38b) ✓ boltenv API https://boltenv.dev (120ms) Summary: 7/7 checks passedWhen a check fails, doctor prints the exact command or action needed to fix it — no Googling required.
GitHub Actions
Use boltenv in GitHub Actions workflows to pull encrypted secrets into your CI environment. Store BOLTENV_TOKEN and BOLTENV_KEY as repository secrets in GitHub Settings → Secrets.
# .github/workflows/deploy.ymlname: Deployon: push: branches: [main]jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install boltenv run: npm install -g @boltenv.dev/cli - name: Pull secrets env: BOLTENV_TOKEN: ${{ secrets.BOLTENV_TOKEN }} BOLTENV_KEY: ${{ secrets.BOLTENV_KEY }} BOLTENV_REPO: myorg/myapp run: boltenv pull -e production -y - name: Build & deploy run: npm run build && npm run deployGitLab CI
boltenv works in GitLab CI pipelines using environment variables. Store BOLTENV_TOKEN and BOLTENV_KEY in your project's CI/CD variables (Settings → CI/CD → Variables).
# .gitlab-ci.ymlstages: - deploydeploy: stage: deploy image: node:22 script: - npm install -g @boltenv.dev/cli - boltenv pull -e production -y - npm run build - npm run deploy only: - mainDocker
Pull secrets into a Docker build or at container startup using environment variables. Never bake secrets into Docker images — use boltenv to inject them at runtime.
# Dockerfile — pull secrets at build timeFROM node:22-alpine# Install boltenvRUN npm install -g @boltenv.dev/cliWORKDIR /appCOPY . .# Pull secrets (requires BOLTENV_TOKEN, BOLTENV_KEY, BOLTENV_REPO at build time)RUN boltenv pull -e production -yRUN npm install && npm run buildCMD ["node", "dist/index.js"]For runtime injection (recommended — keeps secrets out of image layers):
# entrypoint.sh#!/bin/shboltenv pull -e production -yexec "$@"# Run with secrets injected at container startdocker run \ -e BOLTENV_TOKEN="ghp_xxxx" \ -e BOLTENV_KEY="dGhpcyBpc..." \ -e BOLTENV_REPO="myorg/myapp" \ myapp:latestCI/CD (general)
boltenv supports any CI/CD system through three environment variables. Set these in your CI platform's secret store — never hardcode them.
# Required for non-interactive / headless usage:export BOLTENV_TOKEN="ghp_xxxxxxxxxxxx" # GitHub PAT with repo scopeexport BOLTENV_KEY="dGhpcyBpcyBhIDMy..." # From: boltenv key exportexport BOLTENV_REPO="myorg/myapp" # Override git remote detection# Pull in CI (skip all interactive prompts)boltenv pull -e production -yBOLTENV_TOKEN must be a GitHub Personal Access Token with the repo scope. For GitHub Actions, you can use the built-in secrets.GITHUB_TOKEN which is automatically scoped to the current repository.
Configuration (.boltenv.yaml)
boltenv.yaml controls per-project settings. Commit this file — it's not secret. It contains no credentials.
# .boltenv.yaml — full reference# GitHub repository (owner/repo). Auto-detected from git remote if omitted.repo: myorg/myapp# Files to push/pull. Supports glob patterns.files: - .env - .env.local - .env.*.local# Branch-to-environment mapping. Supports glob patterns.environments: production: - main - master staging: - staging - "release/*" - "hotfix/*" development: - develop - "feat/*" - "*" # fallback: any other branch# Server URL (override for self-hosted, when available)# server: https://boltenv.dev# Default push behaviorpush: confirm: true # prompt before push (default: true) merge: true # enable three-way merge (default: true)# Default pull behaviorpull: confirm: true # prompt before overwrite (default: true) format: env # output format: env | json | shellCommand reference
Complete list of all boltenv commands and their flags.
boltenv <command> [flags]COMMANDS login Authenticate with GitHub via Device Flow logout Remove stored GitHub credentials whoami Print the authenticated GitHub user push [file] Encrypt and push .env to boltenv cloud pull Pull and decrypt .env from boltenv cloud ls List available versions for an environment key export Export the repo encryption key as base64 key import <key> Import a base64 encryption key key status Check if a key exists for this repo key fingerprint Print the key fingerprint (safe to share) key rotate Generate a new key and re-encrypt all data init Initialize boltenv in a project directory doctor Run full diagnostic checks version Print version informationGLOBAL FLAGS -r, --repo <owner/repo> Override git remote detection -e, --env <environment> Override branch-based env detection -y, --yes Skip all confirmation prompts --debug Enable verbose debug output --help Show help for any commandPUSH FLAGS [file] Path to .env file (default: .env) -m, --message <msg> Version commit messagePULL FLAGS --revision <n|latest> Pull a specific version number --stdout Print to stdout instead of writing --format <env|json|shell> Output format (default: env)Security model
boltenv's security model is designed around one principle: the server should never be able to read your secrets, even if it is fully compromised.
YOUR MACHINE BOLTENV CLOUD┌───────────────────────────┐ ┌───────────────────────────┐│ plaintext .env │ │ ciphertext (AES-256-GCM) ││ master key (256-bit) │──────▶│ IV (12 bytes, random) ││ HKDF-SHA256 key derivation │ │ auth tag (16 bytes) ││ AES-256-GCM encryption │ │ key fingerprint (HMAC) ││ fresh IV per push │ │ ││ GCM auth tag │ │ cannot decrypt ││ │ │ validates GitHub auth ││ key never transmitted │ │ no master key stored │└───────────────────────────┘ └───────────────────────────┘What boltenv defends against: secrets leaked via a compromised server database, insider threats at the hosting provider, man-in-the-middle attacks (TLS + GCM auth tag), .env files accidentally committed to git, secrets shared via insecure channels (Slack, email), stale access after a teammate is removed from GitHub.
What boltenv does NOT defend against: an attacker who has both the server database AND the BOLTENV_KEY_WRAPPER environment variable (full server compromise). Supply-chain attacks against the boltenv npm package itself. Authorized-but-malicious teammates (someone who already has the key). Secrets already stored in plaintext elsewhere.
Onboarding a teammate
Adding a new teammate to boltenv takes about 2 minutes. The repo owner exports the key; the teammate imports it.
# Repo owner: export the key and share it securelyboltenv key export# → prints: dGhpcyBpcyBhIDMyIGJ5dGUga2V5...# Teammate: install boltenv, login, and import the keynpm install -g @boltenv.dev/cliboltenv loginboltenv key import dGhpcyBpcyBhIDMyIGJ5dGUga2V5...boltenv pullTo revoke access: remove the teammate from the GitHub repository. From that moment, any push or pull attempt with their token will be rejected by the server (GitHub permissions are checked on every request, not cached).
Troubleshooting
Run boltenv doctor first — it diagnoses the most common issues automatically.
PROBLEM SOLUTION──────────────────────────────────────────────────────────────Not authenticated boltenv loginNo key for this repo boltenv key import <base64-key>Wrong repo detected boltenv push -r owner/repoDecryption failed Key mismatch — re-import keyPermission denied Ask repo owner to add you to GitHub repoNo .git directory in CI Set BOLTENV_REPO env varNetwork timeout Check https://status.boltenv.devConflict markers in .env Resolve manually then boltenv push -yToken expired boltenv logout && boltenv loginFor unexpected errors, enable debug output:
BOLTENV_DEBUG=1 boltenv pullMigrating from Doppler
Migrating from Doppler to boltenv takes about 10 minutes. Export your secrets from Doppler, push them to boltenv, update your CI pipelines.
# Step 1: export secrets from Dopplerdoppler secrets download --no-file --format env > .env# Step 2: install boltenv and pushnpm install -g @boltenv.dev/cliboltenv loginboltenv push# Step 3: share the key with your teamboltenv key export# Step 4: update CI — replace Doppler env vars with:# BOLTENV_TOKEN, BOLTENV_KEY, BOLTENV_REPOKey differences: boltenv is client-side encrypted (Doppler is server-side). boltenv uses GitHub for access control (Doppler has its own IAM). boltenv has no web dashboard — it's CLI-only. boltenv free tier supports up to 3 users vs Doppler's 1 user on free.
Migrating from dotenv-vault
If you're using dotenv-vault or a shared .env file in a private git repo, migrating to boltenv gives you proper encryption and access control.
# If you have a .env already, just push it:boltenv loginboltenv push# Remove .env from git history if it was committed:git rm --cached .envecho ".env" >> .gitignoregit commit -m "chore: move secrets to boltenv"