Capítulo 7: Rules: Convenciones Siempre Activas

Por: Artiko
claude-coderulesconvencionesestandares

1. ¿Qué son las Rules en Claude Code?

Las rules son el mecanismo más fundamental del sistema Everything Claude Code (ECC). Representan convenciones y estándares que Claude sigue siempre, en cada interacción, sin necesidad de ser invocadas explícitamente por el usuario.

Para entender qué son las rules, primero hay que distinguirlas de los otros dos artefactos principales del sistema:

Rules vs Skills vs Agentes

El sistema ECC tiene tres tipos de artefactos con roles muy diferentes:

Rules (Reglas) son directivas permanentes. Viven en archivos Markdown dentro de directorios rules/ y Claude las carga automáticamente al inicio de cada conversación. No requieren ningún comando especial para activarse. Definen comportamiento por defecto: cómo nombrar variables, cómo hacer commits, qué validaciones aplicar. Son el “siempre haz esto”.

Skills (Habilidades) son capacidades especializadas que se invocan bajo demanda. El usuario escribe /nombre-del-skill cuando necesita esa capacidad específica. Por ejemplo, /code-review activa el proceso de revisión de código. Los skills pueden ser complejos y tener múltiples pasos, pero solo se ejecutan cuando se les llama. Son el “haz esto cuando te lo pida”.

Agentes son sub-procesos independientes que Claude delega para tareas específicas. Se ejecutan en paralelo o secuencia cuando la tarea lo amerita. El orchestrator principal coordina agentes especializados. Son el “delegá esto a alguien”.

La regla de distinción más práctica: si algo debe aplicarse en toda escritura de código, va en una rule. Si algo requiere un flujo especializado que el usuario activa intencionalmente, va en un skill.

Cómo Claude Carga las Rules en Memoria

Cuando Claude Code inicia una sesión, el sistema carga automáticamente los archivos Markdown de los directorios rules/. Estos archivos se inyectan como parte del contexto del sistema antes de que el usuario escriba su primer mensaje. Esto significa que:

  1. Las rules nunca consumen tokens del presupuesto de la conversación visible al usuario
  2. Claude “ya sabe” estas convenciones desde el momento cero
  3. Las rules se aplican proactivamente, no reactivamente

El mecanismo es conceptualmente similar a un system prompt que se construye dinámicamente a partir de múltiples archivos, donde cada archivo aporta una sección de instrucciones.


2. Cómo Claude Code Carga las Rules

La jerarquía de carga de rules en ECC sigue un modelo de capas con dos niveles principales:

Nivel 1: User-Level Rules (~/.claude/rules/)

Las rules de nivel usuario viven en el directorio home del usuario: ~/.claude/rules/. Estas rules se aplican a todas las sesiones de Claude Code, independientemente del proyecto en el que se esté trabajando.

Son ideales para convenciones personales que el desarrollador quiere en todos sus proyectos:

Nivel 2: Project-Level Rules (.claude/rules/)

Las rules de nivel proyecto viven dentro del repositorio, en .claude/rules/. Estas rules solo se aplican cuando Claude Code está trabajando dentro de ese proyecto específico.

Son ideales para convenciones del equipo o requisitos del stack tecnológico:

Orden de Precedencia

Cuando hay un conflicto entre una rule de usuario y una rule de proyecto, la rule de proyecto tiene precedencia. La lógica es que las convenciones específicas del proyecto son más relevantes que las preferencias personales del desarrollador cuando se trabaja en ese contexto.

graph TD
    A[Claude Code inicia sesión] --> B[Carga rules de ~/.claude/rules/]
    B --> C[Carga rules de .claude/rules/ del proyecto]
    C --> D{¿Conflicto entre rules?}
    D -->|Sí| E[Rule de proyecto tiene precedencia]
    D -->|No| F[Ambas se aplican]
    E --> G[Claude listo para trabajar]
    F --> G

El Rol de common/

Dentro del directorio de rules, existe un subdirectorio especial: common/. Las rules en common/ son universales: se aplican independientemente del lenguaje de programación. Son la base sobre la que se construyen todas las demás rules.

El sistema ECC está diseñado para que common/ sea siempre el primer conjunto de rules que se instala. Sin common/, el agente carece de los principios fundamentales que hacen coherente todo lo demás.


3. Estructura de Directorios del Repo ECC

El repositorio de Everything Claude Code tiene una estructura clara y predecible para sus rules:

graph LR
    A[rules/] --> B[common/]
    A --> C[typescript/]
    A --> D[python/]
    A --> E[golang/]
    A --> F[swift/]
    A --> G[php/]
    A --> H[rust/]
    A --> I[java/]
    A --> J[ruby/]
    B --> B1[coding-style.md]
    B --> B2[git-workflow.md]
    B --> B3[testing.md]
    B --> B4[security.md]
    B --> B5[performance.md]
    B --> B6[development-workflow.md]
    B --> B7[patterns.md]
    B --> B8[agents.md]
    B --> B9[hooks.md]

rules/common/ — Las reglas universales que aplican a todos los proyectos sin importar el lenguaje. Esta es la base fundamental del sistema ECC.

rules/typescript/ — Rules específicas para proyectos TypeScript y JavaScript. Incluyen configuración de tipos estrictos, patrones de async/await, y convenciones de módulos.

rules/python/ — Rules para proyectos Python. Cubren PEP 8, type hints obligatorios, gestión de entornos virtuales, y patrones async con asyncio.

rules/golang/ — Rules para Go. Enfatizan el manejo idiomático de errores, interfaces implícitas, y concurrencia con goroutines.

rules/swift/ — Rules para Swift, especialmente para proyectos iOS/macOS. Cubren Swift 6 concurrency, actors, y protocolos.

rules/php/ — Rules para PHP, con foco en Laravel, seguridad específica de PHP, y patrones modernos.

rules/rust/ — Rules para Rust. Ownership, borrowing, gestión de errores con Result/Option, y patrones seguros.

rules/java/ — Rules para proyectos Java/Kotlin/Spring.

rules/ruby/ — Rules para Ruby y Rails.


4. La Regla de Oro: common/ Siempre Se Instala

Existe una convención fundamental en ECC que se denomina “La Regla de Oro”: las rules de common/ siempre deben estar instaladas. Esta no es una recomendación opcional, sino un requisito del sistema.

Por qué common/ es la Base

Las rules en common/ establecen principios que trascienden cualquier lenguaje de programación. La inmutabilidad de datos es igual de importante en TypeScript que en Python. El formato de commits convencionales aplica a cualquier proyecto. La cobertura mínima de tests del 80% no depende del framework.

Sin common/, el agente puede producir código que:

Qué Pasa si No Las Tenés

La ausencia de las rules de common/ no genera un error explícito. Claude Code no “falla” si faltan. Lo que ocurre es más sutil y más peligroso: el agente opera sin principios guía, tomando decisiones de estilo y arquitectura ad-hoc según lo que parezca razonable en el momento. Esto genera inconsistencia a lo largo del tiempo y entre diferentes sesiones.

Por ejemplo, sin coding-style.md, Claude puede mutar un array en un lugar y crear un nuevo array en otro, dependiendo de cómo esté formulada la pregunta. Sin testing.md, puede escribir tests después del código o saltearlos cuando parece complicado.

Instalación Correcta

El proceso recomendado para cualquier proyecto nuevo es:

  1. Instalar primero common/ completo
  2. Instalar las rules del lenguaje principal del proyecto
  3. Agregar rules específicas del proyecto si se necesitan

Nunca instalar solo las rules de un lenguaje específico sin common/.


5. coding-style.md — Análisis Completo

El archivo coding-style.md es probablemente la rule más importante del sistema. Define cómo debe ser el código en sí mismo, independientemente de qué hace el código.

Principio 1: Inmutabilidad (CRÍTICO)

La rule marca este principio como CRITICAL en mayúsculas por una razón: la mutación de datos es la fuente de una clase entera de bugs que son extremadamente difíciles de debuggear.

El problema con la mutación:

Cuando una función modifica un objeto que recibió como parámetro, cualquier parte del código que tenga una referencia a ese objeto ve el cambio. En sistemas con múltiples funciones, componentes o threads, esto crea dependencias implícitas que no están documentadas en ningún lado.

Código INCORRECTO (mutación en lugar):

function setUserName(user: User, name: string): void {
  user.name = name; // Modifica el objeto original
}

const user = { id: 1, name: "Ana" };
setUserName(user, "María");
// user.name ahora es "María" — cualquier otra referencia a este objeto también lo ve

Código CORRECTO (retorna nueva copia):

function setUserName(user: User, name: string): User {
  return { ...user, name }; // Retorna nuevo objeto con el cambio
}

const user = { id: 1, name: "Ana" };
const updatedUser = setUserName(user, "María");
// user sigue siendo { id: 1, name: "Ana" }
// updatedUser es { id: 1, name: "María" }

Rationale de la rule: El código inmutable hace que las funciones sean puras — su comportamiento depende solo de los inputs, no de estado externo mutable. Esto hace el debugging mucho más fácil (podés razonar sobre cada función de forma aislada), habilita la concurrencia segura (múltiples threads pueden leer sin coordinación), y facilita el testing (no hay setup de estado previo necesario).

Consecuencias de no seguirlo:

