Squelch — menos ruido, menos tokens

La mayor parte de lo que lee un agente de programación es salida de comandos, y la mayor parte de la salida de comandos es ruido: cientos de líneas PASSED alrededor de la única prueba que falló, una barra de progreso por cada paquete que descarga una instalación, una línea Compiling por cada archivo de una compilación, los contadores de objetos de git. El modelo lo lee todo, en cada turno, y todo cuenta para la ventana de contexto y para la factura.

Squelch quita ese ruido antes de que el modelo lo lea. Conserva aquello sobre lo que actúa el agente —errores, fallos, advertencias, resúmenes— y deja fuera el resto. Funciona con todos los agentes (Claude Code, Codex, Kimi Code, Grok, omp) sin instalar nada en la máquina: el proxy de tu Mac recorta los resultados de comandos que lleva cada petición, igual que la Protección de datos personales sustituye los datos personales. Squelch se ajusta por máquina (un espacio de trabajo, en el editor de ajustes) y está desactivado por defecto; la referencia de los campos está en Ajustes → Squelch.

Crédito: Squelch se inspira en rtk (Rust Token Killer, github.com/rtk-ai/rtk, Apache-2.0), que hace lo mismo reescribiendo los comandos de shell del agente en tu máquina. La idea, sus estrategias de filtrado por familia y su informe de «tokens ahorrados» (rtk gain) proceden de rtk; los filtros de Bromure son propios y se ejecutan en el proxy, así que llegan a todos los agentes sin hooks.

Activarlo

Dos formas, ambas inmediatas: la siguiente petición de los agentes ya va recortada y nada se reinicia.

  • En la cabecera de una sesión, haz clic en el icono de Squelch (tres líneas que se estrechan, después del recuento de tokens) y activa el interruptor en el popover.
  • En los ajustes de la máquina, selecciona Squelch bajo Modelos, marca Quitar el ruido de la salida de los comandos antes de que el modelo la lea y haz clic en Guardar.

Para que sea el valor por defecto de las máquinas nuevas, actívalo en Bromure → Ajustes… (la plantilla Valores predeterminados).

Qué quita

Squelch mira el comando del que procede una salida —el último comando de una cadena que hace el trabajo, atravesando los prefijos sudo, timeout, env y VAR=value— y aplica el filtro de su familia:

FamiliaComandos (ejemplos)Se deja fueraSiempre se conserva
Pruebaspytest, jest, vitest, mocha, go test, cargo test, swift test, xcodebuild test, npm test, dotnet test, rspec, phpunitUna línea por prueba superada, los puntos de progreso, el progreso de compilaciónLos fallos, las trazas, los diffs de aserciones, el resumen
Instalacionesnpm/pnpm/yarn/bun install, pip/uv/poetry, apt, brew, cargo fetch, go mod download, docker pullLas líneas de descarga, desempaquetado y «already satisfied», las barras de progreso, los avisos de obsolescenciaLos errores, los conflictos, la línea de resultado
Compilacionescargo build, swift build, xcodebuild, make, cmake, gradle, mvn, tsc, docker buildLas líneas de compilación por archivo, los bloques de pasos de xcodebuild, la cháchara de directorios de make, la misma advertencia impresa otra vezCada error y cada advertencia, con su fragmento de código
gitgit push, pull, fetch, clone, status, commitLos contadores de objetos, las pistas (use "git add"…), las largas listas create modeLas ramas, las refs, los conflictos, los archivos
Registrosdocker logs, kubectl logs, journalctlLas series de líneas que solo difieren en sus números (marcas de tiempo, ids): se conserva la primera, con un recuentoTodo lo que difiere
Búsquedagrep, rg, ag, git grepEl final de las líneas muy largas (archivos minificados)Cada coincidencia y su ubicación
Todo lo demás—Secuencias de escape del terminal, líneas de progreso redibujadas, barras de progreso, la misma línea seis o más veces seguidasEl resto

Una línea que nombra un error, un fallo, una advertencia, un pánico o un tiempo de espera agotado nunca se deja fuera, coincida con el patrón que coincida.

Una desinstalación (pip uninstall, uv pip uninstall, npm remove, brew uninstall, apt remove…) no es una instalación: lo que imprime es la lista de lo que se fue, así que solo recibe la limpieza genérica de «todo lo demás».

