envmap
envmap is a local env manager that helps you:
- Keep local environment variables in sync with the remote secret stores, per project.
- Makes the
.envfile an ephemeral artifact, to keep secrets providers the source of truth. i.e. "envmap --sync" to produce a newly updated.envfile. - Comes with metadata on each key stored to inform when those keys were last changed/created for sake of doing routine rotations.
- Potentially better security since you're not locked to storing secrets in a plaintext
.envfile. - Runs completely local + opensource for audits.
Who is this for?
- Engineers working with multiple
.envvariants like.env.prod, .env.dev, .env.staging. This will help you consolidate and switch environments with a single command. Here's an example of that workflow:
(base) binsquare@mac.lan:~/Documents/envMap (main*) $ ./envmap sync --env prod
Wrote .env (1 secrets)
(base) binsquare@mac.lan:~/Documents/envMap (main*) $ cat .env
# generated by envmap sync 2025-12-01T07:49:20Z
testkey=apishofih123
(base) binsquare@mac.lan:~/Documents/envMap (main*) $ ./envmap sync --env dev
Wrote .env (1 secrets)
(base) binsquare@mac.lan:~/Documents/envMap (main*) $ cat .env
# generated by envmap sync 2025-12-01T07:50:07Z
testkey=test123
- Engineers working a long list of env variables just wants a thin that helps you manage that increases dev velocity by making sure you have metadata
- Engineers working across multiple projects and wants to consolidate and track ENV variables globally.
Installation
Option 1: Go toolchain
go install github.com/binsquare/envmap@latest
Option 2: Prebuilt binary (bash)
# install into /usr/local/bin (requires sudo) curl -sSfL "https://github.com/binsquare/envmap/releases/latest/download/envmap_$(uname -s)_$(uname -m).tar.gz" \ | sudo tar -xz -C /usr/local/bin envmap # or install into ~/.local/bin (no sudo; ensure it's on PATH) mkdir -p ~/.local/bin curl -sSfL "https://github.com/binsquare/envmap/releases/latest/download/envmap_$(uname -s)_$(uname -m).tar.gz" \ | tar -xz -C ~/.local/bin envmap # (optional) verify checksum (adjust path if using ~/.local/bin) curl -sSfL "https://github.com/binsquare/envmap/releases/latest/download/envmap_$(uname -s)_$(uname -m).tar.gz.sha256" \ | sha256sum --check -
If you use the ~/.local/bin option, make sure your shell loads it (most modern shells already do; otherwise append export PATH="$HOME/.local/bin:$PATH" to your profile).
Restart the shell (or reload the profile) and run envmap --help to verify.
Quick start (local provider)
# 1. Generate encryption key (writes to ~/.envmap/key) envmap keygen # 2. Configure global provider (wizard; runs keygen if needed) envmap init --global # 3. Create project config (wizard) envmap init # 4. Add secrets envmap set --env dev DATABASE_URL --prompt envmap set --env dev STRIPE_KEY --prompt # 5. Inspect/export/run envmap get --env dev --all eval $(envmap export --env dev) envmap run --env dev -- npm start
Prefer the wizards, but manual config is supported. Use absolute paths (Go does not expand ~ or ${HOME}).
Manual configuration reference
Global config (~/.envmap/config.yaml)
providers: local-dev: type: local-file path: /Users/<you>/.envmap/secrets.db encryption: key_file: /Users/<you>/.envmap/key
Project config (.envmap.yaml)
project: demo default_env: dev envs: dev: provider: local-dev prefix: demo/dev/
Usage
envmap run [--env <name>] -- <command>– fetch secrets and run the command with them injected as env vars (disk never sees them).envmap export [--env <name>] [--format plain|json]– output suitable foreval, direnv, or tooling.envmap get --env <name> KEY [--raw]– read individual secrets.envmap get --env <name> --all [--raw] [--global]– list all secrets (masked by default);--globaliterates all envs.envmap set --env <name> KEY (--prompt | --file PATH)– write/update secrets without shell history.envmap import PATH --env <name> [--delete]– ingest existing.envfiles.envmap sync --env <name> [--out .env] [--merge] [--keep-local] [--force] [--backup=false]– write a .env file from provider secrets. Provider wins by default; merge keeps extra local-only keys; keep-local preserves local values on conflict; backup writes .bak first.envmap sync --env <name> --check– report drift between provider and .env without writing.envmap keygen [-o PATH]– create a 256-bit key for the local provider.envmap validate– confirm.envmap.yamland global config reference defined providers.envmap init/envmap init --global– interactive project/global configuration.
Use with direnv
# .envrc eval "$(envmap export --env dev)"
Then run direnv allow. Every time you enter the directory, direnv will re-run envmap export and populate the shell with fresh secrets without touching disk.
Configuration
Global config (~/.envmap/config.yaml)
providers: aws-dev: type: aws-ssm region: us-west-2 profile: dev # optional, uses default credential chain vault-prod: type: vault address: https://vault.internal:8200 mount: secret # default: secret local: type: local-file path: ~/.envmap/secrets.db encryption: key_file: ~/.envmap/key # must be chmod 600 # or: key_env: ENVMAP_KEY
Project config (.envmap.yaml)
project: myapp default_env: dev envs: dev: provider: aws-dev path_prefix: /myapp/dev/ staging: provider: aws-dev path_prefix: /myapp/staging/ local: provider: local prefix: myapp/
Built-in providers (WIP)
| Type | Auth | Notes |
|---|---|---|
aws-ssm |
IAM (profile/env/instance) | Requires path_prefix. Uses SecureString. |
aws-secretsmanager |
IAM | Full secret names. JSON secrets expanded to name/key. |
gcp-secretmanager |
ADC or service account | Reads latest version. Adds version on write. |
vault |
Token (env/config) | KV v2. Configurable mount path and namespace. |
onepassword |
Connect server | Requires connect_host. Items matched by title. |
doppler |
Service token | Read-only; writes require Doppler CLI. |
local-file |
AES-256-GCM | Key from file (0600) or env var. For local dev. |
Security Model
- Secrets never touch disk during normal operation. (unless you choose to use localstore to store all your env variables)
- We only have
set --promptandset --fileavoid saving secrets to shell history. - Values are masked by default in
envandgetoutput
Contributions
Contributions and bug reports are welcome—open an issue or submit a PR if you find a bug.
License
Licensed under the Apache License, Version 2.0. See LICENSE for details.