En proyectos medianos, la mutación de estado empieza a generar bugs del tipo “esto funcionaba ayer”. La función A modifica un objeto, la función B asume que ese objeto tiene el valor original, y el bug aparece solo cuando A y B se ejecutan en cierto orden. Estos bugs son especialmente difíciles de reproducir en tests porque los tests usualmente tienen control total del orden de ejecución.

Principio 2: Organización de Archivos

La rule establece una filosofía clara: muchos archivos pequeños son mejores que pocos archivos grandes. Los números concretos son:

El rationale es alto cohesión y bajo acoplamiento. Un archivo de 800 líneas que hace cinco cosas diferentes es muy difícil de mantener. Cinco archivos de 160 líneas, cada uno con una responsabilidad clara, son mucho más fáciles de entender, testear y modificar.

La directive concreta: cuando un módulo empieza a crecer, extraer utilities a archivos separados antes de llegar al límite.

INCORRECTO — un archivo monolítico:

user-service.ts  (1200 líneas con autenticación, perfil, permisos, notificaciones)

CORRECTO — responsabilidades separadas:

user-auth.service.ts      (200 líneas — solo autenticación)
user-profile.service.ts   (180 líneas — solo perfil)
user-permissions.service.ts (150 líneas — solo permisos)
user-notifications.service.ts (170 líneas — solo notificaciones)

Principio 3: Manejo de Errores

La rule requiere manejo de errores comprehensivo en tres dimensiones:

Explícito en cada nivel: No hay “me olvido de manejar este error porque es poco probable”. Si una función puede fallar, el error se maneja.

INCORRECTO:

async function fetchUser(id: string) {
  const response = await fetch(`/api/users/${id}`);
  return response.json(); // ¿Qué pasa si fetch falla? ¿Si json() falla?
}

CORRECTO:

async function fetchUser(id: string): Promise<Result<User, ApiError>> {
  try {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) {
      return { ok: false, error: new ApiError(response.status) };
    }
    const data = await response.json();
    return { ok: true, data };
  } catch (error) {
    return { ok: false, error: new ApiError(500, String(error)) };
  }
}

Mensajes amigables en UI: Los errores que llegan al usuario no deben ser stack traces ni códigos HTTP. Deben ser mensajes que el usuario pueda entender y actuar.

INCORRECTO (UI):

Error: TypeError: Cannot read properties of undefined (reading 'name')

CORRECTO (UI):

No pudimos cargar tu perfil. Por favor, intentá de nuevo más tarde.

Contexto detallado en servidor: En el servidor, los logs de error deben incluir todo el contexto necesario para reproducir y debuggear el problema: ID de usuario, parámetros de la request, timestamp, stack trace completo.

Principio 4: Validación de Inputs

La validación debe ocurrir en los límites del sistema. Un límite es cualquier punto donde datos externos ingresan al sistema: endpoints HTTP, websockets, lectura de archivos, datos de bases de datos.

Este principio previene que datos malformados o maliciosos lleguen a la lógica de negocio. La validación temprana significa errores más claros y seguridad más sólida.

Code Quality Checklist

La rule incluye un checklist de calidad que Claude debe verificar antes de considerar el código completo:


6. git-workflow.md — Análisis Completo

La rule de git workflow estandariza cómo el equipo (y Claude) interactúan con el sistema de control de versiones.

Conventional Commits: El Formato Estándar

El formato establecido por la rule es:

<tipo>: <descripción>

Los tipos válidos y cuándo usar cada uno:

feat — Introduce una nueva funcionalidad visible al usuario.

Ejemplos correctos:

feat: agregar autenticación con Google OAuth
feat: implementar búsqueda en tiempo real
feat: exportar reportes a PDF

fix — Corrige un bug que afectaba el comportamiento esperado.

Ejemplos correctos:

fix: corregir cálculo de descuento para usuarios premium
fix: resolver race condition en actualización de perfil
fix: parsear correctamente fechas en zona horaria UTC-3

refactor — Cambia la estructura del código sin cambiar el comportamiento externo.

Ejemplos correctos:

refactor: extraer lógica de validación a módulo separado
refactor: reemplazar clase UserManager con funciones puras
refactor: simplificar cadena de promesas con async/await

docs — Cambios solo en documentación.

docs: documentar parámetros de la función calcularPrecio
docs: agregar ejemplos de uso a README

test — Agrega o modifica tests sin cambiar código de producción.

test: cubrir casos edge en validación de email
test: agregar tests de integración para endpoint de pagos

chore — Tareas de mantenimiento que no afectan el código de producción.

chore: actualizar dependencias de seguridad
chore: configurar lint en pre-commit hook

perf — Optimizaciones de performance sin cambiar comportamiento.

perf: cachear resultados de queries frecuentes
perf: lazy load de imágenes en feed principal

ci — Cambios en configuración de CI/CD.

ci: agregar step de análisis de cobertura a pipeline
ci: configurar deployment automático a staging

Por Qué Este Formato Importa

Los commits convencionales no son solo estética. Tienen consecuencias funcionales:

  1. Generación automática de changelogs: Herramientas como conventional-changelog pueden generar notas de release automáticamente clasificando los commits por tipo.

  2. Semantic versioning automático: Con este formato, es posible determinar automáticamente si un cambio requiere incremento de major, minor o patch version.

  3. Mejor git log: La búsqueda y filtrado de commits se vuelve trivial: git log --grep="^feat:" muestra solo features nuevas.

  4. Claridad para code review: El reviewer inmediatamente sabe qué tipo de cambio esperar.

Pull Request Workflow

La rule establece un workflow de cuatro pasos para PRs:

Paso 1: Analizar el historial completo de commits

El error más común al crear un PR es describir solo el último commit. La rule es explícita: analizar el historial completo desde que el branch divergió del main. El comando correcto es:

git log main...HEAD --oneline
git diff main...HEAD

Paso 2: Usar git diff [base-branch]...HEAD

Este comando específico muestra exactamente qué cambió desde que el branch se creó, sin incluir cambios que llegaron a main después. La diferencia entre .. y ... importa:

Paso 3: Draft de PR summary completo

El summary debe cubrir:

Paso 4: Test plan con TODOs

El PR debe incluir un checklist de qué hay que verificar manualmente, automatizar, o revisar después del merge.


7. testing.md — Análisis Completo

La rule de testing es una de las más estrictas del sistema ECC. Establece TDD como workflow obligatorio, no como práctica opcional.

Cobertura Mínima: 80%

El umbral del 80% no es arbitrario. Representa el equilibrio entre:

El 80% no significa que el 20% restante no importa. Significa que el 20% que no está cubierto debe ser código que genuinamente es difícil de testear (integrations de terceros, UI específica de plataforma, casos edge extremamente raros).

Los Tres Tipos de Tests: Todos Obligatorios

La rule especifica tres tipos de tests, y la palabra “ALL required” es intencional.

Tipo 1: Unit Tests

Los unit tests verifican funciones individuales, utilities y componentes en aislamiento total. Las dependencias externas se mockean.

Cuándo escribirlos: para cada función pura, cada componente UI, cada transformer de datos.

Características de un buen unit test:

// Ejemplo de unit test correcto
describe("calcularDescuento", () => {
  it("debe aplicar 10% a usuarios premium", () => {
    const usuario = { tipo: "premium" };
    const precio = 100;
    expect(calcularDescuento(usuario, precio)).toBe(90);
  });

  it("debe retornar el precio original para usuarios standard", () => {
    const usuario = { tipo: "standard" };
    const precio = 100;
    expect(calcularDescuento(usuario, precio)).toBe(100);
  });

  it("debe lanzar error si el precio es negativo", () => {
    const usuario = { tipo: "premium" };
    expect(() => calcularDescuento(usuario, -10)).toThrow("Precio inválido");
  });
});

Tipo 2: Integration Tests

Los integration tests verifican que múltiples componentes funcionan correctamente juntos. Incluyen base de datos real (o en memoria), llamadas HTTP reales (contra servidor de test), y sistema de archivos real.

Cuándo escribirlos: para cada endpoint de API, para cada operación de base de datos, para cada flujo que cruza múltiples capas de la arquitectura.

// Ejemplo de integration test para endpoint
describe("POST /api/usuarios", () => {
  it("debe crear usuario y retornar 201", async () => {
    const response = await request(app)
      .post("/api/usuarios")
      .send({ email: "[email protected]", password: "SecurePass123!" });

    expect(response.status).toBe(201);
    expect(response.body.data.email).toBe("[email protected]");
    // Verificar que realmente se guardó en DB
    const usuario = await db.usuarios.findOne({ email: "[email protected]" });
    expect(usuario).toBeTruthy();
  });
});

Tipo 3: E2E Tests

Los end-to-end tests verifican flujos críticos del usuario completos, desde el browser (o cliente) hasta la base de datos y de vuelta. Son los más lentos pero dan la mayor confianza de que el sistema funciona end-to-end.

La rule especifica: “framework chosen per language”. No hay un framework obligatorio, pero hay que tener E2E para flujos críticos.

Cuándo escribirlos: para el flujo de signup/login, para el flujo de pago, para el flujo principal del negocio.

TDD: El Workflow Obligatorio

La rule establece TDD como MANDATORY. El ciclo Red-Green-Refactor es el único workflow aceptado:

Red — Escribir el test primero:

Antes de escribir una sola línea de código de implementación, el test ya debe existir y debe fallar. Esto es crucial: un test que nunca falló no prueba nada.

