Cloud credentials
What every entry in `.env.cloud.example` is for, how the cloud-dev session consumes it, and what is intentionally not there.
The cloud-dev session (Claude Code on the web) has no direct access to
local secrets. Credentials are delivered through the environment variables
panel at Settings → Environment in claude.ai/code. The canonical list
is .env.cloud.example;
your actual .env.cloud is gitignored.
How each credential is actually used
Most entries are not process.env.X that the app reads at runtime. The
env channel is just the only way the cloud agent accepts secrets — what
each value really does varies by type:
| Type | Examples | Behavior |
|---|---|---|
| Tools auto-consume | VERCEL_TOKEN, AWS_*, SLACK_* | Read by CLIs / MCP servers without agent action |
| Raw materials for the agent | GH_TOKEN, E2E_*, VERCEL_AUTOMATION_BYPASS_SECRET | Delivered as env; agent invokes them via specific commands per recipe |
| Pulled from Vercel | OIDC_*, API URLs, per-app bypass header | Written into apps/<app>/.env.development.local by pnpm cloud:bootstrap. Not in .env.cloud |
The variable name often reflects a historical CI use case, not the
real scope. The
use-cloud-credentials skill
makes the real scope explicit per credential. Read it before assuming a
name means what it sounds like.
The credential list
The actual contents of .env.cloud.example change over time as new
services are wired up. The current set, grouped by purpose:
Vercel CLI bootstrap
| Variable | Real scope |
|---|---|
VERCEL_TOKEN | Personal access token scoped to the today-platform team. Used by vercel pull to fetch OIDC creds + API URLs + per-app bypass headers into per-app .env.development.local. |
VERCEL_ORG_ID | Pre-filled constant — the today-platform team's Vercel org ID |
VERCEL_PROJECT_ID_WEB | Pre-filled — apps/web Vercel project |
VERCEL_PROJECT_ID_ADMIN | Pre-filled — apps/admin Vercel project |
VERCEL_PROJECT_ID_DOCS | Pre-filled — design-system/docs Vercel project |
VERCEL_PROJECT_ID_DEV_DOCS | Pre-filled — apps/dev-docs Vercel project (this site) |
pnpm cloud:bootstrap reads these to call vercel pull for each app.
AWS CLI
| Variable | Real scope |
|---|---|
AWS_ACCESS_KEY_ID | Read-only IAM user, CloudWatch Logs only |
AWS_SECRET_ACCESS_KEY | Paired with the access key |
AWS_DEFAULT_REGION | us-west-2 — pre-filled |
Consumed by pnpm cloud:logs to tail backend CloudWatch logs (defaults to
/today/api/dev).
GitHub (cross-repo)
| Variable | Real scope |
|---|---|
GH_TOKEN | Fine-grained PAT with contents:read on todayai-labs/*. General-purpose GH cred for any cross-repo operation. |
Use it to clone sibling repos (todayai-labs/today-cloud), to read PRs /
issues in sibling repos, to query GitHub API beyond what the agent's
built-in tools cover.
E2E testing
| Variable | Real scope |
|---|---|
E2E_USER_EMAIL | Test user email — the dev-environment seed has this user with a known password / OTP path |
E2E_ADMIN_EMAIL | Admin test user — same shape |
E2E_SHARED_SECRET | Gates /internal/e2e/last-otp — the cloud endpoint that returns the latest OTP for an email without going through Resend |
VERCEL_AUTOMATION_BYPASS_SECRET | Vercel deployment protection bypass header (x-vercel-protection-bypass) — works for any client, not just CI |
PLAYWRIGHT_BASE_URL | Defaults to the dev environment if unset; override to test against a specific preview deployment |
Playwright smoke / full configs read these; ad-hoc curl / fetch can use
the bypass secret directly via the x-vercel-protection-bypass header.
Slack (MCP)
| Variable | Real scope |
|---|---|
SLACK_BOT_TOKEN | Bot token for the Slack MCP server. Wired via .claude/settings.json; agents call the MCP tools, the server reads this. |
SLACK_TEAM_ID | Team ID for scoping queries |
When the agent reads Slack ("check the deploy channel for errors"), the MCP server handles auth; the agent never touches the token directly.
Onboarding (Vite app)
| Variable | Real scope |
|---|---|
DEV_API_TOKEN | Token used by apps/onboarding (Vite) to talk to dev APIs without a real session. Lives in .env.cloud because onboarding has no Vercel project, so vercel pull can't fetch it. |
What's intentionally NOT in .env.cloud
The .env.cloud.example header comment lists what to leave out:
WEB_NEXT_PUBLIC_OIDC_*/ADMIN_*equivalents — these are fetched bypnpm cloud:bootstrap(viavercel pull) intoapps/<app>/.env.development.local. Listing them in.env.cloudwould create a stale second source of truth.- Local-only credentials — anything that wouldn't apply to the cloud session (whistle CA fingerprints, machine-specific keychains).
The pattern: vercel pull is the source of truth for per-app dev
credentials; .env.cloud is for everything else.
Setting up a fresh cloud session
When you first connect a new cloud session to this repo:
# In the cloud-dev shell, after the agent clones the repo:
pnpm install # workspace deps
pnpm cloud:bootstrap # vercel pull for web + admin (writes per-app .env.development.local)
# verify by running typecheck:
pnpm typecheck # should be greenIf pnpm cloud:bootstrap errors out, check VERCEL_TOKEN in the env
panel — it's the most common rotation casualty.
Defensive practices
From the use-cloud-credentials
skill:
- Never echo / print / log a credential value. To confirm presence
without leaking, redact:
${VAR:0:4}… - Never include a credential in commit messages, PR descriptions, comments, or error reports. If a tool emits the credential in an error, paraphrase before reporting back.
- Treat names as historical, not authoritative. Re-read the skill before assuming a credential's scope is what its name suggests.
The maintain-cloud-dev skill runs a monthly audit; rotated credentials
that the audit catches surface as one-line action items.
Related
- Cloud dev (Claude Code on the web) — full setup walkthrough for the cloud session
- Claude skills — what
use-cloud-credentialsandmaintain-cloud-devare and when each loads - Agent E2E testing — the primary consumer
of
E2E_*credentials