Hoy tu agente de IA te arma una aplicación en una tarde: backend, base de datos, tareas programadas y todo funcionando en tu laptop. El problema empieza después, cuando la subes, tiene usuarios reales y cada cambio que pides puede romper lo que ya están usando.

Este artículo es para quien hace vibe coding con Claude Code, Codex, OpenCode o Cursor y ya tiene un proyecto de verdad. Tiene dos partes:

  • Parte 1: los tips del video: entornos de desarrollo, reglas de contexto, skills propios, documentación y subagentes con worktrees.
  • Parte 2: lo que el video no cubre y conviene revisar antes de publicar: secretos, autenticación, seguridad del backend, tests y CI.

🎥 Mira el video completo: Vibe coding con usuarios reales: no rompas producción

Parte 1: los tips del video.

1. Separa producción y staging

Cuando tu proyecto tiene una sola copia, cada cambio va directo al entorno donde están tus usuarios y sus datos. Eso trae dos problemas:

  • Si el cambio tiene un error, tu usuario lo ve al instante y puede que no pueda usar la app.
  • No puedes corregir un error urgente sin arrastrar lo que tienes a medias. Si estabas trabajando en otras cosas, para publicar la corrección tienes que subir todo junto.

La solución es tener otra copia completa del proyecto, con su propio servidor: es como desplegarlo dos veces. Cada copia es un entorno:

  • Producción: lo que usan tus usuarios.
  • Staging (o desarrollo): una copia de producción donde pruebas los cambios antes de publicarlos.
  • Ramas de experimento: cambios que quizá nunca lleguen a producción. Por ejemplo, si estás probando pagos con cripto, puedes tener una rama cripto; si no te convence, la borras y no afecta a nada.

Da igual que trabajes solo o en equipo: como mínimo, ten producción y staging.

Y sí, la copia es de todo: frontend, backend y base de datos. En el video lo muestro con Railway: todo proyecto nace con un entorno production y, al crear uno nuevo (por ejemplo staging), puedes duplicar el existente. Según su documentación, el duplicado copia servicios, variables y configuración, y cada entorno tiene su propia red privada y sus propias bases de datos con sus propios volúmenes. Un patrón habitual es que staging se despliegue solo desde una rama staging o develop. Vercel, AWS Amplify o Netlify tienen su propia forma de hacerlo, pero la idea es la misma.

Algunas reglas que te ahorran sustos:

  • Una base de datos por entorno. Nunca conectes tu máquina ni al agente a la base de producción. Un "limpia la tabla de usuarios" mal entendido no tiene vuelta atrás.
  • Las mismas variables, distintos valores. DATABASE_URL, STRIPE_KEY, etc. existen en todos los entornos, pero apuntan a recursos distintos. Mantén un .env.example con los nombres y sin valores.
  • Producción se despliega desde una rama, por ejemplo main, nunca a mano desde tu laptop.
  • Datos de prueba, no datos reales. No copies a staging los correos y datos personales de tus usuarios.

2. Reglas de contexto: CLAUDE.md y AGENTS.md

Las reglas de contexto son un archivo en la raíz del proyecto que el agente lee al empezar cada sesión. En Claude Code es CLAUDE.md (el comando /init te genera uno), y Codex, Cursor u OpenCode leen AGENTS.md.

El error típico es dejar que se llene con un resumen enorme de todo el proyecto. Esa información el modelo la descubre solo mientras trabaja, y además cambia cada vez que modificas el proyecto. Anthropic recomienda mantener cada CLAUDE.md por debajo de 200 líneas: los archivos largos ocupan más contexto y se siguen peor.

Úsalo a tu favor: escribe solo las reglas que de verdad necesitas. Por ejemplo, explicarle tus entornos:

# AGENTS.md

Este proyecto tiene dos entornos: producción y staging.
- La rama `main` es producción. La rama `develop` es staging.
- Todos los cambios se hacen en la rama `develop`.
- No toques `.env`, ni migraciones ya aplicadas, ni la base de producción.
- Antes de dar una tarea por terminada, pruébala y muéstrame el resultado.

