.vercel/project.jsonbash
vercel whoami 2>&1
Authorized → proceed.
Not authorized → one-time setup:
→ In Claude Code (has a browser):
bash
vercel login
→ In OpenClaw or any headless agent:
Tell the user:
"Open vercel.com/account/tokens → Create Token → copy it and send it here. You only need to do this once."
Once received, verify:
bash
export VERCEL_TOKEN=<token>
vercel whoami
~/.zshrc or any file. Keep it in env for this session only, or ask the user to add it to their secrets manager.CRITICAL: Never output HTML in the response text.
Always write directly to a file using the Write/Edit tool:
index.html → deployReason: large HTML files exceed the 32k output token limit and Claude hangs mid-generation. Writing to a file has no such limit.
If the file is very large (>300 lines), build it in logical sections using Edit tool rather than rewriting from scratch.
❌ ANTI-PATTERN: deploy after each individual edit ✅ Rule: all edits in file first → one deploy
.vercel/project.json#bash
ls .vercel/project.json
File exists → proceed to deploy.
File does not exist → first deploy, Vercel will create the project automatically:
bash
vercel deploy --yes --prod
# Vercel creates the project and .vercel/project.json on first run
bash
grep -c "expected string" index.html
bash
# Deploy (run from project folder)
vercel deploy --yes --prod 2>&1 | grep -E "https://|Error"
# If custom alias was not assigned automatically — set it manually:
# For personal accounts (no --scope needed):
vercel alias set <deploy-url> <alias>.vercel.app
# For team accounts only:
vercel alias set <deploy-url> <alias>.vercel.app --scope YOUR_TEAM_SCOPE
Note: script -q /dev/null suppresses interactive prompts on macOS but breaks on Linux. Use plain vercel deploy instead — --yes flag handles prompts cross-platform.
bash
curl -s https://<alias>.vercel.app | grep "expected string"
# 200 + expected string = ✅ done
bash
PROJECT_ID=$(python3 -c "import json; print(json.load(open('.vercel/project.json'))['projectId'])")
TOKEN=$(python3 -c "import json; print(json.load(open('$HOME/Library/Application Support/com.vercel.cli/auth.json'))['token'])")
# For personal accounts:
curl -s -X PATCH "https://api.vercel.com/v9/projects/$PROJECT_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"ssoProtection":null,"passwordProtection":null,"trustedIps":null}'
# For team accounts — add teamId:
curl -s -X PATCH "https://api.vercel.com/v9/projects/$PROJECT_ID?teamId=YOUR_TEAM_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"ssoProtection":null,"passwordProtection":null,"trustedIps":null}'
After a successful deploy, the last message to the user must be the public URL — nothing else:
text
✅ https://<alias>.vercel.app
What went wrongHow to do it rightGenerated HTML in response text (hit 32k token limit)Always write HTML directly to file using Write/Edit toolDeployed from home directory (wrong CWD)Always deploy from the project folder with .vercel/project.jsonMultiple deploys for separate editsAll edits → one deployDidn't verify file actually changed before deployinggrep before deployingDidn't verify after deploycurl on the live URL after every deployUsed --scope on a personal account--scope is for team accounts onlyUsed script -q /dev/null on LinuxUse plain vercel deploy --yes insteadStored token in ~/.zshrcKeep token in env only, never write to filesStarted with partial understandingRead source fully first, make a diff, then apply all edits
--name is deprecated — don't use itvercel project rm doesn't support --yes — interactive onlyvercelAuthentication is NOT supported in API v9 — use ssoProtection: nullvercel deploy --prod the default alias is assigned automatically, custom alias is not (always verify).vercel/project.json yet — just run vercel deploy --yes --prod, it creates the project automatically