// PRIMERO — escribir este test
it("debe enviar email de bienvenida al crear usuario", async () => {
  const emailService = mockEmailService();
  await crearUsuario({ email: "[email protected]" }, emailService);
  expect(emailService.send).toHaveBeenCalledWith({
    to: "[email protected]",
    subject: "Bienvenido"
  });
});
// Ejecutar: DEBE FALLAR (la función no existe todavía)

Green — Implementación mínima:

Escribir el código más simple posible que hace pasar el test. No optimizar, no generalizar, solo hacer pasar ese test específico.

// SEGUNDO — escribir esta implementación
async function crearUsuario(data: { email: string }, emailService: EmailService) {
  // Implementación mínima
  await emailService.send({
    to: data.email,
    subject: "Bienvenido"
  });
}
// Ejecutar: DEBE PASAR

Refactor — Mejorar la calidad:

Con el test verde, es seguro refactorizar. El test es el net de seguridad que garantiza que los cambios no rompen el comportamiento.

Verify — Verificar cobertura:

Después de cada ciclo, verificar que la cobertura se mantiene en 80%+.

Por Qué TDD No Es Opcional

La resistencia más común a TDD es “tarda más tiempo”. Esta percepción es incorrecta a mediano plazo por varias razones:

  1. Los bugs encontrados en tests cuestan exponencialmente menos que bugs encontrados en producción.
  2. Los tests escritos después tienden a testear solo el happy path. Los tests escritos primero obligan a pensar en los edge cases.
  3. El código diseñado para ser testeable tiende a ser código con bajo acoplamiento, lo que facilita cambios futuros.

8. security.md — Análisis Completo

La rule de seguridad es la única que incluye un protocolo de respuesta explícito: detener todo si se encuentra un issue de seguridad. Esto refleja la severidad del dominio.

Los Checks Obligatorios Pre-Commit

La rule establece que estos checks deben ejecutarse antes de cualquier commit, no solo ante cambios de seguridad.

Check 1: No secrets hardcodeados

INCORRECTO — secret en el código:

const apiKey = "sk-prod-abc123xyz789";
const connection = createConnection("postgresql://admin:MyP@ssw0rd@prod-db:5432/mydb");

CORRECTO — usando variables de entorno:

const apiKey = process.env.API_KEY;
if (!apiKey) throw new Error("API_KEY environment variable is required");
const connection = createConnection(process.env.DATABASE_URL);

El problema con secrets hardcodeados va más allá de “alguien puede verlo en GitHub”. Los secrets en código fuente terminan en:

Check 2: Validación de todos los inputs del usuario

INCORRECTO — input sin validar:

app.get("/usuarios/:id", async (req, res) => {
  const userId = req.params.id;
  const usuario = await db.query(`SELECT * FROM usuarios WHERE id = ${userId}`);
  res.json(usuario);
});

CORRECTO — validación antes de usar:

app.get("/usuarios/:id", async (req, res) => {
  const userId = req.params.id;
  if (!isValidUUID(userId)) {
    return res.status(400).json({ error: "ID inválido" });
  }
  const usuario = await db.query("SELECT * FROM usuarios WHERE id = $1", [userId]);
  res.json(usuario);
});

Check 3: SQL injection prevention

La regla es simple: nunca interpolar strings en queries SQL. Siempre usar queries parametrizadas o un ORM que lo maneje.

INCORRECTO — interpolación directa (SQL injection):

query = f"SELECT * FROM users WHERE email = '{email}'"
cursor.execute(query)

Si email es "'; DROP TABLE users; --", esta query destruye la tabla.

CORRECTO — query parametrizada:

query = "SELECT * FROM users WHERE email = %s"
cursor.execute(query, (email,))

Check 4: XSS prevention

Cross-Site Scripting ocurre cuando HTML de usuario se renderiza sin sanitizar.

INCORRECTO:

<!-- React con dangerouslySetInnerHTML -->
<div dangerouslySetInnerHTML={{ __html: userProvidedContent }} />

CORRECTO — sanitizar antes de renderizar:

import DOMPurify from "dompurify";
const sanitized = DOMPurify.sanitize(userProvidedContent);
<div dangerouslySetInnerHTML={{ __html: sanitized }} />

O mejor aún, evitar dangerouslySetInnerHTML completamente cuando sea posible.

Check 5: CSRF protection

Los tokens CSRF previenen que sitios maliciosos realicen requests en nombre del usuario autenticado.

// Middleware CSRF en Express
import csrf from "csurf";
app.use(csrf({ cookie: true }));

// Incluir token en forms
app.get("/form", (req, res) => {
  res.render("form", { csrfToken: req.csrfToken() });
});

Check 6: Rate limiting en todos los endpoints

Sin rate limiting, los endpoints son vulnerables a brute force, DDoS y scraping.

CORRECTO:

import rateLimit from "express-rate-limit";

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutos
  max: 5, // máximo 5 intentos
  message: "Demasiados intentos de login. Intentá más tarde."
});

app.post("/auth/login", loginLimiter, loginHandler);

Check 7: Los mensajes de error no deben revelar información sensible

INCORRECTO — error que revela infraestructura:

Error: connection refused to postgresql://[email protected]:5432/mydb

CORRECTO — error genérico para el usuario:

No se pudo completar la operación. Por favor, intentá más tarde.

El error detallado debe ir al log del servidor, nunca al cliente.

El Protocolo de Respuesta ante Issues de Seguridad

La rule establece tres pasos cuando se encuentra un problema de seguridad:

  1. STOP immediately — Detener cualquier otra implementación. No continuar con la feature.
  2. Usar security-reviewer agent — Escalar al agente especializado en seguridad para análisis profundo.
  3. Fix CRITICAL issues before continuing — Los issues críticos de seguridad son bloqueantes. No hay “lo corrijo después”.

Esta firmeza en la rule refleja que los problemas de seguridad encontrados temprano son órdenes de magnitud más baratos de corregir que los encontrados en producción.


9. performance.md — Análisis Completo

La rule de performance en ECC tiene un enfoque inusual: se centra tanto en la performance del código como en la selección correcta de modelos de IA. Esto refleja que ECC es un framework para desarrollo asistido por IA, y la eficiencia de los modelos impacta directamente el costo operativo.

Estrategia de Selección de Modelos

La rule establece tres perfiles de modelos con criterios claros:

Haiku 4.5 — Para agentes frecuentes y workers

Haiku 4.5 tiene aproximadamente el 90% de la capacidad de Sonnet para tareas de codificación, pero a un costo 3x menor. Esto lo hace ideal para:

La lógica de negocio: si una operación se va a ejecutar 1000 veces por día, la diferencia de costo entre Haiku y Sonnet es significativa. Si la calidad es el 90% equivalente, Haiku es la elección correcta.

Sonnet 4.6 — Para desarrollo principal

Sonnet 4.6 es el modelo de codificación más capaz. La rule lo designa para:

Opus 4.5 — Para decisiones arquitectónicas

Opus 4.5 tiene el razonamiento más profundo pero también el mayor costo. Se reserva para:

graph TD
    A[Tarea recibida] --> B{¿Tipo de tarea?}
    B -->|Worker frecuente, tarea simple| C[Haiku 4.5]
    B -->|Desarrollo principal, coding| D[Sonnet 4.6]
    B -->|Decisión arquitectónica crítica| E[Opus 4.5]
    C --> F[3x más económico que Sonnet]
    D --> G[Balance costo/calidad óptimo]
    E --> H[Máximo razonamiento, mayor costo]

Context Window Management

La rule establece una guía importante sobre el manejo de la ventana de contexto: evitar el último 20% para tareas complejas.

El motivo es que cuando un modelo está cerca del límite de su contexto, la calidad del output degrada. El modelo empieza a “perder” información del inicio del contexto para acomodar lo nuevo. Las tareas que más sufren de esto son:

La estrategia correcta: si se detecta que el contexto está llenándose, iniciar una nueva conversación con el contexto esencial resumido, en lugar de continuar degradando la calidad del trabajo.

Extended Thinking

Para decisiones que requieren razonamiento profundo (usualmente en conjunto con Opus 4.5), la rule menciona el uso de extended thinking. Esta capacidad permite al modelo “pensar” antes de responder, explorando múltiples caminos de razonamiento.

Es apropiado para:


10. development-workflow.md — Análisis Completo

Esta rule establece el proceso completo para implementar una nueva feature, desde cero hasta código listo para review.

Fase 0: Research & Reuse (Obligatorio)

La rule marca esta fase como mandatory y la coloca en el paso 0, antes de cualquier planeamiento o codificación. El principio es: no inventar lo que ya existe.

Búsqueda en GitHub primero:

Antes de escribir una línea de código, buscar si ya existe una implementación open source de calidad. GitHub tiene miles de millones de líneas de código; las probabilidades de que alguien ya resolvió el mismo problema son muy altas.

La búsqueda de GitHub es especialmente valiosa para:

Documentación de librerías con Context7:

Si la tarea involucra una librería conocida, consultar su documentación actualizada con la herramienta Context7 antes de implementar. La razón: las APIs cambian, los patrones recomendados evolucionan. Implementar basándose en documentación desactualizada o en el conocimiento de training del modelo genera código que puede ser incorrecto o subóptimo.

Búsqueda en registros de paquetes:

