Squelch — weniger Rauschen, weniger Tokens
Das meiste, was ein Coding-Agent liest, ist Befehlsausgabe, und die meiste Befehlsausgabe ist Rauschen: Hunderte PASSED-Zeilen rund um den einen Test, der fehlschlug, ein Fortschrittsbalken für jedes Paket, das eine Installation herunterlädt, eine Compiling-Zeile für jede Datei eines Builds, die Objektzähler von git. Das Modell liest all das, in jeder Runde, und alles zählt für das Kontextfenster und die Rechnung.
Squelch entfernt dieses Rauschen, bevor das Modell es liest. Es behält, worauf der Agent reagiert — Fehler, Fehlschläge, Warnungen, Zusammenfassungen — und lässt den Rest weg. Es funktioniert für jeden Agenten (Claude Code, Codex, Kimi Code, Grok, omp), ohne dass in der Maschine etwas installiert wird: Der Proxy auf Ihrem Mac kürzt die Befehlsergebnisse, die jede Anfrage mitführt, so wie der Schutz personenbezogener Daten persönliche Daten austauscht. Squelch wird pro Maschine eingestellt (ein Arbeitsbereich, im Einstellungseditor) und ist standardmäßig aus; die Feldreferenz steht unter Einstellungen → Squelch.
Würdigung: Squelch folgt dem Vorbild von rtk (Rust Token Killer, github.com/rtk-ai/rtk, Apache-2.0), das dasselbe erreicht, indem es die Shell-Befehle des Agenten auf Ihrem Rechner umschreibt. Die Idee, die Filterstrategien pro Befehlsfamilie und der Bericht „eingesparte Tokens“ (
rtk gain) stammen von rtk; die Filter von Bromure sind eigene und laufen stattdessen im Proxy, sodass sie jeden Agenten ohne Hooks erreichen.
Einschalten
Zwei Wege, beide sofort wirksam — die nächste Anfrage der Agenten wird gekürzt, nichts startet neu:
- Klicken Sie im Kopf einer Sitzung auf das Squelch-Symbol (drei schmaler werdende Linien, hinter der Token-Anzahl) und legen Sie im Popover den Schalter um.
- Wählen Sie in den Einstellungen der Maschine Squelch unter Modelle, aktivieren Sie Rauschen aus der Befehlsausgabe entfernen, bevor das Modell sie liest und klicken Sie auf Sichern.
Damit es für neue Maschinen der Standard ist, schalten Sie es in Bromure → Einstellungen… ein (die Vorlage Standardwerte).
Was es entfernt
Squelch betrachtet den Befehl, von dem eine Ausgabe stammt — den letzten Befehl einer Kette, der die Arbeit erledigt, durch die Präfixe sudo, timeout, env und VAR=value hindurch — und wendet den Filter seiner Familie an:
| Familie | Befehle (Beispiele) | Weggelassen | Immer behalten |
|---|---|---|---|
| Tests | pytest, jest, vitest, mocha, go test, cargo test, swift test, xcodebuild test, npm test, dotnet test, rspec, phpunit | Eine Zeile pro bestandenem Test, Fortschrittspunkte, Kompilierfortschritt | Fehlschläge, Tracebacks, Assertion-Diffs, die Zusammenfassung |
| Installationen | npm/pnpm/yarn/bun install, pip/uv/poetry, apt, brew, cargo fetch, go mod download, docker pull | Download-, Entpack- und „already satisfied“-Zeilen, Fortschrittsbalken, Deprecation-Hinweise | Fehler, Konflikte, die Ergebniszeile |
| Builds | cargo build, swift build, xcodebuild, make, cmake, gradle, mvn, tsc, docker build | Kompilierzeilen pro Datei, die Schrittblöcke von xcodebuild, das Verzeichnisgeplauder von make, dieselbe Warnung erneut ausgegeben | Jeder Fehler und jede Warnung, mit ihrem Quelltextauszug |
| git | git push, pull, fetch, clone, status, commit | Objektzähler, (use "git add"…)-Hinweise, lange create mode-Listen | Branches, Refs, Konflikte, die Dateien |
| Logs | docker logs, kubectl logs, journalctl | Folgen von Zeilen, die sich nur in ihren Zahlen unterscheiden (Zeitstempel, IDs) — die erste bleibt, mit einer Anzahl | Alles, was sich unterscheidet |
| Suche | grep, rg, ag, git grep | Das Ende sehr langer Zeilen (minifizierte Dateien) | Jeder Treffer und seine Fundstelle |
| Alles andere | — | Terminal-Escapes, neu gezeichnete Fortschrittszeilen, Fortschrittsbalken, dieselbe Zeile sechsmal oder öfter hintereinander | Der Rest |
Eine Zeile, die einen Fehler, einen Fehlschlag, eine Warnung, eine Panic oder ein Timeout nennt, wird nie weggelassen, egal zu welchem Muster sie passt.
Eine Deinstallation (pip uninstall, uv pip uninstall, npm remove, brew uninstall, apt remove…) ist keine Installation: Was sie ausgibt, ist die Liste dessen, was entfernt wurde, also bekommt sie nur die allgemeine Bereinigung von „Alles andere“.
Manche Ausgaben werden nie angetastet, weil der Agent sie als die Sache selbst liest — meist, um daraus in eine Bearbeitung zu kopieren: cat, head, tail, sed, less, jq, awk, diff, git diff, git show, git log, git blame (egal welche Optionen davor stehen: git --no-pager diff, git -C repo log), gh pr diff, gh api, hg diff, curl, python -c und Ähnliches. Ebenso wenig eine Pipeline, die der Agent selbst gebaut hat (pytest -v | tail -40): Er hat bereits gewählt, was er sehen will. Auch Ergebnisse der eigenen Dateiwerkzeuge der Agenten (Read-, Edit-, Grep-Werkzeuge) werden nie angetastet — nur Shell-Befehle.
Ausgaben unter etwa 300 Bytes oder solche, die um weniger als 10 % schrumpfen würden, gehen unverändert durch.
Was das Modell sieht
Eine gekürzte Ausgabe endet mit einer Zeile, die sagt, was weggelassen wurde und wie man alles bekommt:
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.]
Braucht der Agent die vollständige Ausgabe, führt er den Befehl erneut mit vorangestelltem BROMURE_FULL_OUTPUT=1 aus — harmlos für die Shell, und Squelch lässt die Ausgabe dieses Befehls vollständig durch.
Nur das Modell des Agenten sieht den gekürzten Text. Das eigene Transkript des Agenten, die Chat-Ansicht und Ihr Terminal behalten die vollständige Ausgabe. Squelch ändert die Anfrage String für String und lässt jedes andere Byte so, wie der Agent es gesendet hat, und dieselbe Ausgabe wird immer gleich gekürzt — eine Unterhaltung, die Runde für Runde erneut gesendet wird, behält also ihren Prompt-Cache. (Squelch mitten in einer Unterhaltung ein- oder auszuschalten ändert frühere Runden einmalig, sodass die nächste Anfrage den Cache verfehlt.)
Sehen, was es eingespart hat
Der Kopf jeder Sitzung zeigt, was Squelch in dieser Unterhaltung eingespart hat (12K gespart). Klicken Sie darauf, um das Popover zu öffnen:
- Diese Unterhaltung — eingesparte Tokens, der Anteil der weggelassenen Befehlsausgabe, wie viele Befehlsausgaben an das Modell gingen und wie viele gekürzt wurden.
- Ganz „…“ (die ganze Maschine) — dasselbe für alle Unterhaltungen auf der Maschine.
- Woher es kam — die Befehle mit den größten Einsparungen (
pytest,npm install, …). - Letzte zwei Wochen — eingesparte Tokens pro Tag.
Der Einstellungsbereich Squelch der Maschine zeigt die vollständige Befehlsliste und dasselbe Diagramm.
Tokens werden als Zeichen ÷ 4 geschätzt, wie es auch rtk tut — es gibt keinen Tokenizer im Ablauf, daher ist der eingesparte Anteil verlässlich und die absolute Zahl ungefähr. Jede Befehlsausgabe zählt einmal, beim ersten Mal, wenn eine Anfrage sie mitführt, obwohl der Agent in jeder Runde die ganze Unterhaltung erneut sendet — die tatsächlichen Einsparungen in einer langen Sitzung sind größer als die angezeigte Zahl.
Die Einsparungen werden pro Maschine in ~/Library/Application Support/BromureAC/squelch/ledger.json gespeichert (nach Unterhaltung, Befehl, Familie und Tag, für die letzten 90 Tage). Auf einem Fat Client (einem Mac, iPhone oder iPad, das mit einem anderen Mac verbunden ist) kommen die Zahlen vom Server, auf dem die Maschine läuft, und der Schalter im Popover schaltet Squelch dort ein oder aus.
Grenzen
- Nur Maschinen. Squelch lebt im Proxy, durch den der gesamte KI-Verkehr jeder Maschine läuft. Eine native Maschine (ein Mac mit Bromure Sidecar) schickt den Verkehr ihrer Agenten direkt an den Anbieter, daher greift Squelch dort nicht.
- Muster, kein Urteilsvermögen. Die Filter erkennen die Ausgabeformate der gängigen Werkzeuge. Ein ungewöhnlicher Test-Runner oder ein eigenes Build-Skript bekommt nur die allgemeine Bereinigung (Escapes, Fortschrittsbalken, wiederholte Zeilen).
- Ein Befehl, den die Anfrage nicht nennt. Wenn eine Codex-Runde eine frühere auf dem Server fortsetzt, kann ein Ergebnis ohne den Aufruf ankommen, der es erzeugt hat. Squelch ordnet es dem Aufruf zu, den das Modell in seiner Antwort angekündigt hat; ein Ergebnis, dessen Aufruf es nie gesehen hat — etwa nach einem Neustart von Bromure —, bleibt, wie es ist, da sein Text allein einen Testlauf nicht von einem
cateines Testlogs unterscheiden kann.