Envless variables are encrypted end-to-end with a key derived from your workspace passphrase. The dashboard caches that derived key in your browser's IndexedDB; the CLI caches it in ~/.envless/config.json. These commands manage that cache.
The envless command ships in @goenvless/cli. Install it with npm i -g @goenvless/cli@latest.
Choosing a passphrase
The workspace passphrase is the single key to every secret in the workspace. It is never sent to Envless, so there is no reset link, no recovery flow, and no support ticket that can bring it back. Lose it and the ciphertext stays unreadable. Let it leak and the holder can decrypt every variable in every environment, including any environment served as a virtual env feed.
Because the key is stretched from that one string with PBKDF2 rather than generated at random, its length and unpredictability are the whole of your protection. Envless enforces a floor when a workspace passphrase is first set:
| Rule | Value |
|---|---|
| Minimum length | 16 characters |
| Character variety | At least three of lower case, upper case, digits, symbols. From 24 characters up, two is enough, because length is doing the work. Symbols means anything that is not a letter or a digit, spaces included |
| Repeated runs | Three of the same character in a row is allowed, four is not, so Passsssword-2026 is refused |
| Sequential runs | No run of four or more characters that steps up or down one code point at a time, so both Mine12345!Secure and Mine54321!Secure are refused |
| Well known fragments | Case, symbols and spacing are stripped first, then the passphrase is refused when one known fragment covers half of what is left or more: password, passphrase, qwerty, asdfgh, zxcvbn, letmein, changeme, iloveyou, trustno1, abc123, envless, secret123, admin123, correcthorse. MyPassword-2026!! is refused; Password-Kelp-Trawler-Mist-92! passes, because the fragment is a small part of a long passphrase |
Do not invent this one yourself. The free passphrase generator draws several words uniformly at random in your browser and shows the entropy maths, which is the fastest way to clear the floor with something you can still remember and type. If you already have a passphrase and want to know where it stands before rotating, the strength checker measures it in bits locally. Neither tool sends anything anywhere.
The floor is a floor, not a target. Aim well past it:
- Generate the passphrase with a password manager and store it there. It is the one credential you cannot recover, so it belongs in a vault with a recovery path of its own, never in a note, a chat message, or a repo.
- Four or more unrelated random words, or 20 or more random characters, is the practical target. A single dictionary word with digits on the end meets the length rule and is still weak against an offline guessing attack, because the attacker holds the ciphertext and can try candidates as fast as their hardware allows.
- Never reuse a passphrase that also unlocks anything else, and never reuse one across workspaces.
- Rotate it from the dashboard if it was ever typed on a shared machine, pasted into a chat, or held by someone who has since left the team. Rotation re-encrypts the workspace under the new key, so everyone runs
envless passphrase setagain afterwards.
A passphrase set before this floor existed is not upgraded on its own. The CLI verifies against your existing ciphertext, accepts the passphrase so you are never locked out, and then warns that it is below the strength floor. Treat that warning as a rotation task, not a cosmetic notice.
On a machine, prefer not to manage a passphrase at all: export the raw key from the dashboard and pass it as ENVLESS_KEY, covered under Non-interactive below.
Set the passphrase
envless passphrase setPrompts for your workspace passphrase and saves the derived key under workspaceKeys[<workspaceId>] in ~/.envless/config.json (mode 0600). You run this once per workspace, per machine. Every subsequent envless sync reuses the cached key silently.
How it works
Resolve the workspace
Reads the workspace slug from .envless and resolves it against the API. Errors if the directory hasn't been linked yet. Run envless link first.
Derive the key
The salt is deterministic: SHA-256("envless:workspace:" + workspaceId).slice(0, 16). The passphrase is stretched with PBKDF2 (200,000 iterations, SHA-256) into an AES-GCM-256 key. The CLI derives the same key the dashboard does, so any passphrase set in the browser also works here.
Verify
The CLI tries to decrypt one existing variable in the workspace. If decrypt fails the passphrase is wrong and nothing is cached. If the workspace has no variables yet, the key is cached unverified.
Cache
The derived key is exported to JWK and stored under workspaceKeys[<workspaceId>].
Changing the passphrase
If you rotate your workspace passphrase from the dashboard, just run envless passphrase set again. The CLI derives the new key and overwrites the cached entry.
Values sealed at another cost
A stored value is either v1:base64(iv ‖ ciphertext), which is read with the key derived at the current default, or v2:<iterations>:base64(iv ‖ ciphertext), which pins the iteration count it was sealed at. When that count is not the current default, the CLI derives a second key at the recorded cost and uses it for that value alone. Keys are derived once per cost and reused, so a mixed set does not pay for the same stretch twice.
Re-deriving needs the passphrase, so it only works when one is available: from the prompt, or from ENVLESS_PASSPHRASE. With ENVLESS_KEY there is no passphrase behind the key, and with a cached key on disk there is only the derived material, so a value sealed at a non-default cost cannot be opened either way. It is reported as a variable that failed to decrypt rather than opened with the wrong key. envless passphrase set clears that up for the local case, and CI should use ENVLESS_PASSPHRASE if the workspace holds any such values.
An iteration count outside 100,000 to 1,000,000, or one that is not a whole number, is refused as Unsupported variable format rather than retried at the default.
Non-interactive (CI, containers, production)
Machines can't be prompted, so they skip envless passphrase set entirely and provide the decryption credential through the environment instead:
| Env var | What it is | When to use |
|---|---|---|
ENVLESS_KEY | The base64url-encoded raw AES-256 workspace key, exported from the dashboard's CI / Machine Access page (Settings → /settings/ci-access). | Preferred for CI: no passphrase to reuse or leak; skips the PBKDF2 step. |
ENVLESS_PASSPHRASE | The workspace passphrase in plaintext. The loader derives the key locally with the exact same PBKDF2 (200,000 / SHA-256) recipe. | When you'd rather ship the passphrase than the raw key. |
With either one set alongside ENVLESS_TOKEN (an ev_sk_ key), envless sync, envless run, and the runtime import all decrypt headlessly, with no cached key on disk. See Keys and Production & CI.
ENVLESS_KEY and ENVLESS_PASSPHRASE decrypt every variable in the workspace. Store them in your platform's secret manager, never in the repo or build logs.
Clear the cached key
envless passphrase clearRemoves the cached key for the workspace in the current directory. The next envless sync will refuse with "workspace is locked" until you run envless passphrase set again.
Use this on a shared machine before stepping away, or after rotating the passphrase to force everyone else on this machine to enter the new one.
Clear every workspace
envless passphrase clear --allWipes every cached workspace key on this machine. Useful when you're handing off a laptop or rotating credentials across the board.
What passphrase clear does not do
| Behavior | passphrase clear |
|---|---|
| Removes the cached encryption key | ✅ |
| Logs you out of the CLI | ❌ (use envless logout) |
| Revokes the key server-side | ❌ (encryption is e2e; the server never had the key) |
Deletes .envless | ❌ (the binding stays, only the key is wiped) |
Flags
| Flag | Used with | Description |
|---|---|---|
--all | passphrase clear | Wipe the cached key for every workspace, not just this directory's. |