Para cualquier funcionalidad que parece genérica, verificar que no existe ya una librería de calidad:

El principio es: antes de implementar, responder la pregunta “¿ya existe esto?”. El costo de buscar 5 minutos es mucho menor que el costo de mantener código custom cuando existe una librería mantenida por la comunidad.

Fase 1: Plan First — Usar el Agente Planner

Antes de escribir código, crear un plan. La rule especifica usar el agente planner para esta fase.

El planner produce:

Sin un plan, el desarrollo tiende a “extenderse” — empezar por algo, descubrir que falta otro componente, implementarlo, descubrir otro requisito, etc. Este proceso es caótico y produce código menos coherente.

Fase 2: TDD Approach — Usar el Agente tdd-guide

Con el plan en mano, el agente tdd-guide guía la implementación siguiendo el ciclo Red-Green-Refactor ya descripto. Este agente asegura que los tests se escriben antes de la implementación, no después.

Fase 3: Code Review — Usar code-reviewer Inmediatamente

La rule especifica un timing crítico: usar el agente code-reviewer inmediatamente después de escribir código. No al final del día, no antes de hacer el commit, sino durante el proceso de escritura.

El code-reviewer verifica:

El feedback temprano es más valioso que el tardío porque hay menos código escrito (menos que cambiar) y menos contexto que reaprender.

Fase 4: Commit & Push

Con código revisado y tests en verde, el commit sigue el formato de conventional commits de git-workflow.md.


11. patterns.md — Análisis Completo

Esta rule captura patrones de alto nivel que aplican a cualquier proyecto.

Skeleton Projects

El concepto de “skeleton project” es central en el workflow de ECC: cuando se empieza un proyecto nuevo, buscar un proyecto esqueleto de alta calidad como punto de partida en lugar de construir desde cero.

El proceso recomendado:

Paso 1 — Buscar skeleton projects battle-tested:

Los mejores skeleton projects son los que tienen:

Paso 2 — Usar agentes paralelos para evaluar opciones:

En lugar de evaluar cada opción secuencialmente, lanzar múltiples agentes en paralelo donde cada uno evalúa un skeleton diferente según los mismos criterios. Esto reduce el tiempo de investigación.

Paso 3 — Clonar el mejor match como foundation:

El skeleton ganador se clona y se adapta al proyecto específico. Esto es más eficiente que inicializar desde cero porque:

Repository Pattern

La rule establece el Repository Pattern como el patrón estándar para acceso a datos.

Concepto: Encapsular todo acceso a datos (base de datos, API externa, filesystem) detrás de una interfaz consistente. El código de negocio no sabe si los datos vienen de PostgreSQL, Redis o una API REST.

Implementación mínima:

// Interfaz del repositorio
interface UserRepository {
  findById(id: string): Promise<User | null>;
  findByEmail(email: string): Promise<User | null>;
  save(user: User): Promise<User>;
  delete(id: string): Promise<void>;
}

// Implementación concreta
class PostgresUserRepository implements UserRepository {
  async findById(id: string): Promise<User | null> {
    const row = await db.query("SELECT * FROM users WHERE id = $1", [id]);
    return row ? mapRowToUser(row) : null;
  }
  // ... demás métodos
}

// Test con mock
class MockUserRepository implements UserRepository {
  private users: User[] = [];
  async findById(id: string): Promise<User | null> {
    return this.users.find(u => u.id === id) ?? null;
  }
  // ... demás métodos
}

// El servicio de negocio no sabe qué implementación usa
class UserService {
  constructor(private repo: UserRepository) {}

  async getUser(id: string): Promise<User> {
    const user = await this.repo.findById(id);
    if (!user) throw new UserNotFoundError(id);
    return user;
  }
}

Beneficios concretos:

  1. Los tests de negocio no necesitan base de datos real
  2. Se puede cambiar de PostgreSQL a MongoDB cambiando solo la implementación del repositorio
  3. La lógica de mapeo (row → domain object) está encapsulada

API Response Format

La rule establece un formato de envelope consistente para todas las respuestas de API:

interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: {
    code: string;
    message: string;
  };
  metadata?: {
    page?: number;
    total?: number;
    timestamp: string;
  };
}

Respuesta exitosa:

{
  "success": true,
  "data": { "id": "123", "email": "[email protected]" },
  "metadata": { "timestamp": "2024-12-17T10:30:00Z" }
}

Respuesta de error:

{
  "success": false,
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "No existe un usuario con el ID especificado"
  },
  "metadata": { "timestamp": "2024-12-17T10:30:01Z" }
}

La consistencia en el formato de respuesta simplifica el código del cliente: siempre verificar success, luego acceder a data o error según corresponda.


12. agents.md — Análisis Completo

Esta rule define cómo y cuándo delegar trabajo a agentes especializados, y cómo orquestarlos eficientemente.

El Catálogo de Agentes Disponibles

ECC incluye un conjunto de agentes especializados, cada uno con un dominio claro:

AgenteEspecialidadCuándo invocar
plannerDescomposición de features en tareas atómicasAl inicio de cualquier feature no trivial
architectDecisiones de arquitectura y diseño de sistemasAnte decisiones con impacto a largo plazo
tdd-guideGuía el ciclo TDD Red-Green-RefactorAl implementar cualquier feature
code-reviewerRevisión de código escritoInmediatamente después de escribir código
security-reviewerAuditoría de seguridadAl encontrar posibles issues de seguridad
build-error-resolverResolución de errores de compilación y buildCuando el build falla
e2e-runnerEjecución e interpretación de tests E2EAl ejecutar y analizar tests
refactor-cleanerRefactoring de código con deuda técnicaAl identificar código que necesita limpieza
doc-updaterActualización de documentaciónDespués de cambios de API o arquitectura

Uso Inmediato: Sin Necesidad de Prompt del Usuario

La rule especifica cuatro situaciones donde los agentes se invocan automáticamente, sin que el usuario lo pida:

1. Feature request compleja → planner agent

Si el usuario pide implementar algo que claramente tiene múltiples componentes o consideraciones de diseño, el planner se invoca antes de empezar a codificar.

2. Código recién escrito → code-reviewer agent

Después de escribir código nuevo, el code-reviewer hace una primera pasada automática. No esperar a que el usuario pida review.

3. Bug fix o nueva feature → tdd-guide agent

Para garantizar que TDD se aplica consistentemente, el tdd-guide se activa automáticamente al empezar a trabajar en un cambio de código.

4. Decisión arquitectónica → architect agent

Cuando hay que elegir entre múltiples enfoques con implicaciones de diseño, el architect analiza los trade-offs.

Ejecución Paralela: El Principio Fundamental

La rule establece que las operaciones independientes siempre deben ejecutarse en paralelo. Esta es una de las optimizaciones más importantes en sistemas multi-agente.

sequenceDiagram
    participant O as Orchestrator
    participant A1 as Agente 1 (análisis)
    participant A2 as Agente 2 (tests)
    participant A3 as Agente 3 (docs)

    O->>A1: Analizar código
    O->>A2: Ejecutar tests
    O->>A3: Verificar docs
    Note over A1,A3: Ejecución paralela
    A1-->>O: Resultado análisis
    A2-->>O: Resultado tests
    A3-->>O: Resultado docs
    O->>O: Integrar resultados

En lugar de esperar a que el análisis termine para ejecutar tests, ambos corren en paralelo. El tiempo total es el del agente más lento, no la suma de todos.

Multi-Perspective Analysis

Para problemas complejos, la rule establece el patrón de “split role sub-agents”: lanzar múltiples agentes con roles explícitamente diferentes para analizar el mismo problema.

Los tres roles más útiles:

Factual Reviewer — Verifica que los hechos sean correctos. ¿Este algoritmo realmente funciona como se describe? ¿Esta configuración es válida?

Senior Engineer — Evalúa desde la perspectiva de mantenibilidad y diseño. ¿Este código va a ser mantenible en 6 meses? ¿Hay una forma más simple de hacer esto?

Security Expert — Evalúa desde la perspectiva de seguridad. ¿Hay algún vector de ataque? ¿Se están manejando correctamente los datos sensibles?

La síntesis de las tres perspectivas produce un análisis más robusto que cualquier perspectiva individual.


13. hooks.md — La Rule sobre Hooks

La rule de hooks define cuándo y cómo usar el sistema de hooks de Claude Code para automatizar verificaciones.

Cuándo Crear Hooks

Los hooks de Claude Code son scripts que se ejecutan automáticamente en momentos clave del workflow. Son diferentes a los git hooks (aunque pueden invocarlos): son hooks del ciclo de vida del agente.

Casos de uso apropiados para hooks:

Pre-tool execution hooks: Verificaciones antes de que Claude ejecute una herramienta. Ejemplo: antes de escribir en un archivo, verificar que el archivo existe y no está en una ubicación restringida.

Post-tool execution hooks: Verificaciones después de que Claude ejecuta una herramienta. Ejemplo: después de escribir código, ejecutar el linter automáticamente.

Notification hooks: Notificar al usuario cuando ocurre algo importante. Ejemplo: cuando se completa un proceso largo.

Cuándo NO Crear Hooks

La rule también establece cuándo los hooks no son la solución correcta:

Estructura de un Hook

// Estructura básica de un hook en Claude Code
{
  name: "lint-after-write",
  event: "PostToolUse",
  matcher: { tool: "Write", file_extension: [".ts", ".tsx"] },
  action: {
    type: "command",
    command: "bun run lint --fix ${file}"
  }
}

