CLI-firstZero-knowledge encryption

Losing your .env in a Slack threadends now

Encrypted on your machine, so we only ever store ciphertext. One envhq pull and your whole team is in sync.

Push without holding your breath

Sync is a three-way merge against the last state you and the server agreed on. It adds, it updates, and it stops to ask before it removes.

Nothing disappears quietly
A key is only dropped remotely if you deleted it locally and nobody changed it since. Even then, push stops and asks.
Prod asks twice
Any environment named prod gets its own confirmation before anything lands, because the blast radius is not the same everywhere.
Pull keeps what it replaced
Your previous file is written to .env.bak before a pull overwrites it, and local keys the server has never seen are merged forward rather than dropped.
$ envhq diff prod
prod:
  ~ DATABASE_URL
  + SENTRY_DSN
  - LEGACY_API_KEY
  2 to push, 1 to delete.

$ envhq push prod
✔ Pushed to prod (v9): 1 new, 1 updated, 1 deleted.
$ envhq push prod
✖ prod has moved to version 9 since your last read. Conflicting keys:
  DATABASE_URL: yours="…:5432/orders", server="…:5433/orders"

Both are the CLI's own output. The second wrote nothing: your file and the server stay untouched until you decide.

We cannot read your valuesNeither can anyone who takes them

A copy of the database holds ciphertext, SHA-256 token hashes, and the names of your projects and variables. Not one value anyone can open.

Read the security model

orders-api / prod

Names legible, values not. This is the whole row.

DATABASE_URL
qF8xK2mQ9vTn4pLc7W…
REDIS_URL
bW9cH3vAe8Nk2QtL6y…
SENTRY_DSN
8nR4dLp2XwYh6BsjN0…
SESSION_SECRET
mT7yUq1KeGf0VdRxP5…
SMTP_PASSWORD
zC5oJ9fBi3Hu7MwEa2…
STRIPE_SECRET_KEY
vD6sN8gYr4Ol1PjXt9…

Encryption

XChaCha20-Poly1305
Every value is sealed client-side under a key belonging to its project. The server is never handed plaintext to store.
Argon2id
Your passphrase derives the key that unwraps your X25519 keypair, and that derivation happens on your device every time.

Access

Scoped grants
Viewer, Editor or Admin on a project, capped per environment. Being authorized and being able to decrypt stay separate problems.
Not found, not forbidden
A project you cannot reach returns not found. A stranger and a Viewer probing it learn exactly the same amount about what exists.

Credentials

Hashed tokens
CLI tokens are stored as a SHA-256 hash, so a copy of the database cannot be turned back into a working one.
Recovery phrase
A printable phrase wraps your keypair a second, independent way. Lose it and your passphrase and the data is gone for everyone, us included.

Everything after the first push

A project holds environments, an environment holds versions, and nothing you did last month is unrecoverable.

Unlimited environments under every project

dev, qa, staging, uat, prod, and whatever else your team actually runs.

orders-api
3 variables
prod
DATABASE_URL••••••••••••••••
REDIS_URL••••••••••
SESSION_SECRET••••••••••••

Every push is a version

Commits are append-only. Restore an earlier one to recover a variable somebody overwrote.

  • v91 new, 1 updated, 1 deleted
  • v82 new, 1 updated
  • v7rolled back to v5
  • v64 updated
  • v51 new
  • v412 new
  • v32 updated
  • v21 new, 3 updated

Paste a whole .env

Bulk-import a file into an environment. It upserts, so an import can only ever add or update.

  • +new keys appear
  • ~existing keys update
  • -nothing is removed

Tokens made for CI

Create a token scoped to one project and read-only, drop it into your pipeline, and revoke it whenever you like.

ENVHQ_TOKEN=envhq_pat_••••••••••••read-only

Start with one project

Create a project, push your first environment, and pull it back on another machine a minute later.

EnvHQ is a free tool. Read the security model and the Terms and Conditions before you store production secrets.