NODE_ENV y Next.js para agentes: no dejes production pegado en el shell
Resumen
Next.js carga .env* y trata NODE_ENV como suyo: next build es production, next dev es development. Un harness que exporta NODE_ENV=production rompe tests y a veces el build. Esta guía cubre unset para next build, development para vitest, NEXT_PUBLIC_ y no commitear .env. Docs Next 16.

Qué resuelve
Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.
Varios agentes (Hermes incluido) arrancan con NODE_ENV=production. En una app Next eso no es “más realista”: rompe el loop local. next build ya fuerza production por su cuenta. Si el padre del proceso ya trae production, Vitest, next dev y a veces el propio build se pelean.
La doc de Environment Variables (Next 16.3, actualizada 2026-08-25): Next carga .env* solo desde la raíz del proyecto, no desde /src. create-next-app mete .env* en gitignore: casi nunca quieres commitearlos. Eso encaja con gitignore vs sandbox.
Quién pone NODE_ENV
| Comando | NODE_ENV que espera |
|---|---|
next dev | development |
next build | production (lo setea Next) |
next start | production |
vitest / pnpm test | test o development, no production |
Receta para el agente:
NODE_ENV=development pnpm test
NODE_ENV=development pnpm lint
unset NODE_ENV
pnpm build
unset es más seguro que NODE_ENV=production pnpm build heredado del padre: dejas que Next lo ponga. Si el harness no puede unset, env -u NODE_ENV pnpm build.

.env vs NEXT_PUBLIC_
Next:
- Variables en
.env→process.enven servidor (Route Handlers, etc.). - Prefijo
NEXT_PUBLIC_→ se bundlea al browser. Un agente que pone el API key enNEXT_PUBLIC_STRIPEacaba en el JS del cliente.
Multiline y \n en .env están documentados. El agente no “arregla” una clave PEM partiéndola mal.
@next/env + loadEnvConfig(process.cwd()) si un ORM o Vitest corre fuera del runtime Next. No reimplementes el parser.
.env vive en la raíz, no en src/. Un worktree nuevo no hereda el .env del principal: cópialo a propósito o no.
Lo que el agente no hace
echo SECRET >> .envygit add .env.NODE_ENV=production pnpm test“para ver prod”.- Inventar
.env.localcon keys del chat. - Asumir que Vercel inyecta las mismas vars en local.
El curso instalar un agente no cubre el env del proceso padre. Sandboxing no unsetea variables.

Checklist AGENTS.md
Test/lint: NODE_ENV=development pnpm …
Build: unset NODE_ENV && pnpm build
Never commit .env*
Never NEXT_PUBLIC_ for secrets
.env only at repo root
FAQ
¿Por qué production rompe Vitest? jsdom / next test utils asumen development. Production minifica y salta asserts.
¿.env.production en build? Next lo carga en build/start. No lo commitees si tiene secretos.
¿Turbopack? El env es el mismo. Un symlink de node_modules fuera del root es otro error.
Si el CI de Vercel está verde y el agente local no, lo primero es echo $NODE_ENV en el mismo shell. Nueve de diez veces el padre dejó production. Un printenv | grep NODE antes de test/build es más barato que un issue de “Vitest 0 tests”.
Verificado 2026-09-03 contra Next.js Environment Variables (16.3.4).
Lecturas relacionadas
Sigue explorando Coding Agents y otras piezas para builders.

git status para coding agents: porcelain, XY, no el long

Reusable workflows: workflow_call, no copies el YAML entre repos

schedule (cron) en GitHub Actions: UTC, no cada minuto