Con esa regla, cuando en el video le pido a Claude Code que cree un CLI, trabaja en la rama develop aunque yo estuviera en main. Si quieres ver tus ramas, git branch en la terminal o el panel de Git de tu editor te las muestran (incluidas las de GitHub, como origin/main).

Ya no necesitas dos archivos. Antes, para que Claude Code y otros agentes leyeran las mismas reglas, tenías que duplicar el texto en CLAUDE.md y AGENTS.md. Desde la versión 2.1.277, Claude Code lee AGENTS.md directamente. Un detalle importante de su documentación: solo lo lee si no hay un CLAUDE.md en tu carpeta o en las superiores. Si tienes los dos, lee únicamente CLAUDE.md. Así que si te quedas con AGENTS.md, borra el CLAUDE.md (o impórtalo desde él con @AGENTS.md).

Cada vez que corrijas al agente dos veces por lo mismo, esa corrección debería acabar en este archivo.

3. Skills propios de revisión

Los modelos actuales (Opus 5.5, GPT-6 Astra…) ya no necesitan que les repitas reglas básicas como "no subas el .env a GitHub". Lo que sí ayuda en vibe coding es tener skills de revisión: instrucciones reutilizables para las cosas que siempre quieres comprobar.

Dónde guardarlos dentro del proyecto:

  • .agents/skills/: la carpeta estándar que leen Codex, Cursor y otras herramientas.
  • .claude/skills/: la que lee Claude Code.

No hace falta escribirlos desde cero. Puedes pedírselo al agente: "Crea un skill en .agents y .claude para revisar código sin usar, código repetido y código mal optimizado". Yo nombro los míos con un prefijo (fx-review, fx-test); si no se te ocurre uno, my-review sirve. Lo importante es que el nombre vaya en minúsculas y con guiones.

Escríbelos cortos y genéricos

Aquí está el error más común: instalar o generar skills y no leerlos nunca. El modelo no es determinista: la misma petición puede dar respuestas distintas, así que lo que de verdad controla el resultado son las instrucciones que le das. Si son largas, repetitivas o no las entiendes, el agente las sigue igual y el resultado empeora.

Lo que me encontré al generar el skill:

  • Salió muy largo, con pasos de Git y nombres de carpetas del proyecto. Si quieres reusarlo en otros proyectos, esas referencias no sirven. Pídele: "Haz el skill mucho más puntual y compacto".
  • Los ejemplos limitan al modelo. Si el skill dice "busca código sin usar en exports, imports y variables", el modelo revisa solo eso. Algo más vago, como "revisión de código sin usar", le deja revisar mucho más.
  • No dependas de librerías concretas, que cambian cada pocos meses. Describe el problema: consultas N+1, consultas que devuelven más de lo necesario, bucles innecesarios.

Así quedaría un skill de revisión que cualquiera puede leer y ampliar:

---
name: my-review
description: Revisión de código sin usar, lógica repetida y código mal optimizado.
---

Revisa el proyecto buscando:

- Código sin usar: archivos o funciones que nada utiliza.
- Lógica copiada en dos o más sitios.
- Código mal optimizado: consultas N+1, consultas que devuelven más de lo
  necesario, bucles innecesarios.

Para usarlo escribes /my-review o simplemente "haz un review del código", y el agente lo carga solo. Si no aparece, en Claude Code está /reload-skills. Tener muchos skills no llena el contexto: al empezar solo se cargan sus nombres y descripciones, y el contenido completo entra cuando hace falta. Yo tengo 163 y no se cargan todos de golpe.

Es buena idea tener un skill por tarea (uno de calidad, otro de seguridad, otro de rendimiento) en lugar de uno que lo haga todo: el modelo trabaja mejor con una tarea bien descrita.

4. Un skill de testing con Playwright CLI

El mismo proceso sirve para las pruebas. En el video le pido al agente:

Crea un skill en .agents y .claude con instrucciones para hacer tests automatizados usando Playwright CLI. Si no está disponible, usa Chrome DevTools. Al terminar los tests, elimina los archivos generados por la herramienta de testing y comprueba los últimos cambios implementados. Sé conciso y puntual en el skill.

