Vercel CLI with Tokens
Deploy and manage projects on Vercel using the CLI with token-based authentication, without relying on vercel login. The CLI reads VERCEL_TOKEN from the environment natively — never pass it as a --token flag.
When to Use
- Deploying or managing a Vercel project via CLI when an access token is available (not interactive login).
- Setting up a new Vercel project link from a local repository.
- Adding, listing, pulling, or removing environment variables on Vercel.
- Inspecting deployments, viewing build/runtime logs, or listing recent deployments.
- Managing domains attached to a Vercel project.
- Trigger phrases: "deploy to vercel", "set up vercel", "add environment variables to vercel", "vercel preview deploy", "vercel production deploy", "link vercel project".
Prerequisites
- Node.js installed (for
npm install -g vercel). - Vercel CLI installed and up to date:
npm install -g vercel vercel --version - A Vercel access token — obtainable at
vercel.com/account/tokens. Tokens typically start withvca_. - Windows host (PowerShell) is primary. Adapt bash-style commands below for PowerShell where needed (e.g.
$env:VERCEL_TOKENinstead ofexport VERCEL_TOKEN). On Windows PowerShell:$env:VERCEL_TOKEN = "YOUR_TOKEN" $env:VERCEL_ORG_ID = "YOUR_ORG_ID" $env:VERCEL_PROJECT_ID = "YOUR_PROJECT_ID" - On bash/zsh (WSL, CI, or Linux):
export VERCEL_TOKEN="YOUR_TOKEN" export VERCEL_ORG_ID="YOUR_ORG_ID" export VERCEL_PROJECT_ID="YOUR_PROJECT_ID"
Procedure
Step 1: Locate the Vercel Token
Work through these scenarios in order before running any Vercel CLI command.
A) VERCEL_TOKEN already set in the environment
[ -n "${VERCEL_TOKEN:-}" ] && printf 'VERCEL_TOKEN is set\n'
If this reports a configured token, skip to Step 2.
B) Token is in a .env file under VERCEL_TOKEN
grep -q '^VERCEL_TOKEN=' .env 2>/dev/null && printf 'VERCEL_TOKEN is present in .env\n'
If found, export it:
VERCEL_TOKEN="$(sed -n 's/^VERCEL_TOKEN=//p' .env | tail -n 1)"
export VERCEL_TOKEN
C) Token is in a .env file under a different name
Vercel tokens typically start with vca_. Search for any variable that looks like a Vercel token:
grep -Eio '^[A-Z0-9_]*VERCEL[A-Z0-9_]*(?==)' .env 2>/dev/null
Inspect the output, identify which variable holds the token, then export it as VERCEL_TOKEN:
vercel_var="<VARIABLE_NAME>"
VERCEL_TOKEN="$(sed -n "s/^${vercel_var}=//p" .env | tail -n 1)"
export VERCEL_TOKEN
D) No token found — ask the user
If none of the above yield a token, ask the user to provide one. They can create a Vercel access token at vercel.com/account/tokens.
HARD RULE: Once
VERCEL_TOKENis exported as an environment variable, the Vercel CLI reads it natively — do not pass it as a--tokenflag. Putting secrets in command-line arguments exposes them in shell history and process listings.
# BAD — token visible in shell history and process listings
vercel deploy --token "vca_abc123"
# GOOD — CLI reads VERCEL_TOKEN from the environment
[ -n "${VERCEL_TOKEN:-}" ] || { echo "Set VERCEL_TOKEN first" >&2; exit 1; }
vercel deploy
Step 2: Locate the Project and Team
Check for the project ID and team scope. These let the CLI target the right project without needing vercel link.
# Check environment
[ -n "${VERCEL_PROJECT_ID:-}" ] && printf 'VERCEL_PROJECT_ID is set\n'
[ -n "${VERCEL_ORG_ID:-}" ] && printf 'VERCEL_ORG_ID is set\n'
# Or check .env
grep -Eio '^[A-Z0-9_]*VERCEL[A-Z0-9_]*(?==)' .env 2>/dev/null
If you have a project URL (e.g. https://vercel.com/my-team/my-project), extract the team slug:
# e.g. "my-team" from "https://vercel.com/my-team/my-project"
echo "$PROJECT_URL" | sed 's|https://vercel.com/||' | cut -d/ -f1
If you have both VERCEL_ORG_ID and VERCEL_PROJECT_ID, export them — the CLI will use these automatically and skip any .vercel/ directory:
export VERCEL_ORG_ID="<org-id>"
export VERCEL_PROJECT_ID="<project-id>"
HARD RULE:
VERCEL_ORG_IDandVERCEL_PROJECT_IDmust be set together — setting only one causes an error.
Step 3: Deploy a Project
Always deploy as preview unless the user explicitly requests production.
Quick Deploy (have project ID — no linking needed)
When VERCEL_TOKEN and VERCEL_PROJECT_ID are set in the environment, deploy directly:
vercel deploy -y --no-wait
With a team scope (either via VERCEL_ORG_ID or --scope):
vercel deploy --scope <team-slug> -y --no-wait
Production (only when explicitly requested):
vercel deploy --prod --scope <team-slug> -y --no-wait
Check status:
vercel inspect <deployment-url>
Full Deploy Flow (no project ID — need to link)
Use this when you have a token and team but no pre-existing project ID.
Check project state first:
# Does the project have a git remote?
git remote get-url origin 2>/dev/null
# Is it already linked to a Vercel project?
cat .vercel/project.json 2>/dev/null || cat .vercel/repo.json 2>/dev/null
Link the project:
With git remote (preferred):
vercel link --repo --scope <team-slug> -y
Reads the git remote and connects to the matching Vercel project. Creates .vercel/repo.json. More reliable than plain vercel link, which matches by directory name.
Without git remote:
vercel link --scope <team-slug> -y
Creates .vercel/project.json.
Link to a specific project by name:
vercel link --project <project-name> --scope <team-slug> -y
If the project is already linked, check orgId in .vercel/project.json or .vercel/repo.json to verify it matches the intended team.
Deploy after linking:
A) Git Push Deploy — has git remote (preferred)
Git pushes trigger automatic Vercel deployments.
- Ask the user before pushing. Never push without explicit approval.
- Commit and push:
git add . git commit -m "deploy: <description of changes>" git push - Vercel builds automatically. Non-production branches get preview deployments.
- Retrieve the deployment URL:
Find the latest entry in thesleep 5 vercel ls --format json --scope <team-slug>deploymentsarray.
B) CLI Deploy — no git remote
vercel deploy --scope <team-slug> -y --no-wait
Check status:
vercel inspect <deployment-url>
Deploying from a Remote Repository (code not cloned locally)
- Clone the repository:
git clone <repo-url> cd <repo-name> - Link to Vercel:
vercel link --repo --scope <team-slug> -y - Deploy via git push (if you have push access) or CLI deploy.
About the .vercel/ Directory
A linked project has either:
.vercel/project.json— fromvercel link. ContainsprojectIdandorgId..vercel/repo.json— fromvercel link --repo. ContainsorgId,remoteName, and aprojectsmap.
Not needed when VERCEL_ORG_ID + VERCEL_PROJECT_ID are both set in the environment.
HARD RULE: Do NOT run
vercel project inspectorvercel linkin an unlinked directory to detect state — they will interactively prompt or silently link as a side-effect.vercel lsis safe (in an unlinked directory it defaults to showing all deployments for the scope).vercel whoamiis safe anywhere.
Step 4: Manage Environment Variables
# Set for all environments
echo "value" | vercel env add VAR_NAME --scope <team-slug>
# Set for a specific environment (production, preview, development)
echo "value" | vercel env add VAR_NAME production --scope <team-slug>
# List environment variables
vercel env ls --scope <team-slug>
# Pull env vars to local .env.local file
vercel env pull --scope <team-slug>
# Remove a variable
vercel env rm VAR_NAME --scope <team-slug> -y
Step 5: Inspect Deployments and Logs
# List recent deployments
vercel ls --format json --scope <team-slug>
# Inspect a specific deployment
vercel inspect <deployment-url>
# View build logs (requires Vercel CLI v35+)
vercel inspect <deployment-url> --logs
# View runtime request logs (follows live by default; add --no-follow for a one-shot snapshot)
vercel logs <deployment-url>
Step 6: Manage Domains
# List domains
vercel domains ls --scope <team-slug>
# Add a domain to the project — linked or env-linked directory (1 arg)
vercel domains add <domain> --scope <team-slug>
# Add a domain — unlinked directory (requires <project> positional)
vercel domains add <domain> <project> --scope <team-slug>
Step 7: Stripe Projects Plan Changes (if applicable)
If this project is managed by Stripe Projects, ask the user before running any paid or destructive plan change — upgrades bill a real card, downgrades remove seats.
First run stripe projects status --json to confirm the Vercel resource's local name. The examples below assume the default (vercel-plan); substitute the actual name if it was renamed at stripe projects add time.
- Upgrade to Pro:
stripe projects add vercel/pro(orstripe projects upgrade vercel-plan pro) - Downgrade to Hobby:
stripe projects downgrade vercel-plan hobby
What Pro gives you:
- $20/month platform fee, includes $20/month of usage credit.
- Turbo build machines (30 vCPUs, 60 GB memory) by default for new projects — significantly faster builds than Hobby.
- 1 deploying seat + unlimited free Viewer seats (read-only collaborators, preview comments).
- Higher included allocations (1 TB Fast Data Transfer, 10M Edge Requests per month).
- Paid add-ons available: SAML SSO, HIPAA BAA, Flags Explorer, Observability Plus, Speed Insights, Web Analytics Plus.
Full details: https://vercel.com/docs/plans/pro-plan
Pitfalls
- Never pass
VERCEL_TOKENas a--tokenflag. It exposes the secret in shell history and process listings. Always export it as an environment variable. VERCEL_ORG_IDandVERCEL_PROJECT_IDmust be set together. Setting only one causes an error.- Do not run
vercel project inspectorvercel linkin an unlinked directory to "detect" state — they interactively prompt or silently link as a side-effect. Usevercel lsorvercel whoamiinstead, which are safe in unlinked directories. - Do not modify
.vercel/files directly. The CLI manages this directory. Reading them (e.g. to verifyorgId) is fine. - Do not curl/fetch deployed URLs to verify. Just return the link to the user.
- Default to preview deployments. Only deploy to production (
--prod) when the user explicitly asks. - Ask before pushing to git. Never push commits without the user's explicit approval.
- Token may be expired or invalid. If you see
Authentication required, verify withvercel whoamiand ask the user for a fresh token. - Wrong team scope. Verify with
vercel whoami --scope <team-slug>before deploying. - Build failures — common causes: missing dependencies (ensure
package.jsonis complete and committed), missing environment variables (add withvercel env add), framework misconfiguration (checkvercel.json; Vercel auto-detects frameworks like Next.js, Remix, Vite frompackage.json— override withvercel.jsonif detection is wrong). vercel linkmatches by directory name — usevercel link --repofor more reliable matching via git remote.- Interactive prompts block automation — always use
-yon commands that prompt for confirmation.
Verification
Token is valid:
vercel whoamiExpected: prints the authenticated username/team. If it prints
Authentication required, the token is missing, expired, or invalid.CLI is installed and version is current:
vercel --versionExpected: prints a version number (e.g.
35.0.0or higher for--logssupport).Project is linked correctly:
cat .vercel/project.json 2>/dev/null || cat .vercel/repo.json 2>/dev/nullExpected: JSON containing
orgIdandprojectId(orremoteNameandprojectsmap for repo linking). VerifyorgIdmatches the intended team.Deployment succeeded:
vercel inspect <deployment-url>Expected: deployment metadata showing
READYstate. For build logs:vercel inspect <deployment-url> --logsEnvironment variables are set:
vercel env ls --scope <team-slug>Expected: lists all env vars with their target environments.
Team scope is correct:
vercel whoami --scope <team-slug>Expected: confirms the authenticated identity under the specified scope.
Working Agreement
- Never pass
VERCEL_TOKENas a--tokenflag. Export it as an environment variable and let the CLI read it natively. - Check the environment for tokens before asking the user. Look in the current env and
.envfiles first. - Default to preview deployments. Only deploy to production when explicitly asked.
- Ask before pushing to git. Never push commits without the user's approval.
- Do not modify
.vercel/files directly. The CLI manages this directory. Reading them is fine. - Do not curl/fetch deployed URLs to verify. Just return the link to the user.
- Use
--format jsonwhen structured output will help with follow-up steps. - Use
-yon commands that prompt for confirmation to avoid interactive blocking.
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.