Después de reducir a 9 agentes y poner CLAUDE.md a dieta, los intervalos entre Compacting conversation... se alargaron notablemente. Las mismas tareas, pero aguantaba mucho más que antes. Me sentí bien.

Entonces estaba viendo la consola después de pedir una nueva funcionalidad. Los tests corrieron. 30 casos, todos pasaron. Pero Claude estaba mencionando los tests exitosos otra vez. Algo se sentía raro.

Le pregunté a Claude. “¿Por qué mencionas otra vez los tests que ya pasaron?” Claude me explicó el concepto de herramientas. Cuando Claude ejecuta un comando de terminal o lee un archivo, todo eso son “llamadas a herramientas”. Y cada vez que una herramienta se ejecuta, su resultado completo se apila en el contexto de la conversación. Resultado de npm test — 30 líneas. Log de Hugo build — 180 líneas. Todo. Los tests pasaron todos sin nada que ver, pero leyó los 30. Para arreglar errores de build, solo necesitaba las últimas 5 líneas, pero cargó las 180.

El balde con fugas no era uno solo.

Y fue dicho: seguirás los hooks

Mientras buscaba, descubrí los hooks de Claude Code. PreToolUse — un script que se interpone justo antes de que Claude ejecute una herramienta. Puede transformar la salida antes de que se ejecute un comando Bash, y puede bloquear una llamada Read antes de que suceda.

Ahora podía establecer mandamientos para proteger my precious.

Primer mandamiento: No leerás lo que tuvo éxito

30 tests pasaron todos, no hay necesidad de leerlos de nuevo. Hice un hook que filtra solo los casos fallidos y descarta el resto. (Le pedí a Claude que lo hiciera.)

1
filtered_cmd="$cmd 2>&1 | grep -A 10 -E '(FAIL|ERROR|✕|FAILED)' | head -150"

Donde antes Claude leía los 30 resultados de tests, ahora solo ve los fallos. Si todo pasa, la cantidad de lectura es cero. 100% de lecturas innecesarias — eliminadas.

Segundo mandamiento: No subirás lo que no sea error

Log de Hugo build 180 líneas, Docker build 80 líneas — no hace falta subir todo para encontrar errores. Misma lógica: hice un hook que filtra solo ERROR, WARN, failed.

1
2
# Hugo
filtered_cmd="$cmd 2>&1 | grep -E '(ERROR|WARN|error|failed|Fatal)' | head -30"

180 líneas se convirtieron en 5. Corté el 97%. Docker pasó de 80 líneas a unas 10.

Tercer mandamiento: No leerás lo que es inútil

Hay una carpeta de archivo que ya no se usa. No hay razón para que Claude la abra mientras explora archivos. Hice un hook que intercepta llamadas a la herramienta Read y deniega cualquier ruta que contenga _archive.

1
2
3
if [[ "$file_path" == *"/_archive/"* ]]; then
  # deny
fi

Simple, pero efectivo.

Pero hay un detalle

La mejora era tangible. Compacting conversation... apareció menos frecuentemente. El contexto se mantenía mucho más ligero incluso después de ejecutar builds. Tres hooks bloqueando a Claude de leer información innecesaria.

Pero era “tangible”. No sabía exactamente cuánto había ahorrado. Hoy se sentía mejor que ayer, pero ¡no podía presumir de cuánto había cortado! ¿En qué se diferenciaba esto del EP.1, donde creí que “dividir agentes ayudaría” sin ninguna evidencia?

Si no lo mides, no lo has mejorado. Era hora de medir de verdad.

Otros posts de esta serie


Referencias