add-env-var
Add, rename or remove an environment variable or setting for any service, locally and in every deployed environment. Use when code needs a new setting, a secret, a provider key or a feature switch.
SKILL.md.claude/skills/add-env-var/SKILL.md
GitHubAdd an environment variable
A variable lives in up to six places, and all of them change together.
- Validate it where the service reads it, with a type and bounds:
- a Nest service: its
src/env.ts(t3-env, zod). One several services share: a fragment inpackages/nest-common/src/env.ts, spread into each; - web:
apps/web/src/env.ts(server-only; the browser gets nothing); - ai: a field in
apps/ai/app/settings.pywithalias="<NAME>"and a constraint; - mobile: build-time in
apps/mobile/app.config.ts, runtimeEXPO_PUBLIC_*insrc/lib/config.ts(public: never a secret). Importenv; never readprocess.envelsewhere.
- a Nest service: its
- A feature switch? Optional features are on only when their variables are set:
add it to
featuresinapps/api/src/features.ts(both-or-neither for pairs) and toFEATURESinpackages/contracts/src/api/system.ts, so disabled procedures answerFEATURE_DISABLEDand clients hide the UI. - Production guard. A test-only value (a fake URL, a loopback address, a local
stand-in) is refused at boot when
NODE_ENV=production, next to the existing guards at the end of the service'ssrc/env.ts. .env.example, in its section, with a comment saying what it does and what switches on. A secret getschange-mesobun run setupgenerates it (packages/testing/src/secrets.tsknows the formats); an optional one stays empty. Tests run with these values, never.env.docs/environment.md: a row in the service's table (name, who reads it, default, what it does).- Deployed. A plain setting: the service's
envindeploy/charts/stack/values.yaml, or per environment indeploy/environments/<env>/stack.yaml. A secret: the service's SOPS Secret (deploy/environments/<env>/secrets/<service>.sops.yaml; the user edits it withsops, you never decrypt it), and its line in the templates indocs/new-project.mdand the list indeploy/README.md.
Locally: bun run setup adds the new key to .env (the doctor fails until then);
bun run env:set NAME=value sets it. Never read .env.
Removing one: delete it from all of the above in one change; the doctor then reports it
as stale in existing .env files, and bun run env:unset NAME deletes it.
Done when
bun run check-typesandbun run testpass (every suite runs with.env.example's values, so a required variable missing there fails them).- The service starts with the example value (
bun dev, in the background) and refuses a bad one with a readable message. bun run charts:checkpasses ifdeploy/changed.- The
docs-syncagent reports nothing out of date; thesecurity-revieweragent for a secret.