Algunas salidas nunca se tocan, porque el agente las lee como la cosa en sí, normalmente para copiar de ellas en una edición: cat, head, tail, sed, less, jq, awk, diff, git diff, git show, git log, git blame (sean cuales sean las opciones que vayan antes: git --no-pager diff, git -C repo log), gh pr diff, gh api, hg diff, curl, python -c y similares. Tampoco una tubería que el propio agente haya montado (pytest -v | tail -40): ya eligió qué ver. Los resultados de las herramientas de archivos propias de los agentes (herramientas Read, Edit, Grep) tampoco se tocan nunca; solo los comandos de shell.

Una salida de menos de unos 300 bytes, o que encogería menos de un 10 %, pasa sin cambios.

Qué ve el modelo

Una salida recortada termina con una línea que dice qué se dejó fuera y cómo obtenerlo todo:

FAILED tests/test_api.py::test_retry_budget - assert 2 == 3
========================= 1 failed, 120 passed in 4.12s =========================
[Bromure Squelch left out 120 noise lines (passing tests 120). Run the command again prefixed with BROMURE_FULL_OUTPUT=1 to see all of it.]

Cuando el agente necesita la salida completa, vuelve a ejecutar el comando con BROMURE_FULL_OUTPUT=1 delante, algo inofensivo para el shell, y Squelch deja pasar entera la salida de ese comando.

Solo el modelo del agente ve el texto recortado. La transcripción del propio agente, la vista de chat y tu terminal conservan la salida completa. Squelch cambia la petición cadena a cadena y deja todos los demás bytes tal como los envió el agente, y la misma salida siempre se recorta igual, así que una conversación reenviada turno tras turno conserva su caché de prompt. (Activar o desactivar Squelch a mitad de una conversación cambia una vez los turnos anteriores, de modo que la siguiente petición falla la caché.)

Ver lo que ahorró

La cabecera de cada sesión muestra lo que Squelch ahorró en esa conversación (12K ahorrados). Haz clic para abrir el popover:

  • Esta conversación: tokens ahorrados, la parte de la salida de comandos que se dejó fuera, cuántas salidas de comandos se enviaron al modelo y cuántas se recortaron.
  • Todo «…» (toda la máquina): lo mismo, para todas las conversaciones de la máquina.
  • De dónde vino: los comandos que más ahorraron (pytest, npm install, …).
  • Últimas dos semanas: tokens ahorrados por día.

El panel de ajustes Squelch de la máquina muestra la lista completa de comandos y el mismo gráfico.

Los tokens se estiman como caracteres ÷ 4, como hace rtk: no hay ningún tokenizador en el circuito, así que la parte ahorrada es fiable y el recuento absoluto, aproximado. Cada salida de comando cuenta una vez, la primera vez que una petición la lleva, aunque el agente reenvíe toda la conversación en cada turno; el ahorro real en una sesión larga es mayor que el número mostrado.

Los ahorros se guardan por máquina en ~/Library/Application Support/BromureAC/squelch/ledger.json (por conversación, comando, familia y día, durante los últimos 90 días). En un cliente pesado (un Mac, iPhone o iPad conectado a otro Mac), los números vienen del servidor que ejecuta la máquina, y el interruptor del popover activa o desactiva Squelch allí.

Límites

  • Solo máquinas. Squelch vive en el proxy por el que pasa todo el tráfico de IA de cada máquina. Una máquina nativa (un Mac que ejecuta Bromure Sidecar) envía el tráfico de sus agentes directamente al proveedor, así que Squelch no se aplica allí.
  • Patrones, no criterio. Los filtros reconocen los formatos de salida de las herramientas habituales. Un ejecutor de pruebas poco común o un script de compilación propio solo recibe la limpieza genérica (secuencias de escape, barras de progreso, líneas repetidas).
  • Un comando que la petición no nombra. Cuando un turno de Codex continúa uno anterior en el servidor, un resultado puede llegar sin la llamada que lo produjo. Squelch lo empareja con la llamada que el modelo anunció en su respuesta; un resultado cuya llamada nunca vio —tras un reinicio de Bromure, por ejemplo— se deja como está, ya que su texto por sí solo no permite distinguir una ejecución de pruebas de un cat de un registro de pruebas.