Principios de Hooks Efectivos

  1. Rápidos: Los hooks que tardan más de unos segundos interrumpen el flujo de trabajo
  2. Seguros ante fallos: Un hook que falla no debe bloquear el trabajo del agente
  3. Informativos: Si el hook detecta un problema, el mensaje debe ser claro y accionable
  4. Idempotentes: Ejecutar el hook múltiples veces debe tener el mismo efecto que ejecutarlo una vez

14. TypeScript Rules — Análisis

Las rules de TypeScript en ECC extienden las de common/ con convenciones específicas del ecosistema JavaScript/TypeScript.

Type Safety Estricta

La rule principal de TypeScript es never use any. El tipo any es esencialmente desactivar el sistema de tipos, que es la principal ventaja de TypeScript sobre JavaScript.

INCORRECTO:

function processData(data: any) {
  return data.value; // Sin type safety
}

CORRECTO:

interface DataPayload {
  value: string;
  timestamp: Date;
}

function processData(data: DataPayload): string {
  return data.value;
}

Cuando el tipo genuinamente no se conoce (por ejemplo, al parsear JSON externo), usar unknown en lugar de any:

function parseResponse(raw: unknown): ApiResponse {
  if (!isApiResponse(raw)) {
    throw new Error("Respuesta inválida del servidor");
  }
  return raw;
}

function isApiResponse(value: unknown): value is ApiResponse {
  return (
    typeof value === "object" &&
    value !== null &&
    "success" in value
  );
}

Async/Await Sobre Promises Raw

La rule establece usar async/await en lugar de .then().catch() chains para código más legible.

INCORRECTO:

function fetchUser(id: string): Promise<User> {
  return fetch(`/api/users/${id}`)
    .then(res => res.json())
    .then(data => validateUser(data))
    .catch(err => { throw new ApiError(err); });
}

CORRECTO:

async function fetchUser(id: string): Promise<User> {
  const res = await fetch(`/api/users/${id}`);
  if (!res.ok) throw new ApiError(res.status);
  const data = await res.json();
  return validateUser(data);
}

Strict TypeScript Configuration

La rule requiere configuración estricta en tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true
  }
}

Estas configuraciones fuerzan patrones correctos:

Módulos ES vs CommonJS

La rule establece usar módulos ES (import/export) en lugar de CommonJS (require/module.exports) en proyectos nuevos.

CORRECTO:

import { UserService } from "./user.service";
export { createUser } from "./create-user";

Barrel Files con Cuidado

Los barrel files (index.ts que re-exporta todo) son convenientes pero pueden causar problemas de circular dependencies y bundle size. La rule es: usarlos para APIs públicas de módulos, no para todo.


15. Python Rules

Las rules de Python cubren los estándares del ecosistema Python moderno.

PEP 8 Como Base

PEP 8 es el estándar de estilo de Python. Las rules de ECC lo adoptan con algunas adiciones:

Type Hints Obligatorios

La rule establece que todos los parámetros y retornos de funciones deben tener type hints.

INCORRECTO:

def calcular_precio(producto, cantidad, descuento):
    return producto.precio * cantidad * (1 - descuento)

CORRECTO:

from decimal import Decimal

def calcular_precio(
    producto: Producto,
    cantidad: int,
    descuento: Decimal
) -> Decimal:
    return producto.precio * cantidad * (1 - descuento)

Dataclasses y Pydantic

Para modelos de datos, la rule establece preferir dataclasses o Pydantic sobre diccionarios o clases planas:

from dataclasses import dataclass
from datetime import datetime

@dataclass(frozen=True)  # frozen=True para inmutabilidad
class Usuario:
    id: str
    email: str
    created_at: datetime

El parámetro frozen=True alinea con la rule de inmutabilidad de common/coding-style.md.

Async Patterns

Para código asíncrono, la rule establece usar asyncio con async/await:

INCORRECTO:

import requests

def fetch_data(url: str) -> dict:
    return requests.get(url).json()  # Bloqueante

CORRECTO:

import httpx
import asyncio

async def fetch_data(url: str) -> dict:
    async with httpx.AsyncClient() as client:
        response = await client.get(url)
        response.raise_for_status()
        return response.json()

Manejo de Errores con Excepciones Específicas

INCORRECTO:

try:
    result = procesar(data)
except Exception:
    pass  # Silenciar todos los errores

CORRECTO:

try:
    result = procesar(data)
except ValueError as e:
    logger.error("Datos inválidos: %s", e)
    raise InvalidDataError(str(e)) from e
except DatabaseError as e:
    logger.error("Error de base de datos: %s", e)
    raise ServiceUnavailableError() from e

Herramientas del Ecosistema

La rule establece las herramientas estándar para proyectos Python modernos:


16. Go Rules

Las rules de Go enfatizan la filosofía idiomática del lenguaje.

Manejo de Errores: El Estilo Go

Go no tiene excepciones. El patrón estándar es retornar el error como segundo valor:

INCORRECTO:

func getUser(id string) User {
    // ¿Qué pasa si hay un error?
    user, _ := db.Query(id)
    return user
}

CORRECTO:

func getUser(id string) (User, error) {
    user, err := db.Query(id)
    if err != nil {
        return User{}, fmt.Errorf("getUser(%s): %w", id, err)
    }
    return user, nil
}

La rule establece el patrón %w para wrapping de errores, que permite usar errors.Is y errors.As para inspección.

Interfaces Pequeñas

La regla de oro en Go: las interfaces deben ser pequeñas, idealmente de un solo método. Go favorece la composición de interfaces pequeñas sobre jerarquías de herencia complejas.

// INCORRECTO — interfaz demasiado grande
type UserManager interface {
    Create(user User) error
    Update(user User) error
    Delete(id string) error
    FindByID(id string) (User, error)
    FindByEmail(email string) (User, error)
    List(filter Filter) ([]User, error)
}

// CORRECTO — interfaces pequeñas y composables
type UserCreator interface {
    Create(user User) error
}

type UserFinder interface {
    FindByID(id string) (User, error)
}

type UserRepository interface {
    UserCreator
    UserFinder
    // solo agregar más si es necesario
}

No Usar panic en Código de Producción

panic en Go es equivalente a una excepción no manejada que mata el proceso. La rule establece: nunca usar panic en código de producción. Solo está permitido en:

Goroutines: Siempre Comunicar por Canales

La regla Go de concurrencia: “Don’t communicate by sharing memory; share memory by communicating.”

INCORRECTO:

var counter int
var mu sync.Mutex

func increment() {
    mu.Lock()
    counter++
    mu.Unlock()
}

CORRECTO para muchos casos:

func counter() chan<- struct{} {
    ch := make(chan struct{})
    go func() {
        count := 0
        for range ch {
            count++
        }
    }()
    return ch
}

17. Swift Rules

Las rules de Swift están diseñadas para el desarrollo moderno en iOS/macOS con Swift 6.

Swift Concurrency: Actors y async/await

Swift 6 introduce verificación estática de concurrencia. La rule establece usar el modelo de concurrencia nativo:

// Correcto: usar actor para estado compartido
actor UserCache {
    private var cache: [String: User] = [:]

    func user(for id: String) -> User? {
        cache[id]
    }

    func store(_ user: User) {
        cache[user.id] = user
    }
}

// Correcto: async/await para operaciones asíncronas
func fetchUser(id: String) async throws -> User {
    let url = URL(string: "/api/users/\(id)")!
    let (data, _) = try await URLSession.shared.data(from: url)
    return try JSONDecoder().decode(User.self, from: data)
}

Protocols Sobre Herencia

Swift favorece protocolos sobre herencia de clases. La rule establece diseñar con Protocol-Oriented Programming:

protocol Displayable {
    var displayName: String { get }
}

protocol Identifiable {
    var id: String { get }
}

// Composición de protocolos
typealias Entity = Displayable & Identifiable

struct User: Entity {
    let id: String
    let displayName: String
}

Value Types Sobre Reference Types

Structs y enums son value types en Swift (copiados en asignación). La rule prefiere value types para modelos de datos:

// Correcto: struct para modelos de datos
struct User {
    let id: String
    var name: String
    var email: String
}

// Clase solo cuando se necesita referencia o herencia
class UserSession: ObservableObject {
    @Published var currentUser: User?
}

Manejo de Errores con Result

enum NetworkError: Error {
    case invalidURL
    case noData
    case decodingFailed(Error)
}

func fetchUser(id: String) async -> Result<User, NetworkError> {
    guard let url = URL(string: "/api/users/\(id)") else {
        return .failure(.invalidURL)
    }
    do {
        let (data, _) = try await URLSession.shared.data(from: url)
        let user = try JSONDecoder().decode(User.self, from: data)
        return .success(user)
    } catch is DecodingError {
        return .failure(.decodingFailed(error))
    }
}

18. PHP Rules

Las rules de PHP están orientadas a proyectos modernos, principalmente con Laravel.

PSR-12 Como Estándar de Estilo

PHP tiene el estándar PSR-12 para estilo de código. La rule lo adopta completamente:

Laravel: Service Layer Pattern

La rule establece el patrón de capas para proyectos Laravel:

// Controller: solo coordinación, sin lógica de negocio
class UserController extends Controller
{
    public function __construct(
        private readonly UserService $userService
    ) {}