Si no sabes programar, añade algo como "estos skills son para alguien sin conocimiento técnico: haz los textos genéricos". El resultado pasa de una lista de comandos a pasos que entiendes y puedes cambiar:

---
name: fx-test
description: Prueba en el navegador los últimos cambios de la app.
---

1. Mira qué cambió en los últimos cambios.
2. Abre la app y pruébala en el navegador con Playwright CLI
   (o Chrome DevTools si no está disponible). Usa el modo headed.
3. Decide si funciona y explica qué probaste.
4. Deja todo limpio: borra los archivos que generó la prueba.

La última regla del paso 2 la añadí después: Playwright CLI abre el navegador sin interfaz por defecto, y con el modo headed (--headed) ves la ventana mientras el agente navega, se registra o hace cualquier operación de tu app. Playwright CLI está pensado para agentes de código: gasta menos tokens que un servidor MCP y puede instalar su propio skill con playwright-cli install --skills.

Si no conoces estas herramientas, tengo un video de cada una: Playwright CLI y skills y Chrome DevTools MCP.

5. Documenta lo justo (y en diagramas)

La documentación también se actualiza como el código, así que no se trata de generarla y olvidarte. Su valor está en que entiendas qué está haciendo el agente y puedas corregirlo antes de que lo implemente.

Documenta solo lo importante: el diseño del backend, el del frontend o un resumen del proyecto, pero muy puntual. Una forma rápida de ver el panorama completo es pedir un diagrama: "En la carpeta docs crea un gráfico de Mermaid resumiendo toda la arquitectura del proyecto". En VS Code lo ves con la vista previa de Markdown:

UsuariosWeb Next.jsmidominio.comAPI Expressapi.midominio.comPostgreSQLStripePayPal

Es un plano básico, pero luego puedes pedir uno solo del backend, otro del frontend, y así ir aprendiendo de qué se trata cada parte sin leer páginas de texto.

6. Subagentes y worktrees: varias tareas sin que choquen

Cuando trabajas con un agente, normalmente le vas pidiendo cosas una detrás de otra. En Claude Code, si le das una tarea mientras está con otra, se encola: la hace cuando termina la anterior. Si quieres avanzar en paralelo, tienes dos herramientas.

Subagentes. Le dices "crea un subagente para…" y el hilo principal lanza otra sesión con su propio contexto. En el video lo hago mientras el agente principal añade un MCP:

  • Un subagente crea un skill que explica cómo usar el CLI del proyecto.
  • Otro quita la documentación innecesaria.

El prompt de cada subagente lo escribe el hilo principal, no tú. Cuando terminan, le reportan el resultado al principal, así que sigues hablando con una sola conversación.

Worktrees. Esas tres tareas no tocaban los mismos archivos. Pero si pides algo que cambia todo el proyecto, como integrar el login con Google o con GitHub, los agentes se pueden pisar. Para eso, pide que use un worktree: "crea un subagente para integrar GitHub usando un worktree".

Un worktree no es solo una rama: es una copia de todos los archivos del proyecto, en su propia rama, tomada como una foto en el tiempo. El agente trabaja en esa copia y, al terminar, une sus cambios con los originales. Según la documentación de Claude Code:

  • Se crean en .claude/worktrees/.
  • Puedes arrancar una sesión aislada con claude --worktree.
  • Puedes hacer que un subagente use siempre uno con isolation: worktree.
  • El worktree de un subagente se borra solo si termina sin cambios.

Tienes que pedirlo: si no dices "usa un worktree", el subagente trabaja sobre los mismos archivos que el resto.

Todo esto lo hice sin herramientas extra, solo con lo que trae el propio harness de Claude Code. Y revisa lo que devuelven los subagentes: también se equivocan.


Parte 2: lo que el video no cubre.

Lo anterior te ayuda a trabajar sin romper producción. Lo que sigue es lo mínimo que conviene revisar antes de publicar algo hecho con IA, porque el agente hace lo que le pides y casi nadie le pide lo que no se ve.

7. API keys y secretos

Es de los errores más frecuentes en apps hechas con IA, y de los más caros.

