Dejé de Programar por Intuición y Comencé con 'Contratos de Prompts' — Mi Código con Claude Pasó de Ser una Apuesta a Funcionar de Verdad
No era porque fuera código malo. Compilaba. Funcionaba. Hasta se veía limpio.
Pero resolvía el problema equivocado. Había pedido un flujo de autenticación con Supabase y seguridad a nivel de fila. Lo que recibí fue un hermoso sistema de auth de nivel producción — usando Firebase.
Claude Code me hizo un clásico reverse de Uno a todo mi stack. Como pedir una pizza y recibir un risotto perfectamente cocinado. Técnicamente impresionante. Fundamentalmente incorrecto.
Ese fue el momento en que me di cuenta de algo incómodo: No estaba programando con Claude Code. Estaba apostando con él.
Y si estás escribiendo prompts en lenguaje natural en Claude Code 🧑💻 esperando lo mejor, tú también estás tirando dados. Excepto que el dungeon master es una IA sin contexto y con confianza infinita.

La Trampa del Vibe Coding
Así se ve el vibe coding en la vida real:
> Créame un dashboard para mi SaaS
Claude Code escribe 3,000 líneas en 14 archivos. Entrecierras los ojos mirando el resultado como si intentaras ver un poster de Magic Eye. Algo parece estar bien.
Lo ejecutas.
Algo se rompe.
Dices "arréglalo."
Arregla una cosa, rompe tres más. Esto no es debugging. Es whack-a-mole con una suscripción de $100 al mes.
Hace unas semanas, me topé con un concepto de un ex-ingeniero de OpenAI: Prompt Contracts
Cuarenta y cinco minutos después, has enviado algo que funciona pero que no entiendes completamente. Felicidades, ahora estás manteniendo un código escrito por una inteligencia alienígena que no recuerda haberlo escrito. Qué podría salir mal.
Viví en este bucle durante meses. Lancé dos productos SaaS casi completamente con Claude Code, y no exagero cuando digo que el 30% de mi tiempo lo pasé deshaciendo cosas que Claude Code construyó confiadamente en la dirección equivocada. Es como programar en pareja con un genio que tiene amnesia y cero concepto de tu repo.
El problema nunca fue la inteligencia de Claude Code. Opus 4.6 es absurdamente capaz — es básicamente un ingeniero senior que leyó todas las respuestas de Stack Overflow jamás publicadas y las retuvo todas, incluyendo las incorrectas.
El problema era que mis prompts eran vibes, no especificaciones.
"Hazlo responsive." "Agrega manejo de errores." "Usa mejores prácticas."
Estas no son instrucciones. Son horóscopos. Y Claude Code no es un adivino — es un contratista. No le darías a un contratista una servilleta que dice "construye casa, que quede bonita" y esperarías la casa de tus sueños. Obtendrías una casa. Hasta podría tener paredes. Pero el baño estaría en la cocina porque nunca dijiste que no debería estar ahí.
Prompt Contracts: La Solución
Hace unas semanas, me topé con un concepto de un ex-ingeniero de OpenAI: Prompt Contracts. La idea es simple — en lugar de escribir prompts como briefs creativos, escríbelos como contratos legales con cuatro cláusulas ejecutables:
Goal — la métrica exacta de éxito. Constraints — límites duros que no se pueden cruzar. Output Format — la estructura específica que esperas. Failure Conditions — qué hace que el resultado sea inaceptable.
Pensé: "Esto está lindo para posts de ChatGPT. ¿Pero puede sobrevivir a Claude Code construyendo un backend real a las 3 AM cuando estás funcionando a base de cafeína y malas decisiones de vida?"
Así que lo probé. Durante tres semanas seguidas, en dos proyectos SaaS, reemplacé cada vibe prompt con un Prompt Contract.
Spoiler: ahora duermo.
Componente 1: GOAL — Deja de Decir "Constrúyeme X"
La mejora más grande fue obligarme a definir cómo se ve terminado antes de que Claude Code escriba una sola línea.
Antes (vibe):
> Agrega un sistema de suscripciones a la app
Esto es el equivalente en prompts de decirle a tu GPS "llévame a algún lugar bonito." Terminarás en algún lugar. Podría ser un restaurante Michelin. Podría ser una gasolinera en Ohio.
Después (contrato):
> GOAL: Implementar gestión de suscripciones Stripe donde los usuarios
> puedan suscribirse a 3 niveles (free/pro/team), actualizar/degradar
> instantáneamente, y ver estado de facturación en /settings/billing.
> Éxito = un usuario gratuito puede suscribirse a Pro,
> ver el cargo en el dashboard de Stripe, y acceder a
> funciones restringidas en 5 segundos.
La diferencia no es solo el detalle — es la verificabilidad. Cuando Claude Code termina, puedo verificar el objetivo en menos de un minuto. Sin ambigüedad. Sin "bueno, medio que funciona" — el gato de Schrödinger de las demos de software.
Solo esto redujo mi ida y vuelta con Claude Code aproximadamente a la mitad. Cuando la IA sabe cómo se ve la línea de meta, deja de vagar por la pista tomándose selfies.
Componente 2: CONSTRAINTS — Las Paredes Que Te Salvan
Aquí es donde las cosas se vuelven específicas de Claude Code, porque sin restricciones, Claude Code absolutamente reinventará tu stack por ti. Es como contratar a un renovador de cocinas que aparece y dice "también tumbé la pared de tu sala porque el feng shui estaba mal."
Ahora mantengo un CLAUDE.md en la raíz de cada proyecto que actúa como una capa de restricciones permanente:
# CLAUDE.md — Restricciones del Proyecto (siempre activas)
## Stack (no negociable, te haré mass git revert)
- Frontend: Next.js 14+ App Router, TypeScript strict
- Backend: Convex para datos en tiempo real, Supabase para auth + storage
- Auth: Clerk (nunca hagas auth custom, no somos animales)
- Styling: Solo Tailwind — no CSS modules, no styled-components
## Reglas Duras
- Nunca instales una nueva dependencia sin preguntar primero
- Nunca modifiques el schema de la base de datos sin mostrar el plan de migración
- Todas las llamadas API van a través de funciones Convex, nunca
llamadas directas del cliente Supabase desde componentes
- Variables de entorno van en .env.local, nunca hardcodeadas
(Te encontraré y te revertiré)
## Patrones
- Usa server components por defecto, client components solo cuando
se requiera interactividad
- Error boundaries en cada segmento de ruta
- Validación Zod en cada input del usuario
Antes de CLAUDE.md, Claude Code decidía aleatoriamente usar Prisma en lugar de Convex, o cambiar Clerk por NextAuth porque "es más común." Eso es como que tu barista decida que en realidad querías té porque más gente toma té globalmente. No pedí una democracia. Pedí Clerk.
¿Ahora? Se mantiene en su carril. Cada vez.
Pro tip: Cuando inicies una nueva sesión de Claude Code, tu primer mensaje debería ser:
> Lee CLAUDE.md y confirma que entiendes las restricciones del proyecto
> antes de hacer cualquier cosa.
Esto fuerza un handshake. Piénsalo como los derechos Miranda de tu código. Claude Code repite las restricciones, ambos se ponen de acuerdo sobre la realidad, y entonces comienza el trabajo. Sin esto, esencialmente estás empezando cada sesión entregando las llaves a alguien que no sabe qué auto está manejando.
Componente 3: FORMAT — Dile Exactamente Qué Entregarte
El vibe coding deja que Claude Code decida la estructura. Esto es como decirle a un chef "sorpréndeme" y luego sorprenderte cuando recibes una ensalada César deconstruida servida dentro de un zapato.
Antes:
> Crea un endpoint API para onboarding de usuarios
Claude Code decide: un archivo masivo, validación inline, sin tipos, todo en una sola función de 800 líneas que hace auth, llamadas a base de datos y envío de emails en una sola respiración. Funciona. También es un crimen de guerra contra el tú del futuro que tiene que mantenerlo.
Después:
> FORMAT:
> 1. Función Convex en convex/users.ts (mutation, no action)
> 2. Schema Zod para validación de input en convex/schemas/onboarding.ts
> 3. Tipos TypeScript exportados desde convex/types/user.ts
> 4. Incluir JSDoc en la función pública
> 5. Retornar { success: boolean, userId: string, error?: string }
Ahora obtengo código modular, tipado, documentado — cada vez. No porque Claude Code no pueda producir esto por sí solo, sino porque sin instrucciones explícitas de formato, optimiza para velocidad, no para mantenibilidad. Está haciendo speedrun de tu código. Necesitas que juegue a largo plazo.
Esto importa aún más cuando usas la función de equipos de agentes de Claude Code para paralelizar trabajo. Si tus sub-agentes no siguen el mismo contrato de formato, terminas mergeando código que parece escrito por cinco desarrolladores que se comunican exclusivamente a través de mensajes de commit pasivo-agresivos.
Componente 4: FAILURE CONDITIONS — El Arma Secreta
Este es el componente que cambió todo. Si el Goal es la zanahoria, las Failure Conditions son el palo. Y Claude Code responde a palos como un desarrollador responde a un mensaje de Slack de "producción está caído" — inmediatamente y con total atención.
Definir qué rompe el contrato le da a Claude Code un objetivo negativo. Es como entrenar a un perro: "siéntate" está bien, pero "NO en el sofá, NO en la mesa, NO encima de los suegros de visita" es lo que realmente salva tus muebles.
Aquí hay un Prompt Contract real que usé la semana pasada:
> Construye la página /dashboard.
>
> GOAL: Mostrar proyectos activos del usuario con actualizaciones en tiempo real.
> First meaningful paint bajo 1 segundo. El usuario puede crear, archivar,
> y renombrar proyectos inline.
>
> CONSTRAINTS: Convex useQuery para datos, no polling, no SWR.
> Clerk useUser() para verificación de auth. Redirigir a /sign-in si
> no está autenticado. Máximo 150 líneas por archivo de componente.
>
> FORMAT: Componente Page en app/dashboard/page.tsx (server component
> wrapper), client component en components/dashboard/ProjectList.tsx,
> query Convex en convex/projects.ts. Solo Tailwind.
>
> FAILURE CONDITIONS:
> - Usa useState para datos que deberían estar en Convex
> - Cualquier componente excede 150 líneas
> - Obtiene datos client-side cuando podría ser server-side
> - Usa cualquier librería UI además de clases utility de Tailwind
> - Faltan estados de loading y error
> - Faltan tipos TypeScript en cualquier parámetro de función
Cuando ejecuté esto, Claude Code produjo un dashboard limpio y en tiempo real al primer intento. Sin Firebase. Sin Prisma. Sin paquetes npm misteriosos de 2019 con 12 estrellas en GitHub y un README que dice "TODO." Sin god-component de 1,200 líneas que el yo del futuro necesitaría terapia para refactorizar.
Compáralo con lo que pasó el mes anterior, cuando "constrúyeme un dashboard" produjo un componente que importaba Material UI (no uso Material UI), usaba useEffect para obtener datos (tenemos Convex por una razón), y tenía cero estados de loading. Solo optimismo crudo y desprotegido de que los datos siempre estarían ahí instantáneamente. El equivalente en software de dejar tu casa sin llave porque "este es un barrio bonito."
Las failure conditions actúan como barandillas. Claude Code no tiene que adivinar qué significa "bueno" cuando ya le dijiste cómo se ve "malo." Es la diferencia entre "maneja con cuidado" y "no excedas 80, no te pases rojos, no tomes la autopista en hora pico." Una es una oración. La otra es un sistema de navegación.
🔄 Actualización: Un contrato que no mencioné en la versión original de este artículo porque aún no existía: `/security-review`. Escríbelo antes de hacer push. Claude escanea tus cambios pendientes en busca de inyección SQL, bypasses de auth, secretos hardcodeados — las cosas que te pierdes cuando estás en modo feature profundo. Escribí un desglose completo de cómo funciona y cómo personalizarlo para tu stack. Versión más corta: es la red de seguridad post-contrato. Tus Prompt Contracts hacen que Claude construya lo correcto. `/security-review` se asegura de que lo correcto no tenga un agujero.
Los Resultados (3 Semanas de Prompt Contracts)
Rastreé mi flujo de trabajo en dos proyectos activos. Los números no están peer-reviewed — soy un desarrollador en un cuarto oscuro, no un laboratorio de investigación — pero el patrón era inconfundible.
Tasa de deshacer/revertir bajó de aproximadamente 1 en 3 generaciones a cerca de 1 en 10. Claude Code dejó de construir cosas que no pedí. Mi memoria muscular de git revert ya se está desvaneciendo. Podría necesitar reaprender el comando algún día. O no. Estoy en paz con esto.
Tiempo de prompt a código utilizable pasó de un promedio de 3 rondas de ida y vuelta a 1.2 rondas. La mayoría de outputs de Prompt Contract eran utilizables en la primera o segunda generación. Esto liberó tiempo que ahora paso en cosas importantes, como sobre-ingenierizar mi CLAUDE.md y agregar failure conditions para failure conditions.
Violaciones de CLAUDE.md (librería incorrecta, patrón incorrecto, valores hardcodeados) pasaron de unas pocas por día a esencialmente cero una vez que agregué el handshake de restricciones al inicio de sesión. La combo CLAUDE.md + handshake es básicamente una checklist de pre-vuelo. Los pilotos no se la saltan. Tú tampoco deberías. A menos que disfrutes que tu código se estrelle contra una montaña metafórica.
¿La mayor sorpresa? Mis prompts se volvieron más cortos con el tiempo, no más largos. Una vez que CLAUDE.md mantiene las restricciones permanentes y internalizas la estructura de 4 componentes, un Prompt Contract para una función compleja toma tal vez 60 segundos escribir. Esos son 60 segundos que te ahorran 45 minutos de debugging y cuestionar tus decisiones de carrera.
Cómo Empezar Hoy
No necesitas reformar tu flujo de trabajo. No necesitas leer un libro de 400 páginas sobre prompt engineering. No necesitas ver un video de YouTube de 3 horas donde alguien explica el concepto en los primeros 4 minutos y luego te vende un curso durante las 2 horas y 56 minutos restantes.
Empieza con dos cosas:
- Primero, crea un
CLAUDE.mden la raíz de tu proyecto con tu stack, reglas duras y patrones. Esta es tu capa de Constraints permanente. Cada sesión de Claude Code empieza leyéndolo. Piénsalo como la Constitución de tu repo — excepto que esta sí se sigue. - Segundo, la próxima vez que estés a punto de escribir un vibe prompt como "agrega página de configuración de usuario," detente. Toma 30 segundos y agrega un GOAL, un CONSTRAINT y una FAILURE CONDITION. Solo uno de cada uno. Sentirás la diferencia inmediatamente. Es como pasar de "espero que esto funcione" a "sé que esto funciona" — un sentimiento tan raro en desarrollo de software que debería clasificarse como sustancia controlada.
El framework de Prompt Contract no se trata de escribir más. Se trata de pensar durante 60 segundos para que Claude Code no tenga que adivinar durante 60 minutos.
Pasé de apostar a enviar. Tu turno.
Si estás construyendo SaaS con Claude Code y quieres más desgloses tácticos como este, sígueme para deep dives semanales. Envío, rompo y mass-revierto cosas en público para que tú no tengas que hacerlo.
**