    public function store(CreateUserRequest $request): JsonResponse
    {
        $user = $this->userService->create($request->validated());
        return response()->json(['data' => $user], 201);
    }
}

// Service: lógica de negocio
class UserService
{
    public function create(array $data): User
    {
        return DB::transaction(function () use ($data) {
            $user = User::create($data);
            event(new UserCreated($user));
            return $user;
        });
    }
}

Seguridad Específica de PHP

PHP tiene vectores de ataque históricos específicos. La rule establece:

CSRF Protection: Siempre usar el middleware CSRF de Laravel en formularios.

Mass Assignment Protection: Siempre definir $fillable o $guarded en los modelos Eloquent.

INCORRECTO:

class User extends Model
{
    // Sin fillable/guarded — vulnerable a mass assignment
}

CORRECTO:

class User extends Model
{
    protected $fillable = ['name', 'email', 'password'];
    // 'is_admin' y otros campos sensibles NO están en fillable
}

File Upload Validation: Nunca confiar en el tipo MIME reportado por el cliente.

// INCORRECTO
if ($request->file('avatar')->getMimeType() === 'image/jpeg') {
    // ...
}

// CORRECTO — validar con Intervention Image o verificación real
$request->validate([
    'avatar' => ['required', 'image', 'max:2048', 'mimes:jpg,jpeg,png']
]);

Type Declarations

PHP moderno (8.x) soporta type declarations completos. La rule los hace obligatorios:

// INCORRECTO
function calcularTotal($items, $descuento) {
    return array_sum($items) * (1 - $descuento);
}

// CORRECTO
function calcularTotal(array $items, float $descuento): float
{
    return array_sum($items) * (1 - $descuento);
}

19. Rules vs CLAUDE.md

Una pregunta frecuente en ECC es: ¿qué va en una rule file y qué va en CLAUDE.md?

El Rol de CLAUDE.md

CLAUDE.md es el archivo de configuración del proyecto para Claude Code. Es el punto de entrada que Claude lee al iniciar una sesión en un proyecto específico. Contiene:

CLAUDE.md es principalmente descriptivo e informativo. Le dice a Claude qué es el proyecto y cómo trabajar con él.

El Rol de las Rules

Las rules son prescriptivas y normativas. Le dicen a Claude cómo debe comportarse, qué estándares debe seguir, qué está prohibido hacer.

La Diferencia Clave

graph LR
    A[CLAUDE.md] -->|"Qué es este proyecto"| B[Contexto]
    A -->|"Cómo trabajar con él"| C[Comandos]
    D[Rules] -->|"Cómo debe comportarse Claude"| E[Directivas]
    D -->|"Qué está permitido/prohibido"| F[Restricciones]

CLAUDE.md dice: “Este proyecto usa Next.js 14 con App Router. Los componentes viven en src/components/. Para correr el servidor: bun dev.”

Una rule dice: “Al crear componentes React, siempre colocarlos en el directorio correspondiente a su dominio, no en un directorio genérico components/. Los componentes deben ser menores de 150 líneas.”

Overlap y Prioridad

Cuando hay información en ambos (CLAUDE.md y rules), las rules tienen precedencia para cuestiones de comportamiento y estilo. CLAUDE.md tiene más peso para cuestiones de contexto específico del proyecto.

Si CLAUDE.md dice “usamos Tailwind para estilos” y una rule dice “preferir CSS Modules”, el desarrollador debe resolver el conflicto actualizando la rule o CLAUDE.md para ser coherente. Las inconsistencias confunden al agente.

Cuándo Usar Cada Uno

Usar CLAUDE.md para:

Usar Rules para:


20. Crear Rules Propias

Crear rules propias es una parte fundamental de personalizar ECC para un proyecto o equipo específico.

Template Completo para una Rule

# Nombre de la Rule

## Contexto
[Explicar por qué esta rule existe. Qué problema resuelve. Cuál es el rationale.]

## Reglas

### [Nombre del principio 1] (CRITICAL/IMPORTANT/RECOMMENDED)
[Descripción del principio]

INCORRECTO:
```[lenguaje]
[ejemplo de lo que NO hacer]

CORRECTO:

[ejemplo de lo que SÍ hacer]

Rationale: [Por qué esta es la forma correcta] Consecuencias de no seguirlo: [Qué pasa si se ignora]

[Nombre del principio 2]

[…]

Excepciones

[Cuándo esta rule no aplica, si hay alguna excepción válida]

Referencias

[Links a documentación, artículos, o standards relevantes]


### Qué Hace una Rule Efectiva

**1. Prescriptiva, no descriptiva**: Una rule efectiva dice "SIEMPRE hacer X" o "NUNCA hacer Y", no "considerar hacer X".

Inefectivo: "Es buena práctica validar los inputs"
Efectivo: "SIEMPRE validar inputs en los límites del sistema antes de procesarlos"

**2. Ejemplos concretos de código**: Las abstracciones son difíciles de aplicar consistentemente. Los ejemplos de código CORRECTO vs INCORRECTO eliminan la ambigüedad.

**3. Rationale explícito**: Explicar el "por qué" es tan importante como el "qué". Cuando el agente entiende el principio subyacente, puede aplicarlo correctamente a situaciones no anticipadas.

**4. Granularidad apropiada**: Una rule con 50 principios diferentes es difícil de seguir. Mejor 5 rules con 10 principios cada una, organizadas por tema.

**5. Tono imperativo**: Las rules deben usar imperativo: "Usar", "Nunca", "Siempre", "Evitar". No subjuntivo: "Sería mejor", "Se recomienda", "Podría considerarse".

**6. Sin ambigüedad**: "Funciones pequeñas" es ambiguo. "Funciones de máximo 50 líneas" es una rule accionable.

### Granularidad Correcta

La granularidad de una rule debe ser suficientemente específica para ser accionable pero no tan detallada que cree fricción innecesaria.

**Demasiado vaga:**
```markdown
# Código Limpio
Escribir código limpio y mantenible.

Demasiado detallada:

# Nombramiento de Variables
- Variables booleanas deben empezar con is, has, can, should, will o did
- Variables de arrays deben estar en plural
- Variables de funciones deben ser verbos en infinitivo
- [... 30 reglas más]

Apropiada:

# Naming Conventions
SIEMPRE usar nombres descriptivos que comuniquen intención.
- Variables booleanas: prefijo `is`, `has`, `can`
- Funciones: verbos que describen la acción (`fetchUser`, `validateEmail`)
- No usar abreviaturas excepto las estándar de la industria (url, id, api)

21. Rules en Cursor

Cursor, el editor de código con IA, tiene su propio sistema de rules con algunas diferencias respecto a Claude Code.

Frontmatter Adicional

Las rules en Cursor soportan frontmatter YAML con campos específicos:

---
description: "Estándares de código para proyectos TypeScript"
globs: ["**/*.ts", "**/*.tsx"]
alwaysApply: true
---

# TypeScript Standards
[contenido de la rule]

description: Descripción breve de qué hace la rule. Cursor la usa para determinar cuándo aplicar la rule.

globs: Patrones de archivos a los que aplica la rule. Si se especifica, la rule solo se activa cuando se trabaja con archivos que coinciden con el patrón.

alwaysApply: Cuando es true, la rule se aplica en todas las conversaciones. Cuando es false o se omite, Cursor puede optar por no cargarla dependiendo del contexto.

Diferencias Clave con Claude Code

AspectoClaude CodeCursor
ActivaciónSiempre activas (si están instaladas)Condicional por globs y alwaysApply
FrontmatterNo requeridoSoportado y recomendado
Ubicación~/.claude/rules/ o .claude/rules/.cursor/rules/
FormatoMarkdown puroMarkdown con frontmatter YAML
ScopeGlobal o proyectoGlobal, proyecto, o por tipo de archivo

Rules Condicionales por Archivo

La capacidad de Cursor de aplicar rules solo a ciertos tipos de archivos es poderosa:

---
description: "Reglas específicas para componentes React"
globs: ["src/components/**/*.tsx"]
alwaysApply: false
---

# React Component Rules
[reglas específicas para componentes React]

Esta rule solo se activa cuando Cursor está trabajando con archivos .tsx dentro de src/components/. Al trabajar con archivos de servidor o configuración, esta rule no consume espacio en el contexto.

Compatibilidad entre Claude Code y Cursor

Las rules de ECC son compatibles con ambos sistemas. La diferencia principal es que en Cursor se puede agregar el frontmatter opcional. Si se quiere usar la misma rule en ambos sistemas, escribirla para Claude Code (sin frontmatter) funciona en ambos, aunque en Cursor no se beneficia de las capacidades de globs.


22. Conflictos Entre Rules

Los conflictos entre rules son posibles, especialmente cuando se tienen rules de múltiples fuentes (common/ + lenguaje + proyecto).

Tipos de Conflictos

Conflicto directo: Dos rules dicen cosas opuestas sobre el mismo tema.

Ejemplo: common/coding-style.md dice “funciones máximo 50 líneas” y una rule de proyecto dice “funciones máximo 100 líneas”.

Conflicto de omisión: Una rule establece algo pero otra rule relevante lo omite completamente, creando ambigüedad.

Conflicto de prioridad: Ambas rules son correctas pero se aplican a la misma situación y requieren diferentes acciones.

Cómo Claude Resuelve Conflictos

