Wenn die Finger Esc drücken: Vim-Keybindings für den Hermes-CLI-Composer (plus der Branch-Name in deiner Status Bar)

Du hast einen langen Prompt in Hermes getippt, und kurz vor dem Enter fällt dir mitten drin ein falsch geschriebenes Wort auf. Deine Finger drücken Esc und dann dd – und der Composer tut absolut nichts. Unter den standardmäßigen Emacs-Bindings ist Esc kein „Insert-Mode verlassen“, sondern eine Cancel-/Clear-Taste, und dd wurden einfach zwei Textzeichen. Wenn du ein Jahrzehnt in vim verbracht hast, ist diese halbe Sekunde Reibung schwer jemandem zu erklären, der das nicht kennt.
Jetzt gibt es eine offizielle Antwort. Der klassische CLI-Composer kann vi/vim-Keybindings nutzen – und das Setup ist kleiner, als du erwarten würdest: ein Config-Key, und kein neues Slash-Kommando.
Einschalten: display.vim_mode
Füge eine Zeile unter dem Abschnitt display in ~/.hermes/config.yaml hinzu:
display:
# Nur CLI: vi/vim-Keybindings im Input-Composer (Esc → NORMAL, i → INSERT)
# Der aktuelle Modus NORMAL / INSERT / REPLACE erscheint rechts in der Status Bar.
# Nur per Config, wird beim Start gelesen.
vim_mode: true
Dann öffne deine Config mit hermes config edit (oder deinem eigenen Editor), speichere und starte Hermes neu.
Eine Falle, die man gleich am Anfang aus dem Weg räumt: Es gibt kein /vim-Slash-Kommando. Eine frühe Iteration dieses Features brachte eines mit on|off|status-Unterkommandos, aber es wurde vor dem Merge entfernt – aus einem vernünftigen Grund. Seine Nachbarn (/statusbar, /battery, /timestamps) schalten Anzeige-Elemente für den Moment um, während Keybindings eine Bearbeitungsgewohnheit sind, und sie an die Konfiguration zu binden ist konsistenter, als sie Sitzung für Sitzung umzuschalten. Siehst du also irgendwo anders /vim on geschrieben, ist das der verworfene Zwischenstand – es zu tippen bewirkt gar nichts.
Wie es sich tatsächlich anfühlt
Das Verhalten entspricht dem, was deine Finger erwarten:
- Esc geht in den NORMAL-Mode, wo Tasten Kommandos statt Text sind;
i(odera,ound Verwandte) bringt dich zurück in den INSERT-Mode für normales Tippen;- die Status Bar zeigt den aktuellen Modus an ihrem rechten Rand – eines von
NORMAL,INSERToderREPLACE. Das ist wirklich nützlich, keine Dekoration: In einem mehrzeiligen Prompt ist das Vergessen, in welchem Modus man ist, die klassische kleine Plage, und ein dauerhaftes Label beseitigt die meisten „warum passiert nichts, wenn ich tippe“-Momente.
Dieses Label ist live, es folgt deinen Esc- und i-Anschlägen, statt beim Start festgelegt zu sein. Unter der Haube baut die Status Bar es dynamisch aus dem aktuellen Editing-Mode (_vim_mode_label in cli_status_bar_mixin.py).
Und wenn du vim noch nie genutzt hast? Der Standard ist off, wodurch prompt_toolkits Standard-Emacs-Bindings erhalten bleiben – ändere nichts, bemerke nichts. Genau diese Opt-in-Haltung ist der Grund, warum das als Config-Schalter gelandet ist.
Ein Begleiter, den man kennen sollte: dein aktueller Git-Branch in der Status Bar
Wo wir bei der Status Bar sind: Es gibt ein zweites Feld nach dem Motto „standardmäßig aus, bewusst einschalten“ – den aktuellen Git-Branch.
Auf einer Maschine mit mehreren Repositories und Worktrees ist „auf welchem Branch ist diese Sitzung eigentlich“ eine häufige und folgenreiche Frage – besonders, nachdem ein Agent für dich Dateien bearbeitet hat und du sicher sein willst, welcher Branch es getroffen hat. Hefte es an die Status Bar, und es ist immer einen Blick entfernt:
display:
status_bar:
# Nicht leer = nur diese Felder werden gezeigt (eingebaute Reihenfolge bleibt;
# die Config steuert Sichtbarkeit, nicht die Reihenfolge). Leere Liste = Standardfelder.
fields: ["model", "git_branch", "duration"]
Verfügbare Felder sind unter anderem model, context_pct, cache_hit, latency, tps, compressions, bg_tasks, bg_subagents, goal, git_branch (gerendert als ⎇ branch), duration, focus, yolo, battery, title und total_tokens. Zwei Regeln sind wichtig:
- Eine nicht leere Liste ist eine Whitelist: Nur die von dir benannten Felder werden gezeigt; eine leere Liste stellt das Standardset wieder her. Die Reihenfolge bleibt eingebaut – die Konfiguration entscheidet nur über Sichtbarkeit.
- Schmale Terminals werfen Felder automatisch raus. Wird das Fenster eng, werden breite Felder wie
context_detail,prompt_elapsedundidle_sinceentfernt statt gequetscht. Das ist beabsichtigtes Verhalten, keine kaputte Config.
Wenn du nur die Status Bar selbst umschalten willst, macht /statusbar das; die Feldliste ist Konfiguration.
Vorbehalte
- Nach dem Bearbeiten neu starten.
vim_modewird beim Start gelesen, ein Hot-Config-Edit schaltet den Modus also nicht in einer bereits laufenden Sitzung um. - Es betrifft nur den Composer. Die Änderung gilt für das Eingabefeld, in das du Prompts tippst, nicht für jede andere Interaktionsfläche und schon gar nicht dafür, wie der Agent arbeitet.
- CLI-spezifisch. Keybindings gehören zum klassischen CLI-Composer; die Desktop-App und andere TUI-Flächen haben ihre eigene Eingabelogik. Erwarte nicht, dass ein Schalter alle umstellt.
- Es ist nicht ganz vim. Das ist prompt_toolkits vi-Editing-Mode: Bewegung, Löschen, Eintritt in den Insert-Mode – alltägliches Editieren, keine Neovim-Sitzung mit Plugins und ausgefeilten Registern.
- Das Feature hat Vorläufer. Der ursprüngliche Wunsch ist Issue #4254, und etwa zur selben Zeit brachte die GitHub Copilot CLI den vim-Mode zur allgemeinen Verfügbarkeit (ihre v1.0.84-2-Notes nennen sowohl ein
/vim-Kommando als auch eineeditorMode-Einstellung). Beide Projekte sind sich im Kern einig: Gewohnheiten beim Terminal-Editieren verdienen Respekt.
Wenn du dein CLI-Setup justierst, lohnen sich drei verwandte Beiträge hier: der Leitfaden zur Ctrl+P Command Palette, der Deep Dive zu Status-Bar-Metriken und das Entfernen der Max-Turns-Obergrenze für lange Sitzungen. Eine Maschine von Grund auf einzurichten beginnt beim Installationsleitfaden.
Die Kurzfassung
Ein Satz: Willst du vim-Tasten? Schreib display.vim_mode: true und starte neu – und such nicht nach einem /vim-Kommando, denn es gibt keines.
Drei Dinge zum Mitnehmen:
- Standardmäßig aus, es ändert sich also nichts, solange du nicht danach fragst; einmal an, zeigt die Status Bar dauerhaft NORMAL / INSERT / REPLACE.
- Ziehe in Betracht,
git_branchzudisplay.status_bar.fieldshinzuzufügen – in einer Multi-Branch-Umgebung verhindert es eine ganze Klasse dummer Fehler. - Diese Änderung ist nach dem Tag v0.21.2 gemerged, liegt aktuell also auf
mainstatt in einem getaggten Release;hermes updateholtmain, oder warte auf die nächste Version.
Für alle, die vim-Muskelgedächtnis ins Terminal tragen, ist es eine kleine Änderung, die du mehrmals am Tag nutzen wirst.