Core Commands
These commands handle the basic workflow of syncing environment variables between EnvManager and your local .env files.
pull
Download variables from EnvManager to a local file.
envmanager pull [options]
Options:
| Option | Description |
|---|---|
-e, --environment <name> | Environment name (default: from config or "development") |
-p, --project <id> | Project ID (default: from config) |
-o, --output <file> | Output file path (default: .env) |
--format <type> | Export format (see Export Formats) |
--k8s-namespace <ns> | Kubernetes namespace (default: "default") |
--k8s-name <name> | Kubernetes resource name |
--no-secrets | Exclude secret values (will be empty) |
-f, --force | Overwrite existing file without prompting |
-r, --resolve-references | Resolve ${VAR} references to their values |
-F, --include-fallbacks | Include fallback values for empty variables |
-s, --show-sources | Show value source as inline comments |
Examples:
# Pull from configured project/environment
envmanager pull
# Pull specific environment
envmanager pull --environment production
# Pull to custom file
envmanager pull --output .env.local
# Pull without secret values
envmanager pull --no-secrets
# Pull as Docker Compose YAML
envmanager pull --format docker-compose -o docker-compose.env.yml
# Pull as Kubernetes Secret
envmanager pull --format k8s-secret --k8s-name my-app --k8s-namespace production -o secrets.yaml
Output:
Pulled 12 variables to .env (dotenv)
8 plain, 4 secrets
For details on all supported export formats, see Export Formats.
push
Upload a local .env file to EnvManager. Existing variables are updated in place, new ones are added; nothing is deleted. The push is all-or-nothing: if anything fails, no variable is changed.
envmanager push [options]
Options:
| Option | Description |
|---|---|
--org <name> | Organization name (only needed if you belong to several) |
-e, --environment <name> | Environment name (default: from config or "development") |
-p, --project <id> | Project ID, friendly ID or name (default: from config) |
-i, --input <file> | Input file path (default: .env) |
--secrets <keys> | Comma-separated keys or patterns to mark as secrets (see below) |
--plain <keys> | Comma-separated keys or patterns to explicitly mark as plain — turns those secrets back into plain variables; other keys keep their flag |
--all-secrets | Mark every variable in the file as a secret |
--no-secrets | Mark every variable in the file as plain |
--service <name> | Push to a specific service instead of the shared variables |
--create | Create the --service if it doesn't exist yet (owners and admins only) |
--dry-run | Show exactly what would happen without changing anything |
--no-sync | Don't trigger auto-sync to connected platforms after the push |
Examples:
# Push from .env
envmanager push
# Preview first — shows target project, environment and service
envmanager push --dry-run
# Mark specific variables as secrets
envmanager push --secrets "DATABASE_URL,API_SECRET"
# Patterns: * matches anything, ? matches one character
envmanager push --secrets "STRIPE_*,*_SECRET,*_TOKEN"
# Push a different file to production
envmanager push --input .env.production --environment production
# Push to a service, creating it on the first run
envmanager push --service worker --create
# Turn PORT and LOG_LEVEL back into plain variables, keep everything else as is
envmanager push --plain "PORT,LOG_LEVEL"
# Both at once: STRIPE_* become secrets, NEXT_PUBLIC_* become plain
envmanager push --secrets "STRIPE_*" --plain "NEXT_PUBLIC_*"
How secrets are decided:
- Keys matching
--secretsbecome secrets. Matching is case-sensitive;*and?are the only wildcards. - Keys matching
--plainbecome plain variables, even if they are secrets today. Same pattern syntax. - Keys that match neither keep whatever they already are on the server. A key that is already a secret stays a secret even when you leave it out of
--secrets. New keys are plain. --secretsand--plaincan be combined, but a key that matches both is an error.--all-secretsmakes everything a secret;--no-secretsmakes everything plain. Neither can be combined with--secretsor--plain.- If an entry in
--secretsor--plainmatches no key in your file, you get a warning (not an error) so a typo doesn't go unnoticed.
Auto-sync:
After a successful push the CLI triggers auto-sync for every integration of the environment that has Auto-sync enabled (Vercel, Render, Railway, GitHub, ...), exactly like saving in the web app does. Only sync targets whose scope includes what you pushed are triggered: a push to the shared variables reaches every target, a push with --service api reaches "whole environment" targets and the api target. The outcome is printed under the summary:
✔ Pushed 12 variables to production
3 inserted, 9 updated
Auto-sync: render ✔
Auto-sync: vercel ✖ Vercel token expired — reconnect the integration
A failed auto-sync does not fail the push (the variables are saved); open the integration page for details. Pass --no-sync to skip auto-sync, for example when you push several files in a row and want to sync once at the end. Nothing is printed when the environment has no auto-sync targets.
Changing whether a variable is secret:
Once a key is a secret it stays one until you say otherwise. To un-mark a few keys after an earlier --all-secrets push, use push --plain "KEY_A,KEY_B", or set a single key directly with envmanager set KEY=VALUE --no-secret (see set). The other direction works the same way: push --secrets or set KEY=VALUE --secret.
Empty values:
A secret can't be empty. If any key that would end up as a secret has an empty value, the push stops before anything is written and lists every offending key:
✖ Push aborted: 2 secrets have an empty value
STRIPE_KEY
DB_PASSWORD
Plain variables may be empty.
Dry run output:
✔ Dry run — no changes made
Project: acme-api
Environment: production
Service: worker (will be created)
Variables: 12 (3 new, 9 updated)
Secrets: STRIPE_KEY, DB_PASSWORD
Un-marked: PORT
Variables to push:
PORT=3000
STRIPE_KEY=•••••• [secret] [new]
A dry run performs every check the real push does (authentication, project/environment/service lookup, naming conventions, empty secrets), so a successful dry run means the push will succeed. The Un-marked line only appears when --plain is given and lists the keys that are secrets today and will become plain.
set
Set one or more variables directly from the command line, without a .env file. Existing keys are updated, new ones are created; nothing else in the environment is touched. Like push, the write is all-or-nothing.
envmanager set KEY=VALUE [KEY2=VALUE2 ...] [options]
Options:
| Option | Description |
|---|---|
--org <name> | Organization name (only needed if you belong to several) |
-e, --environment <name> | Environment name (default: from config or "development") |
-p, --project <id> | Project ID, friendly ID or name (default: from config) |
--service <name> | Set the variables on a service instead of the shared variables (default: service from config, if set) |
--secret | Mark the variables as secrets |
--no-secret | Mark the variables as plain — turns a secret back into a plain variable |
--no-sync | Don't trigger auto-sync to connected platforms after saving |
Without --secret or --no-secret each key keeps the flag it already has on the server; new keys are plain. Like push, a successful set triggers auto-sync for integrations with Auto-sync enabled and prints the outcome.
Examples:
# Set a plain variable in the configured environment
envmanager set LOG_LEVEL=debug
# Set a secret in production
envmanager set STRIPE_KEY=sk_live_... --environment production --secret
# Several at once; the value may contain = and can be quoted
envmanager set API_URL="https://api.example.com" DEBUG=true
# Turn an existing secret back into a plain variable
envmanager set PORT=3000 --no-secret
# Set on a service
envmanager set WORKER_CONCURRENCY=4 --service worker
Output:
✔ Set STRIPE_KEY in production [secret]
0 inserted, 1 updated
Values are split on the first =, so DATABASE_URL=postgres://u:p@host/db?sslmode=require works as expected. Matching surrounding quotes are removed. A secret can't have an empty value; a plain variable can. Naming conventions are checked exactly as in push.
service
Manage services — named subdivisions of a project such as api or worker that keep their own set of variables per environment.
service create
envmanager service create <name> [options]
Options:
| Option | Description |
|---|---|
--org <name> | Organization name (only needed if you belong to several) |
-p, --project <id> | Project ID, friendly ID or name (default: from config) |
-d, --description <text> | Optional description |
The command is safe to run repeatedly: if the service already exists (names are matched case-insensitively) it reports that and exits successfully, so it can run unconditionally in CI. Only organization owners and admins can create services.
envmanager service create worker --description "Background jobs"
envmanager push --service worker
diff
Compare a local .env file with the variables stored in EnvManager. It only reports; it never changes anything.
envmanager diff [options]
Options:
| Option | Description |
|---|---|
--org <name> | Organization name (only needed if you belong to several) |
-e, --environment <name> | Environment name (default: from config or "development") |
-p, --project <id> | Project ID, friendly ID or name (default: from config) |
-i, --input <file> | Local file to compare (default: .env) |
--service <name> | Compare against a service: its variables plus the shared ones (default: service from config, or the whole environment) |
--keys-only | Only show key names, not values |
--tag <tags...> | Only compare variables with these tags (untagged variables are always included) |
Output:
+ 1 to add (local only):
+ NEW_VAR=value
- 2 remote only (not touched by push):
- OLD_VAR
- LEGACY_TOKEN [secret]
push never deletes: these stay on the server until you remove them in the web app.
~ 1 modified:
~ API_URL
8 unchanged
How to read it:
- to add (local only) — keys in your file that don't exist remotely.
pushwill create them. - remote only (not touched by push) — keys that exist remotely but not in your file.
pushleaves them alone; it never deletes. Remove them in the web app if they are obsolete, orpullto get them locally. - modified — the value differs.
pushwill overwrite the remote value with yours;pulldoes the opposite.
Secret values are never shown in diff output.
Services: a key can exist once as a shared variable and once per service. Without --service, diff compares every row and tags ambiguous keys with their scope, e.g. ~ DATABASE_URL (service: api), and prints a note suggesting --service. With --service api, the comparison covers exactly what pull --service api and run --service api receive: the service's own variables plus the shared ones.
list
List projects, environments, or variables.
envmanager list <type> [options]
Types:
| Type | Description |
|---|---|
projects | List all accessible projects |
environments | List environments in a project |
variables | List variables in an environment |
Options:
| Option | Description |
|---|---|
--org <name> | Organization name (only needed if you belong to several) |
-p, --project <id> | Project ID (for environments/variables) |
-e, --environment <name> | Environment name (default: "development") |
--service <name> | Only list that service's variables (default: service from config, or every scope) |
-v, --verbose | Show IDs (and creation dates for variables) |
Examples:
# List all projects
envmanager list projects
# List environments in a project
envmanager list environments --project abc123
# List variables (uses config if no project specified)
envmanager list variables
# Only the variables of one service
envmanager list variables --service api
# Verbose output with IDs
envmanager list projects --verbose
envmanager list variables --verbose
Output:
✔ Found 3 projects
#1 my-app (Acme)
#2 backend-api (Acme)
#3 marketing-site (Acme)
✔ Found 5 variables (2 secrets)
API_KEY [secret] (shared)
DATABASE_URL [secret] (service: api)
DATABASE_URL [secret] (service: worker)
DEBUG (shared)
PORT (service: api)
Values are never listed; use pull for that. Each variable shows its scope: (shared) for variables every service receives, or (service: name). A key can appear more than once when it is defined per service. With --service, only that service's own rows are shown — shared variables are visible without the flag.
config
Manage project configuration.
envmanager config <action> [options]
Actions:
| Action | Description |
|---|---|
init | Create envmanager.json interactively |
get <key> | Get a config value |
set <key> <value> | Set a config value |
Examples:
# Initialize configuration
envmanager config init
# Get current project
envmanager config get project_id
# Change environment
envmanager config set environment staging
debug
Collect diagnostic info for troubleshooting. Share the output with support when reporting issues.
envmanager debug
Output:
=== EnvManager CLI Debug Report ===
Timestamp: 2026-02-19T15:48:27.806Z
CLI Version: 0.1.5
Node: v22.14.0
Platform: darwin arm64
--- Config ---
Config file: /path/to/envmanager.json
project_id: not set
environment: not set
--- Authentication ---
Auth method: CLI session key (em_abc1234...)
API URL: default (production)
--- API Connection ---
Auth exchange: 120ms
getUser: 45ms
User ID: abc-123...
Email: user@example.com
Org query: 32ms
Organizations (1):
- My Org (owner) [abc12345...]
=== End Debug Report ===
API keys are partially redacted. No secrets are exposed.
Common Workflows
Initial Setup
# Login once
envmanager login
# Initialize project
envmanager init --project <id>
# Pull current variables
envmanager pull
Daily Development
# Check what's different
envmanager diff
# Pull latest changes
envmanager pull --force
# Or use real-time sync
envmanager dev
Updating Production
# Compare with production
envmanager diff --environment production
# Push changes (with review)
envmanager push --environment production
# Or dry-run first
envmanager push --environment production --dry-run