En la jerarquía de precedencia de ECC:

  1. Rules de proyecto (.claude/rules/) tienen precedencia sobre
  2. Rules de usuario (~/.claude/rules/) que tienen precedencia sobre
  3. Comportamiento por defecto del modelo

Dentro del mismo nivel de jerarquía, si hay conflicto:

Cómo Evitar Conflictos

1. Estructura modular clara: Cada rule cubre un dominio específico sin overlap con otras.

2. Explicitamente referenciar overrides: Si una rule de proyecto necesita sobreescribir algo de common/, decirlo explícitamente.

# Python Specific Rules

## File Length Override
Este proyecto usa notebooks Jupyter donde los archivos pueden ser más largos.
OVERRIDE de common/coding-style.md: archivos de notebook (.ipynb) pueden
superar 800 líneas cuando el contenido educativo lo requiere.

3. Revisión periódica: Al agregar nuevas rules, revisar las existentes para detectar posibles conflictos.


23. Rules y Performance de Tokens

Las rules consumen tokens del contexto de Claude. Este es un trade-off real que hay que gestionar.

Cuántos Tokens Consumen las Rules

Las rules de common/ típicamente suman 2000-4000 tokens en total (todos los archivos combinados). Las rules de un lenguaje específico suman 500-1500 tokens adicionales. En una ventana de contexto de 200K tokens, esto representa menos del 2-3% del contexto total — un costo pequeño por los beneficios.

Sin embargo, si se agregan muchas rules customizadas, el consumo puede escalar.

Cuándo Considerar Deshabilitar Rules

Hay situaciones donde puede ser apropiado deshabilitar algunas rules temporalmente:

Para sesiones de exploración: Cuando se está explorando una idea nueva o haciendo un spike técnico, las rules estrictas pueden ser innecesariamente restrictivas.

Para análisis de código legacy: Al analizar código existente que viola las rules, las rules pueden generar ruido al sugerir cambios constantes cuando el objetivo es entender, no cambiar.

Para tareas muy específicas y acotadas: Si la sesión tiene un objetivo muy específico (por ejemplo, solo generar documentación), las rules de testing y git workflow son irrelevantes.

Estrategia de Selección

La mejor práctica es tener las rules comunes siempre activas y ser selectivo con las rules específicas. No instalar rules de un lenguaje que no se usa en el proyecto.


24. Evolucionar Rules con rules-distill

El skill /rules-distill es uno de los más poderosos del sistema ECC. Analiza el codebase existente para extraer patrones implícitos y generar rules formales.

Cómo Funciona rules-distill

El proceso es:

  1. El agente analiza el historial de commits del proyecto
  2. Identifica patrones recurrentes: cómo se nombran las cosas, cómo se estructuran los archivos, cómo se manejan los errores
  3. Contrasta estos patrones con las rules existentes
  4. Propone nuevas rules para convenciones que están en el código pero no formalizadas
  5. Propone actualizaciones a rules existentes donde el código diverge

Cuándo Usar rules-distill

Al onboarding de un proyecto existente: Si un proyecto ya tiene mucho código con convenciones implícitas, rules-distill puede generar un conjunto inicial de rules rápidamente.

Periódicamente en proyectos activos: Las convenciones evolucionan. Las rules deben evolucionar con ellas. Correr rules-distill cada pocos meses asegura que las rules reflejen la realidad actual del codebase.

Cuando las rules parecen desactualizadas: Si Claude frecuentemente sugiere cosas que el equipo rechaza, probablemente las rules no reflejan las convenciones actuales.

El Output de rules-distill

El skill genera un diff de rules: rules nuevas propuestas y modificaciones a las existentes. El desarrollador revisa y aprueba/rechaza cada propuesta. Esto es importante: rules-distill propone, el humano decide.


25. Testing de Rules

Verificar que Claude está siguiendo las rules correctamente es un paso importante del proceso de onboarding y mantenimiento.

Estrategia de Verificación

Método 1: Tests de comportamiento dirigidos

Hacer preguntas o peticiones específicas que deben activar una rule, y verificar que la respuesta es conforme:

Método 2: Revisión del razonamiento

Claude puede explicar por qué tomó ciertas decisiones. Pedir explícitamente que justifique una decisión de código revela si está siguiendo las rules o tomando decisiones ad-hoc.

Usuario: "¿Por qué creaste una nueva copia del objeto en lugar de modificarlo?"
Claude: "Siguiendo la rule de inmutabilidad en coding-style.md, siempre retorno
nuevos objetos en lugar de modificar los existentes, para evitar efectos colaterales."

Método 3: Casos edge deliberados

Crear situaciones que pongan a prueba el conflicto entre comodidad y seguimiento de rules:

Si las rules están bien cargadas y son claras, Claude debe resistir estas peticiones o al menos señalar la violación.

Debugging Cuando las Rules No Se Siguen

Si Claude no está siguiendo las rules esperadas, las causas posibles son:

  1. Las rules no están cargadas: Verificar que los archivos están en los directorios correctos y tienen el formato correcto.

  2. La rule es ambigua: Si la rule usa lenguaje vago (“considerar usar X”), Claude puede ignorarla. Hacerla más imperativa.

  3. Hay un conflicto no resuelto: Si otra fuente (CLAUDE.md, system prompt) contradice la rule, puede ganar la otra fuente. Resolver el conflicto.

  4. La rule está fuera del contexto ventana: En conversaciones muy largas, las rules pueden “perderse” hacia el inicio del contexto. Iniciar una nueva sesión.


26. Jerarquía de Prioridad

Cuando múltiples fuentes de instrucciones existen, ¿cuál gana?

Orden Completo de Prioridad

graph TD
    A[System Prompt del modelo] -->|Mayor prioridad| B[Instrucciones de seguridad]
    B --> C[Rules de proyecto .claude/rules/]
    C --> D[Rules de usuario ~/.claude/rules/]
    D --> E[CLAUDE.md del proyecto]
    E --> F[Contexto de la conversación]
    F --> G[Instrucción del usuario en el turno actual]
    G -->|Menor prioridad| H[Comportamiento por defecto del modelo]

Instrucciones de seguridad (máxima prioridad): Los principios de seguridad y ética del modelo nunca pueden ser overrideados por ninguna rule o instrucción.

Rules de proyecto: Tienen la mayor prioridad sobre las fuentes configurables. El razonamiento: las convenciones del equipo son la ley en ese proyecto.

Rules de usuario: Las preferencias personales del desarrollador son relevantes pero ceden ante las del proyecto.

CLAUDE.md del proyecto: El contexto del proyecto es relevante para las decisiones del agente pero no es prescriptivo como las rules.

Contexto de la conversación: El historial de la conversación informa pero no manda.

Instrucción del turno actual: La petición específica del usuario. Importante pero no puede violar reglas de orden superior.

Comportamiento por defecto: Lo que Claude haría sin ninguna instrucción. La base.

Implicaciones Prácticas

Esta jerarquía tiene implicaciones importantes:

  1. Si el usuario pide explícitamente “ignora las rules de testing”, Claude puede (y debe) señalar que las rules de testing tienen mayor prioridad que las instrucciones del turno actual para cuestiones de estándares de código.

  2. Si CLAUDE.md describe cómo funciona el sistema pero una rule prescribe un comportamiento diferente, la rule gana.

  3. Si una rule de usuario y una rule de proyecto se contradicen, la de proyecto gana para todo trabajo en ese proyecto.


27. Rules para Equipos

Cuando múltiples desarrolladores trabajan en el mismo proyecto, las rules de ECC se convierten en el mecanismo de estandarización del equipo.

Project-Level vs User-Level para Equipos

Project-Level (.claude/rules/) — Para todo el equipo:

Las rules de proyecto deben estar versionadas en el repositorio. Todos los miembros del equipo las tienen automáticamente al clonar el repo. Son el equivalente a las convenciones de coding del equipo, pero ejecutadas por el agente.

User-Level (~/.claude/rules/) — Para preferencias individuales:

Las preferencias personales que no afectan al equipo van en el nivel usuario. Por ejemplo, si un desarrollador prefiere un cierto estilo de logging para debugging personal, eso es nivel usuario.

Gobernanza de Rules de Equipo

Las rules de proyecto son tan importantes como el código. Deben seguir el mismo proceso de revisión:

  1. Proponer cambios a rules via PR (igual que código)
  2. El equipo revisa y aprueba/rechaza
  3. Los cambios se documentan (qué cambió y por qué)
  4. Se comunica al equipo que hay rules nuevas

Onboarding con Rules

Las rules son una parte importante del onboarding de nuevos desarrolladores. En lugar de transmitir convenciones verbalmente (que se pierden), las rules las formalizan. Un nuevo desarrollador que instala Claude Code en el repo automáticamente tiene acceso a todas las convenciones del equipo.

Rules y Code Review

Las rules también ayudan en code review. Si hay una rule que dice “funciones máximo 50 líneas” y el código tiene una función de 80 líneas, el reviewer puede referirse a la rule en lugar de a su preferencia personal. Esto despersonaliza el feedback y lo ancla en estándares acordados por el equipo.


28. Mejores Prácticas

Basado en la experiencia de uso del sistema ECC, estas son las 15 mejores prácticas para rules efectivas:

1. Siempre incluir el rationale. Una rule sin “por qué” es difícil de internalizar y puede parecer arbitraria. El agente (y los humanos) siguen mejor las reglas que entienden.