Nunca en el código

  • Las claves van en variables de entorno, nunca escritas en el código.
  • El archivo .env va en .gitignore desde el primer commit, y se versiona solo el .env.example:
# .gitignore
.env
.env.*
!.env.example
  • Si una clave llegó a un commit, ya está filtrada, aunque borres el archivo después: sigue en el historial de git. La única solución es rotarla: revocarla en el proveedor y crear una nueva.

Lo que va al navegador es público

Todo lo que llega al frontend lo puede leer cualquiera con las herramientas del navegador. En Next.js son las variables NEXT_PUBLIC_*; en Vite, las VITE_*.

Si pones ahí la clave secreta de OpenAI, Anthropic o Stripe, alguien la va a encontrar y la factura la pagas tú. Las llamadas que usan claves secretas se hacen siempre desde tu backend.

Permisos mínimos, límites de gasto y secret managers

  • Usa claves con el mínimo permiso posible (por ejemplo, las restricted keys de Stripe).
  • Configura límites de gasto y alertas en los proveedores de IA y en tu nube. Si una clave se filtra, el daño queda acotado.
  • Cuando el proyecto crece, guarda los secretos en un secret manager (AWS Secrets Manager, Google Secret Manager, Doppler, Infisical, 1Password…) o, como mínimo, en las variables de entorno de tu hosting, nunca en un archivo subido al servidor.
  • Activa el escaneo de secretos de GitHub (secret scanning y push protection) o una herramienta como gitleaks.

8. Autenticación y JWT

No inventes tu propio login

Si puedes, usa una solución probada: Auth.js, Better Auth, Clerk, Supabase Auth o la de tu framework. El login es de las partes donde un agente puede generar algo que "funciona" y a la vez es inseguro.

Si usas JWT, lo básico

  • Fírmalo con un secreto largo y aleatorio, guardado como secreto. Nunca uses valores de ejemplo como "secret".
  • Expiración corta para el access token y un refresh token que se renueve y se pueda revocar.
  • Valida la firma y la expiración en el servidor en cada petición. Decodificarlo no es validarlo.
  • No guardes datos sensibles dentro del token. El payload de un JWT es base64: cualquiera puede leerlo.
  • Guárdalo en una cookie httpOnly, Secure y SameSite en lugar de localStorage, donde cualquier script inyectado (XSS) lo puede robar:
res.cookie("session", token, {
  httpOnly: true,   // JavaScript del navegador no puede leerla
  secure: true,     // solo viaja por HTTPS
  sameSite: "lax",  // reduce el riesgo de CSRF
  maxAge: 15 * 60 * 1000,
});

Contraseñas

Siempre con un hash diseñado para contraseñas: argon2 o bcrypt. Nunca en texto plano, y tampoco con MD5 ni con SHA: son demasiado rápidos y se pueden probar a miles de millones por segundo.

Autenticado no es autorizado

Que el usuario haya iniciado sesión no significa que pueda ver cualquier cosa. Si tu API responde a /api/pedidos/123, el backend tiene que comprobar que ese pedido es del usuario que lo pide. Los agentes olvidan esta comprobación con mucha frecuencia:

// Mal: cualquiera con sesión puede pedir cualquier pedido
const pedido = await db.pedido.findUnique({ where: { id } });

// Bien: el pedido tiene que ser del usuario que lo pide
const pedido = await db.pedido.findFirst({
  where: { id, userId: session.user.id },
});
if (!pedido) return new Response("No encontrado", { status: 404 });

Y recuerda: ocultar un botón en el frontend no protege nada. Si la API responde, cualquiera puede llamarla directamente.

9. Seguridad básica del backend

Una lista corta que vale la pena pedirle explícitamente al agente (o convertir en un skill de seguridad, como en el tip 3):

  • Valida todas las entradas con un esquema (por ejemplo, zod) antes de usarlas.
  • Consultas parametrizadas u ORM, nunca concatenar texto del usuario en una consulta.
  • CORS restringido a tus dominios, no *.
  • Rate limiting en el login, el registro y cualquier endpoint caro, sobre todo los que llaman a un modelo de IA.
  • Errores genéricos en producción y nada de secretos ni datos personales en los logs.
  • Apaga lo que sobra: endpoints de depuración, usuarios administradores de ejemplo y contraseñas por defecto que el agente dejó para probar.
  • Si usas Supabase o Firebase, activa las reglas de acceso (RLS o security rules).
  • Dependencias: revisa npm audit y verifica que cada paquete que agrega el agente existe y es el que crees. A veces los modelos inventan nombres de paquetes, y hay gente registrando esos nombres con código malicioso (slopsquatting).

