8.8 KiB
description
| description |
|---|
| Manage Vercel environment variables. Commands include list, pull, add, remove, and diff. Use to sync environment variables between Vercel and your local development environment. |
Vercel Environment Variables
Manage environment variables for the current Vercel project with safety rails to prevent secret leakage.
🔒 Never-Echo-Secrets Rule: Environment variable values must never appear in command output, summaries, or conversation text. Only show variable names, environments, and metadata (created date, type). This rule applies to all subcommands.
Preflight
- CLI available? — Confirm
vercelis on PATH.- If missing:
npm i -g vercel(orpnpm add -g vercel/bun add -g vercel).
- If missing:
- Project linked? — Check for
.vercel/project.jsonin the current directory or nearest parent.- If not found: run
vercel linkinteractively, then re-run/env.
- If not found: run
- Detect environment files — Check for
.env,.env.local,.env.production.local,.env.development.localin the project root. Note which exist for the diff subcommand.
Plan
Based on "$ARGUMENTS", determine the action:
| Argument | Action | Destructive? |
|---|---|---|
list / ls / (none) |
List env var names per environment | No |
pull |
Download env vars to local .env.local |
No (overwrites local file) |
add <NAME> |
Add a new env var | Yes (if production) |
rm <NAME> / remove <NAME> |
Remove an env var | Yes |
diff |
Compare local vs Vercel key names | No |
For any operation that mutates production environment variables (add or rm targeting production):
⚠️ Production environment mutation requested. This will change environment variables on your live production deployment. Ask the user for explicit confirmation before proceeding. Do not mutate production env vars without a clear "yes."
Commands
"list" or "ls" or no arguments
# List all environment variables
vercel env ls
# Filter by environment
vercel env ls production
Present results as a table of variable names only grouped by environment. Never print values.
| Name | Production | Preview | Development |
|---|---|---|---|
| DATABASE_URL | ✓ | ✓ | ✓ |
| API_KEY | ✓ | ✓ | — |
"pull"
# Pull all env vars for the current environment into .env.local
vercel env pull .env.local
# Pull for a specific environment
vercel env pull .env.local --environment=production
vercel env pull .env.local --environment=preview
vercel env pull .env.local --environment=development
# Overwrite existing file without prompting
vercel env pull .env.local --yes
# Pull to a custom file
vercel env pull .env.production.local --environment=production
After pulling, remind the user:
Ensure
.env*.localis in your.gitignoreto avoid committing secrets.
"add <NAME>"
- Ask the user which environments to target: production, preview, development (can select multiple).
- If production is selected, require explicit confirmation (see Plan section).
- Run the add command:
# Interactive — prompts for value and environments
vercel env add MY_SECRET
# Non-interactive
echo "secret-value" | vercel env add MY_SECRET production
# Add to multiple environments
echo "secret-value" | vercel env add MY_SECRET production preview development
# Add a sensitive variable (encrypted, not shown in logs)
vercel env add MY_SECRET --sensitive
The CLI will prompt for the value interactively — do not pass the value as a CLI argument or echo it.
"rm <NAME>" or "remove <NAME>"
- If the variable exists in production, require explicit confirmation.
- Run the remove command:
# Remove from specific environment
vercel env rm MY_SECRET production
# Remove from all environments
vercel env rm MY_SECRET
Confirm the target environment(s) with the user before executing.
"diff"
Compare local environment file key names against Vercel-configured key names. Only compare names — never read or display values.
- Read local env file keys (from
.env.localor.env— whichever exists):
grep -v '^#' .env.local | grep '=' | cut -d'=' -f1 | sort
- Fetch Vercel env var names:
vercel env ls
Parse the output to extract variable names for the target environment (default: development).
- Present the diff:
## Env Diff — Local vs Vercel (development)
### In local but NOT on Vercel:
- EXTRA_LOCAL_VAR
- DEBUG_MODE
### On Vercel but NOT in local:
- ANALYTICS_KEY
- SENTRY_DSN
### In both:
- DATABASE_URL
- API_KEY
- NEXT_PUBLIC_APP_URL
If all keys match, report: "Local and Vercel environment keys are in sync."
Environment-Specific Configuration Reference
Vercel Dashboard vs .env Files
| Use Case | Where to Set |
|---|---|
| Secrets (API keys, tokens) | Vercel Dashboard (https://vercel.com/{team}/{project}/settings/environment-variables) or vercel env add |
| Public config (site URL, feature flags) | .env or .env.[environment] files |
| Local-only overrides | .env.local |
| CI/CD secrets | Vercel Dashboard (https://vercel.com/{team}/{project}/settings/environment-variables) with environment scoping |
Environment Scoping on Vercel
Variables set in the Vercel Dashboard at https://vercel.com/{team}/{project}/settings/environment-variables can be scoped to:
- Production — only
vercel.appproduction deployments - Preview — branch/PR deployments
- Development —
vercel devandvercel env pull
A variable can be assigned to one, two, or all three environments.
Git Branch Overrides
Preview environment variables can be scoped to specific Git branches:
# Add a variable only for the "staging" branch
echo "staging-value" | vercel env add DATABASE_URL preview --git-branch=staging
Common Gotchas
vercel env pull Overwrites Custom Variables
vercel env pull .env.local replaces the entire file — any manually added variables (custom secrets, local overrides, debug flags) are lost. Always back up or re-add custom vars after pulling:
# Save custom vars before pulling
grep -v '^#' .env.local | grep -v '^VERCEL_\|^POSTGRES_\|^NEXT_PUBLIC_' > .env.custom.bak
vercel env pull .env.local --yes
cat .env.custom.bak >> .env.local # Re-append custom vars
Or maintain custom vars in a separate .env.development.local file (loaded after .env.local by Next.js).
Scripts Don't Auto-Load .env.local
Only Next.js auto-loads .env.local. Standalone scripts (drizzle-kit, tsx, custom Node scripts) need explicit loading:
# Use dotenv-cli
npm install -D dotenv-cli
npx dotenv -e .env.local -- npx drizzle-kit push
npx dotenv -e .env.local -- npx tsx scripts/seed.ts
# Or source manually
source <(grep -v '^#' .env.local | sed 's/^/export /') && node scripts/migrate.js
Verification
After any mutation (add or rm), verify the change took effect:
vercel env ls
Re-list environment variables and confirm:
- For
add: the new variable name appears in the expected environment(s). - For
rm: the variable name no longer appears in the target environment(s).
If verification fails (variable still present after remove, or missing after add), report the discrepancy and suggest retrying.
Summary
Present a structured result block:
## Env Result
- **Action**: list | pull | add | remove | diff
- **Status**: success | failed
- **Variable**: <NAME> (for add/remove)
- **Environments**: production, preview, development (as applicable)
- **Details**: <key outcome>
For diff, include counts:
- **Local only**: N keys
- **Vercel only**: N keys
- **Shared**: N keys
Next Steps
Based on the action performed:
- After list → "Run
/env pullto sync to local, or/env diffto compare local vs Vercel." - After pull → "Restart your dev server to pick up the new variables. Run
/env diffto verify sync." - After add → "Run
/deployto make the new variable available in your next deployment. For production, the variable is available immediately on the next request." - After remove → "The variable is removed. If your app depends on it, update your code or add a replacement. Consider redeploying with
/deploy." - After diff → "Add missing variables with
/env add <NAME>, or pull from Vercel with/env pullto sync."