Claude Code trae un slash command llamado /simplify que revisa tu código automáticamente. Le pasé un diff gordo — unas 500 líneas en 8 ficheros — y el resultado fue… interesante. Encontró cosas que yo no habría pillado. Pero también me hizo perder tiempo con cosas que no importaban.
Así que lo desmembramos, y lo monté de vuelta pieza por pieza.
Qué hace /simplify
Es un skill que viene con Claude Code (no lo instalas). Lanza tres agentes en paralelo, cada uno mirando el mismo diff desde un ángulo distinto:
- Code Reuse — ¿Hay utilidades existentes que podrían reemplazar código nuevo?
- Code Quality — Estado redundante, copy-paste, leaky abstractions, stringly-typed code.
- Efficiency — I/O innecesario, concurrencia desaprovechada, memory leaks.
Los tres devuelven hallazgos, y luego el sistema intenta arreglarlos directamente.
Lo que encontró bien
El agente de reuse pilló un helper duplicado verbatim en dos suites de tests. Mismo nombre, mismas líneas, dos ficheros distintos. Lo moví a un módulo compartido. Limpio.
El de efficiency detectó un doble viaje a disco por iteración en un bucle de procesamiento: cargar estado, modificar, guardar, leer datos, volver a cargar, volver a guardar. Dos escrituras cuando con una bastaba. No me habría dado cuenta solo.
También señaló que un buffer de memoria no tenía cleanup en el path de error. Si algo fallaba entre la reserva y la liberación, leak. El path principal sí lo tenía. El clásico copy-paste que se come el detalle.
Hasta aquí, bien. Tres hallazgos legítimos, accionables. Pero el problema de /simplify no es lo que encuentra — es todo lo demás que reporta.
Donde se queda corto
Demasiado ruido en severidad baja. Me sugirió eliminar un campo de un struct porque era «redundante» con una propiedad computada. Son 8 bytes. Ese campo se usa en más de 10 sitios del código y en los tests. El churn de cambiarlo supera con creces el beneficio de ahorrarse un entero.
No entiende el contexto del proyecto. Me reportó como HIGH un patrón de concurrencia que efectivamente es un riesgo. Correcto en abstracto. Pero ya estaba documentado en el CLAUDE.md del proyecto, tenía un lint dedicado, estaba en la allowlist, y había un issue abierto. El agente no sabe nada de esto porque trabaja solo con el diff, en el vacío.
No distingue «incorrecto» de «mejorable». El doble viaje a disco era ineficiente pero correcto. El patrón de concurrencia era una bomba latente. Ambos salían como MEDIUM. La priorización es plana.
Sugiere enums para datos externos. Me dijo que unos campos de un DTO deberían ser enums en vez de strings. Pero esos campos vienen de una API externa. Solo se leen y se muestran. Convertirlos a enum requiere custom decoding y no aporta nada — si la API añade un valor nuevo, tu enum explota en vez de degradar graceful.
Son errores que cualquier dev con contexto del proyecto habría filtrado en dos segundos. Pero /simplify no tiene contexto. Tiene un diff y buenas intenciones.
Las tres mejoras que apliqué
Después de ver los resultados, identifiqué tres problemas estructurales de /simplify y los arreglé en un skill custom que llamé /improve.
1. Inyectar contexto del proyecto
Cada agente recibe el CLAUDE.md, los issues abiertos del tracker, y los resultados de los linters antes de emitir hallazgos. Si algo ya está gestionado, lo menciona pero no lo reporta como nuevo.
Esto solo elimina la categoría más irritante de false positives: los que tú ya sabes y tienes controlados.
2. Filtro de coste/beneficio
Antes de reportar, cada agente estima cuántos ficheros toca el fix. Si el ratio esfuerzo/mejora es negativo — como renombrar un campo en 10+ sitios para ganar legibilidad marginal — lo descarta.
Esto parece obvio, pero /simplify no lo hace. Trata un cambio de una línea y un refactor de 15 ficheros con la misma prioridad.
3. Separar «fix automático» de «issue para backlog»
Los hallazgos se clasifican en dos tipos:
– auto-fix: mecánico, ≤3 ficheros, sin riesgo. Se aplica directamente.
– issue: requiere diseño, toca >3 ficheros, o cambia una interfaz. Se crea como issue en el tracker.
Así el review no intenta arreglar cosas que necesitan pensar.
Lo que descarté (y por qué)
Un segundo LLM como revisor. La idea suena sexy — cross-model validation, más ojos, otro training. En la práctica, el cuello de botella no es la cantidad de ojos sino la calidad del contexto. Un segundo modelo sin acceso al CLAUDE.md ni al tracker devuelve exactamente lo mismo: opiniones genéricas de «buenas prácticas» que ya están en cualquier libro.
Categorización en 4 severidades. Empecé con CRITICAL/HIGH/MEDIUM/LOW, pero con filtro de coste/beneficio activo, casi todo lo que pasa el filtro es MEDIUM o HIGH. Las otras dos categorías se vacían. Más taxonomía no implica mejor priorización.
El consejo Jedi
Y aquí viene la idea que cambió el resultado.
Hace unas semanas escribí sobre invocar a expertos como mentores — pedirle a un LLM que adopte la perspectiva de Tufte, Munger, o quien sea. Funcionó brutalmente bien para diseño.
¿Y si en vez de tres agentes genéricos (reuse, quality, efficiency) pusiera tres agentes con nombre, filosofía y reglas de decisión concretas?
La idea tiene un nombre que cualquier fan de Star Wars reconoce: el consejo Jedi. Tres maestros con perspectivas distintas evaluando el mismo caso. Pero ojo — no se trata de que el LLM haga cosplay superficial poniendo citas famosas. Se trata de que cada «sabio» aplique reglas de filtrado específicas que un reviewer genérico no aplicaría.
Los tres sabios (y por qué estos)
Kent Beck — Simplicidad. «Make it work, make it right, make it fast — in that order.» Es el tipo que te dice «esas tres líneas duplicadas están bien, no extraigas un helper todavía». Su regla clave: la regla de tres. NO reportar duplicación hasta que el mismo bloque aparezca tres veces. Dos veces es coincidencia. Tres es un patrón. Y si el fix toca más ficheros que el código que arregla, probablemente no merece la pena.
Pero Beck no es solo simplicidad. También busca bugs de corrección: casos donde la elección obvia tiene semántica distinta de la correcta. Ese async que parece inocuo pero hereda un contexto que no quieres. Ese default que funciona en tests pero explota en producción.
Martin Fowler — Diseño. Los code smells son síntomas, no enfermedades. El refactoring es una disciplina, no un hobby. Su regla clave: solo sugerir refactoring si hay un cambio concreto que se beneficiaría de él. «Refactoring sin dirección es turismo por el codebase.» Si un string viene de una API externa y solo se lee, no sugieras convertirlo a enum. Si un campo siempre está sincronizado con otro por diseño, la redundancia es intencional.
Mike Acton — Rendimiento. «The purpose of all programs is to transform data from one form to another.» Si no has medido, no tienes un problema de rendimiento — tienes una opinión. Su regla clave: I/O es lo único que importa en la mayoría de apps. CPU rara vez es el cuello de botella. Disco y red sí.
Acton no opina — mide
Aquí es donde la cosa se pone interesante. Mike Acton no se queda en el análisis estático. Hace dos cosas antes de abrir la boca:
Conteo estático de I/O: escanea el diff buscando operaciones de lectura/escritura a disco, red, o base de datos. Mapea cada operación a su contexto: ¿está en un bucle? ¿En hot path? Genera una tabla de frecuencias antes de opinar.
Profiling real: si el diff toca código de hot path y el proyecto se puede compilar, ejecuta un profiler y condensa los resultados. Si un hotspot coincide con código del diff, lo reporta con números, no con opiniones.
La tabla de I/O incluye estimaciones de orden de magnitud: lectura SSD ~0.5ms, escritura ~1ms, persistencia ~2-5ms, red ~100-500ms. No es precisión — es detección de operaciones que en agregado superan el umbral.
El riesgo (y cómo evitarlo)
Antes de que salgas montando un consejo Jedi para cada pull request, el elefante en la habitación: el LLM puede hacer cosplay superficial. Poner «como diría Kent Beck…» y soltar el mismo consejo genérico de siempre con su nombre encima.
Para evitarlo, las instrucciones no dicen «adopta la perspectiva de Kent Beck». Dicen: «aplica la regla de tres: si un fix toca más ficheros que el código que arregla, descártalo». Reglas concretas, no vibes.
Además, cada sabio debe acabar con una sección de «Descartados» — hallazgos que consideró pero descartó, con la regla que aplicó. Eso da visibilidad de que el sabio filtró activamente, no que simplemente reportó menos.
Y si dos sabios se contradicen sobre el mismo código — Beck dice «no tocar» y Fowler dice «refactorizar» — se lanza un agente moderador que evalúa el caso concreto hasta llegar a consenso. Si no hay consenso → descartar. Mejor no actuar que actuar mal.
¿Es lo mismo que tener a Kent Beck delante? Obviamente no. Pero es infinitamente mejor que tres agentes genéricos que reportan todo sin criterio.
La prueba: mismo diff, dos reviews
Pasé el mismo diff por /simplify y por /improve. Mismos cambios, mismo proyecto, misma sesión:
| /simplify | /improve | |
|---|---|---|
| Hallazgos reportados | 8 | 5 |
| False positives | 3-4 | 0 |
| Hallazgos nuevos | 0 | 1 (bug de concurrencia, HIGH) |
| Sección «Descartados» | No | Sí, con regla aplicada |
| Contexto del proyecto | No | CLAUDE.md + tracker + linters |
El hallazgo nuevo que /improve encontró y /simplify no: un bug de concurrencia donde el patrón aparentemente correcto heredaba un contexto de ejecución equivocado, provocando que la UI se congelara. Dicho en cristiano: el código parecía bien, compilaba sin warnings, pero bloqueaba el hilo principal. /simplify no lo detectó porque sus agentes genéricos no buscan bugs donde la elección «obvia» es incorrecta. Kent Beck sí, porque su mandato incluye exactamente eso.
Los false positives de /simplify — el campo «redundante» de 8 bytes, el patrón de concurrencia ya gestionado, los enums para JSON externo — no aparecen en /improve. El filtro de coste/beneficio descartó el primero. El contexto de proyecto descartó el segundo. La regla de Fowler («stringly-typed solo si duele») descartó el tercero.
Lo que más me convenció: la sección de «Descartados». Ver qué consideró cada sabio y por qué lo descartó da mucha más confianza que ver solo lo que reportó. Sabes que miró más de lo que dijo.
Cómo instalarlo
El skill se llama /improve y vive en ~/.claude/skills/improve/SKILL.md. Es un skill global de Claude Code — funciona en cualquier proyecto.
# Crear el directorio
mkdir -p ~/.claude/skills/improve
# Copiar el SKILL.md (o escríbelo tú siguiendo la estructura de skill de Claude Code)
Uso:
# Solo review (no toca código)
/improve
# Review + aplicar fixes mecánicos
/improve --fix
# Review + informe de senior dev
/improve --report
# Review de un rango de commits específico
/improve --diff HEAD~5..HEAD
En resumen
/simplify es un buen punto de partida. Tres agentes genéricos que detectan duplicaciones, ineficiencias y code smells. Pero sin contexto del proyecto reporta ruido, sin filtro de coste/beneficio sugiere cambios que no compensan, y sin criterio propio trata todos los hallazgos igual.
/improve es la evolución: tres sabios con filosofía concreta, contexto del proyecto, filtro de coste/beneficio, y separación entre fixes automáticos e issues para el backlog. Beck te dice cuándo NO extraer un helper. Fowler te dice cuándo un smell es cosmético. Acton te dice cuándo un «problema de rendimiento» es una opinión sin datos.
Menos hallazgos, cero false positives, y un bug real que el otro no vio. A veces la mejora no es más ojos — es mejores ojos.
Relacionado: Invocar a los sabios — la técnica original con Tufte y Munger. /loop vs claude-cron — otro skill de Claude Code que analicé.
Read this article in English.