2. Un archivo por dominio. Agrupar todas las reglas de testing en testing.md, todas las de seguridad en security.md, etc. Evitar archivos catch-all.

3. Usar niveles de criticidad. Marcar algunas reglas como (CRITICAL) para indicar que son no negociables. Las reglas sin marcar pueden tener más flexibilidad.

4. Ejemplos de código en cada regla importante. Las reglas abstractas se interpretan de muchas formas. Los ejemplos de código son unívocos.

5. Mantener las rules versionadas. Las rules son parte del contrato del proyecto. Deben estar en git, con historia de cambios y reviews.

6. Revisar rules periódicamente. El código evoluciona, las rules deben evolucionar con él. Una revisión trimestral es razonable.

7. Empezar con common/ y agregar gradualmente. Instalar todo de golpe es abrumador. Empezar con las rules fundamentales y agregar cuando hay necesidad real.

8. Documentar excepciones explícitamente. Si hay situaciones donde una rule no aplica, documentarlas. Evita que el agente aplique reglas donde no corresponde.

9. Usar tono imperativo. “SIEMPRE usar queries parametrizadas” es mejor que “Se recomienda usar queries parametrizadas”.

10. No duplicar lo que está en CLAUDE.md. Si el contexto del proyecto ya está en CLAUDE.md, no repetirlo en las rules. Cada fuente tiene su rol.

11. Las rules no son sustituto de tests. Las rules guían el agente, pero las reglas de negocio deben tener tests. No confundir los niveles.

12. Testear las rules antes de comitearlas. Antes de agregar una rule al equipo, verificar que Claude la sigue correctamente con algunos casos de prueba.

13. Rules específicas son mejor que rules generales. “Usar Zod para validación de schemas” es más accionable que “Validar datos de entrada”.

14. Considerar el costo de tokens. Más rules = más tokens. Ser selectivo y no agregar rules por las dudas.

15. Las rules más importantes primero. En cada archivo, las reglas más críticas deben estar al principio. Si el contexto se llena, las últimas son las que se pierden.


29. Anti-Patrones

Estos son los 10 errores más comunes al crear o usar rules:

Anti-patrón 1: Rules vagas sin ejemplos de código

“Escribir código limpio” no es una rule accionable. Sin criterios concretos, cada agente interpreta “limpio” de forma diferente.

Anti-patrón 2: Rules que se contradicen sin resolución explícita

Tener “funciones máximo 50 líneas” en common/ y “funciones máximo 100 líneas” en una rule de proyecto sin indicar cuál tiene precedencia crea confusión.

Anti-patrón 3: Rules que dicen “considerar” o “podría ser útil”

El lenguaje condicional hace que las rules sean opcionales. Si algo debe hacerse, usar “SIEMPRE”. Si algo está prohibido, usar “NUNCA”.

Anti-patrón 4: Rules sin rationale

Sin saber por qué existe una rule, es imposible aplicarla correctamente a situaciones no anticipadas.

Anti-patrón 5: Demasiadas rules de bajo nivel

Tener una rule para cada micro-decisión de estilo (dónde va la llave de apertura, cuántos espacios entre parámetros) es mejor manejarlo con un formatter automático (Prettier, Black, gofmt).

Anti-patrón 6: Rules no versionadas

Tener rules locales que no están en el repositorio significa que el resto del equipo no las tiene.

Anti-patrón 7: Rules que no se testean

Agregar una rule y asumir que Claude la sigue sin verificar. El testing de rules es obligatorio.

Anti-patrón 8: Mezclar contexto (CLAUDE.md) con prescripciones (rules)

Poner instrucciones de comportamiento en CLAUDE.md y descripción del proyecto en las rules genera confusión sobre el propósito de cada artefacto.

Anti-patrón 9: Rules que nunca se actualizan

Las rules escritas hace 12 meses para un stack diferente se vuelven ruido. Revisión periódica es obligatoria.

Anti-patrón 10: Instalar rules de lenguajes que no se usan

Instalar las rules de Python, Go, Swift y Ruby en un proyecto TypeScript solo consume tokens sin beneficio.


30. Ejercicios Prácticos

Ejercicio 1: Instalar Rules y Verificar Comportamiento

Objetivo: Experimentar la diferencia entre tener y no tener rules instaladas.

Pasos:

  1. En un proyecto vacío, pedir a Claude que cree una función que modifique un array
  2. Anotar el resultado
  3. Instalar common/coding-style.md con la rule de inmutabilidad
  4. Hacer la misma petición
  5. Comparar los resultados

Resultado esperado: Sin la rule, Claude puede crear código que muta el array. Con la rule, debe crear una función que retorna un nuevo array.

Ejercicio 2: Crear una Rule para un Proyecto Existente

Objetivo: Formalizar convenciones implícitas en una rule.

Pasos:

  1. Analizar el código existente de un proyecto
  2. Identificar tres convenciones que se siguen consistentemente pero no están documentadas
  3. Escribir una rule con el template de la sección 20
  4. Verificar que Claude las sigue en la siguiente sesión

Ejercicio 3: Detectar un Conflicto de Rules

Objetivo: Entender cómo los conflictos se manifiestan.

Pasos:

  1. Crear dos rules que se contradicen sobre el mismo tema
  2. Pedir a Claude algo que activa ambas rules
  3. Observar qué hace Claude
  4. Resolver el conflicto y repetir

Ejercicio 4: Medir el Consumo de Tokens

Objetivo: Entender el trade-off de tener muchas rules.

Pasos:

  1. Iniciar una sesión con todas las rules de common/ instaladas
  2. Usar la tool de análisis de tokens para medir el consumo
  3. Instalar adicionalmente las rules de TypeScript
  4. Medir el nuevo consumo
  5. Evaluar si el beneficio justifica el costo

Ejercicio 5: rules-distill en un Proyecto con Historial

Objetivo: Extraer rules de un codebase existente.

Pasos:

  1. Elegir un proyecto con al menos 3 meses de historial de git
  2. Invocar /rules-distill
  3. Revisar las rules propuestas
  4. Aceptar las que reflejan convenciones reales del proyecto
  5. Rechazar las que no aplican
  6. Verificar en la siguiente sesión que las reglas aceptadas se siguen

31. Referencia por Lenguaje

Esta tabla resume todos los lenguajes soportados por ECC con sus rules correspondientes:

LenguajeDirectorioRules DisponiblesStack Típico
Universalrules/common/coding-style, git-workflow, testing, security, performance, development-workflow, patterns, agents, hooksTodos los proyectos
TypeScript/JSrules/typescript/types, async, modules, react, nodeNext.js, React, Bun, Deno
Pythonrules/python/pep8, types, async, testing, securityDjango, FastAPI, Data Science
Gorules/golang/idioms, errors, interfaces, concurrencyBackend services, CLIs
Swiftrules/swift/concurrency, protocols, memory, swiftuiiOS, macOS, watchOS
PHPrules/php/psr12, laravel, security, typesLaravel, WordPress
Rustrules/rust/ownership, errors, async, traitsSystems, WASM, Embedded
Javarules/java/solid, spring, patterns, testingSpring Boot, Enterprise
Rubyrules/ruby/ruby-style, rails, testingRails, Sinatra

Combinaciones Recomendadas por Tipo de Proyecto

Aplicación web moderna (TypeScript + Node.js):

common/ + typescript/

API REST con Python:

common/ + python/

Microservicio en Go:

common/ + golang/

App iOS:

common/ + swift/

Aplicación Laravel:

common/ + php/

Sistema de alta performance:

common/ + rust/

32. Checklist y Resumen

Checklist de Rules para Nuevo Proyecto

Checklist de Rule Individual

Resumen de Conceptos Clave

Las rules son el mecanismo de estandarización permanente en ECC. A diferencia de los skills (que se invocan) y los agentes (que se delegan), las rules están siempre activas y forman el “background radiation” del comportamiento de Claude en un proyecto.

Las rules de common/ son el núcleo obligatorio. Cubren inmutabilidad, estilo de código, git workflow, testing obligatorio, seguridad, performance, workflow de desarrollo, patrones de diseño y orquestación de agentes.

Las rules de lenguaje extienden common/ con convenciones específicas del ecosistema: TypeScript tiene type safety estricto, Python tiene PEP 8 y type hints, Go tiene manejo idiomático de errores, Swift tiene concurrencia con actors.

La jerarquía de prioridad es clara: rules de proyecto > rules de usuario > CLAUDE.md > contexto de conversación. Esta jerarquía garantiza que las convenciones del equipo siempre prevalecen.

Las mejores prácticas para rules efectivas son: ser prescriptivo (no descriptivo), incluir ejemplos de código, documentar el rationale, mantener las rules versionadas, y revisarlas periódicamente.

Los anti-patrones más comunes son: rules vagas, rules que se contradicen, rules sin rationale, y rules no actualizadas.

El testing de rules es obligatorio: verificar con casos específicos que Claude sigue las convenciones esperadas, debuggear cuando no las sigue, y usar rules-distill para mantener las rules alineadas con la evolución del codebase.

Las rules de ECC son, en última instancia, la forma en que los equipos capturan y transmiten su conocimiento colectivo sobre cómo debe ser el código. Son la diferencia entre tener un agente genérico y tener un agente que realmente entiende cómo trabaja tu equipo.