Pagos y webhooks

  • Verifica la firma del webhook con el secreto del endpoint. Si no, cualquiera puede llamar a tu URL y fingir un pago.
  • Sé idempotente: el proveedor puede enviar el mismo evento más de una vez.
  • No des acceso por lo que diga el navegador. Activa el plan cuando llega el webhook confirmado, no cuando el frontend dice "pagado".

Subida de archivos

  • Valida el tipo real y el tamaño en el servidor, no solo la extensión.
  • Guarda los archivos con nombres generados por ti y en un bucket privado por defecto, con URLs firmadas temporales.

10. Planifica, divide y usa Git como red de seguridad

  • Pide un plan antes del código: qué archivos va a tocar, qué enfoque seguirá y cómo se comprueba que funciona (en Claude Code, el plan mode). Es más barato corregir un plan que deshacer cien líneas.
  • Una tarea = una rama = un cambio pequeño, con un criterio claro de "hecho". Y una conversación por tarea: cuando el contexto se llena de cosas viejas, el agente empieza a olvidar.
  • Pull requests aunque trabajes solo, commits pequeños y main protegido.
  • Limita lo que el agente puede hacer: no le des credenciales de producción, y los modos que aprueban todo sin preguntar (como --dangerously-skip-permissions) déjalos para entornos aislados.
  • Cuidado con la prompt injection: un archivo, un issue o una página web que el agente lee pueden traer instrucciones escondidas. Lee los skills y servidores MCP de terceros antes de instalarlos.

11. Tests y CI antes de desplegar

Un agente que dice "listo" no ha demostrado nada.

  • Cubre lo crítico primero: pagos, login y permisos. Añade un test de punta a punta del flujo principal (el skill de testing del tip 4 es un buen punto de partida).
  • Revisa qué cambió en los tests. Un agente atascado a veces "arregla" el test en lugar del código.
  • Ejecuta la app tú mismo antes de dar nada por bueno.
  • Despliegue con puertas: cada PR pasa por CI y por staging, y solo main llega a producción.
# Pasos mínimos de CI en cada pull request
- run: npm ci
- run: npm run lint
- run: npm run typecheck
- run: npm test
- run: npm audit --audit-level=high
  • Migraciones primero en staging, backups probados, monitoreo de errores (por ejemplo, Sentry), alertas de costos y un plan para volver a la versión anterior si un deploy sale mal.

Checklist rápido

Tu flujo con agentes

  • Producción y staging separados, cada uno con su base de datos.
  • Un AGENTS.md (o CLAUDE.md) corto, con tus reglas y tus entornos.
  • Skills propios de revisión y testing, que hayas leído y entiendas.
  • Documentación puntual y un diagrama de la arquitectura.
  • Subagentes para tareas independientes y worktrees cuando tocan los mismos archivos.

Antes de publicar

  • Ninguna clave en el código, en el historial de git ni en el frontend.
  • Login con una librería probada y cada endpoint comprueba que el recurso es del usuario.
  • Validación de entradas, CORS, rate limiting y webhooks con firma verificada.
  • Tests de lo crítico, CI con puertas y backups probados.

Conclusión

Me quedo con tres ideas:

  • ✅ Nunca pruebes sobre producción: un entorno de staging te deja equivocarte sin que tus usuarios lo noten.
  • ✅ Lee lo que le das al agente: reglas y skills cortos, genéricos y escritos para que tú los entiendas.
  • ✅ Paraleliza con cabeza: subagentes para lo independiente y worktrees para lo que puede chocar.

Si tienes dudas o quieres que amplíe alguno de estos temas, déjamelo en los comentarios del video en YouTube.

Fuentes