So erkennst du, wann Claude Code, Codex oder OpenCode auf dich wartet
Claude Code sagt dir über drei Hooks, dass es wartet: PreToolUse auf AskUserQuestion, eine Notification vom Typ permission_prompt und ein Stop, dessen letzte Nachricht mit einer Frage endet. Ignoriere idle_prompt, das nach jeder Antwort kommt, auf die niemand reagiert. Hier ist die Übersicht, die Foxl Code für Remote-Terminals mit Claude Code, Codex, OpenCode und Hermes nutzt, was jede CLI nicht melden kann und wie du einen Hook schreibst, der den Agenten wenig kostet und nie versehentlich mit dem Modell spricht.

Auf dieser Seite
Die Hooks von Claude Code führen einen Befehl aus, den du festlegst, sobald ein bestimmtes Ereignis eintritt, und drei davon sagen dir, dass es auf dich wartet. Ein PreToolUse-Hook auf das Tool AskUserQuestion feuert, wenn es seinen Fragedialog öffnet. Ein Notification-Hook vom Typ permission_prompt feuert, wenn ein Berechtigungsdialog seit ein paar Sekunden offen ist. Ein Stop-Hook feuert am Ende jeder Antwort und trägt deren Text in last_assistant_message, sodass du prüfen kannst, ob sie mit einer Frage endete. Ignoriere idle_prompt: Es kommt etwa eine Minute nach jeder Antwort, auf die niemand etwas getippt hat, nicht nur nach einer Frage.
Foxl Code, das Coding-Agenten in Remote-Terminals ausführt, nutzt genau diese drei, um ein Remote-Terminal mit Claude Code als wartend auf seinen Nutzer zu markieren. Seit v0.9.3-beta.5 liest derselbe Meldebefehl auch Codex, OpenCode und Hermes über deren eigene Hooks und Plugins. Hier steht die Übersicht für jede CLI, die Fallen, die jede einzelne hat, und wie man den Hook so schreibt, dass er den Agenten so wenig wie möglich kostet und nie Text in den Kontext des Modells durchsickern lässt. Noch hat kein echtes Cloud-Terminal eine Rückfrage gemeldet; der letzte Abschnitt sagt, was noch nicht verifiziert ist.
Warum sieht man nicht, dass ein Agent in einem Terminal wartet?
Wer Agenten in Remote-Terminals laufen lässt, hat oft mehrere gleichzeitig offen und schaut auf keines davon. Am 2026-10-21 stellte ein Remote-Terminal mit Claude Code eine Ja-oder-Nein-Frage und blieb an seiner Eingabeaufforderung stehen, während die API von Foxl selbst meldete, dass keine Aufgabe auf irgendwen wartete. Die Seitenleiste von Foxl Code, ihre Liste „Braucht dich“ mit Aufgaben, die auf eine Person warten, und die Handy-App blieben alle still. Vor dieser Änderung hat in Foxl Code nichts auf diesen Moment gehört.
Den Bildschirm zu lesen, sieht nach der Lösung aus, geht aber leicht kaputt. Für einen Leser von außen unterscheiden sich die Bildschirme fürs Nachdenken, fürs Fertigsein und fürs Fragen nur um ein paar Zeichen der Zeichnung, die die CLI selbst malt, und jedes Release kann sie neu zeichnen. Als wir einmal die CLI-Versionen aktualisiert haben, die wir ausliefern, zeichneten die neuen Builds einen anderen ersten Bildschirm als den, auf den unsere Eingabeprüfung wartete, und Remote-Terminals mit Codex und OpenCode ignorierten zehn Tage lang stillschweigend jede Eingabe. Ein Hook ist die eigene Aussage der CLI darüber, was gerade passiert ist, mit dokumentiertem Payload, also hören wir darauf.
Welche Hooks von Claude Code bedeuten „Ich warte auf dich“?
Unsere Cloud-Images pinnen Claude Code 2.1.296. Wo ein Detail unten als aus dem Paket gelesen markiert ist, stammt es aus dem npm-Paket dieser Version, nicht aus einem laufenden Terminal.
| Hook | was er bedeutet | wir behandeln ihn als |
|---|---|---|
PreToolUse, Matcher AskUserQuestion | der Fragedialog öffnet sich gleich; tool_input enthält die Fragen und ihre Optionen | eine Frage, mit ihren Auswahlmöglichkeiten |
Notification, Matcher permission_prompt | ein Berechtigungsdialog ist seit etwa sechs Sekunden ohne Tastendruck offen (aus dem Paket gelesen) | eine Berechtigungsanfrage |
Stop | die Antwort ist fertig; last_assistant_message ist ihr Text | eine Frage, wenn der Text mit ? endet, sonst das Ende eines Durchgangs |
UserPromptSubmit, PostToolUse, PostToolUseFailure, SessionEnd | die Person hat getippt, das freigegebene Tool ist gelaufen oder gescheitert, die CLI wurde beendet | beantwortet |
Notification, Typ idle_prompt | "Claude finished responding about 60 seconds ago and you haven't typed since" | ignoriert |
An der Zeile idle_prompt gehen die meisten Setups schief. Ihre Meldung klingt genau nach dem, was man will, aber sie folgt auf jede Antwort, auf die niemand getippt hat, und wer sie als Frage behandelt, löst nach fast jedem Durchgang einen Alarm aus (bei Foxl ein Eintrag in „Braucht dich“ und eine Benachrichtigung aufs Handy). Wir registrieren den Notification-Hook nur mit dem Matcher permission_prompt, und das Skript prüft den Typ noch einmal. Für den Test bei Stop entfernen wir vor dem Prüfen Leerraum am Ende, Markdown-Hervorhebungen, Backticks, schließende Klammern und Anführungszeichen und akzeptieren auch das vollbreite ?, das CJK-Eingabemethoden tippen.
Die aktuelle Dokumentation von Claude Code führt außerdem ein eigenes Ereignis PermissionRequest und mehr Benachrichtigungstypen als diese auf. Ob 2.1.296 das neuere Ereignis schon hat, haben wir nicht geprüft. permission_prompt steht weiterhin in der aktuellen Liste, und seine Wartezeit von sechs Sekunden filtert einen Dialog heraus, den jemand am Bildschirm beantwortet. Füge die Hooks in die Einstellungsdatei von Claude Code auf Benutzerebene ein, hinter allen Hooks, die für dasselbe Ereignis schon konfiguriert sind, damit bestehende Hooks weiterlaufen:
{
"hooks": {
"PreToolUse": [{ "matcher": "AskUserQuestion",
"hooks": [{ "type": "command", "command": "report-prompt", "timeout": 10 }] }],
"Notification": [{ "matcher": "permission_prompt",
"hooks": [{ "type": "command", "command": "report-prompt", "timeout": 10 }] }],
"Stop": [{ "hooks": [{ "type": "command", "command": "report-prompt", "timeout": 10 }] }]
}
}Alle rufen ein kleines Skript auf, den Meldebefehl (oben report-prompt), der die Zugangsdaten der Aufgabe aus seiner Umgebung liest. Die Ereignisse, die bedeuten, dass die Person geantwortet hat, UserPromptSubmit und die übrigen (die Schließ-Ereignisse), werden genauso registriert, hinter einem Wächter, der unten beschrieben ist.
Wie schreibt man einen Hook, der den Agenten so wenig wie möglich kostet?
Ein Melde-Hook läuft innerhalb der Schleife des Agenten selbst, also wird jeder Fehler darin zum Problem des Agenten. Am Ende standen fünf Regeln, jede aus der Dokumentation oder aus dem Paket 2.1.296:
- Nichts auf stdout ausgeben. Bei den meisten Ereignissen protokolliert Claude Code das stdout eines Hooks nur, aber bei
UserPromptSubmitund ein paar anderen gilt: „Claude Code fügt reinen Text auf stdout als Kontext hinzu, den Claude sehen und auf den es reagieren kann.“ Eine Statuszeile aus einem Meldeskript würde Teil des Prompts. - Immer mit 0 beenden. Exit-Code 2 blockiert bei Ereignissen, die blockieren können, die Aktion, und jeder andere Code ungleich null zeigt einen Fehlerhinweis. In unserem Skript kostet ein Netzwerkfehler eine Zeile auf stderr und sonst nichts.
- Synchron laufen, mit kurzem Timeout. Hooks können mit
"async": truelaufen, aber der gepinnte Build gibt jedes Mal eine Zeile im Terminal aus, wenn ein asynchroner Hook fertig ist, und das wird zu Rauschen, wenn Hooks nach jedem Tool-Aufruf laufen. Unsere Hooks sind synchron mittimeout: 10, und das Skript gibt seiner Anfrage drei Sekunden und beendet sich kurz danach von selbst. Bei Claude Code sind die echten Kosten ein Start von Node.js und eine Anfrage am Ende jeder Antwort, höchstens etwa drei Sekunden, wenn der Server von Foxl nicht erreichbar ist. - Die häufigen Ereignisse in der Shell abfangen.
PostToolUsefeuert bei jedem Tool-Aufruf. Der Meldebefehl legt eine Markierungsdatei an, wenn er eine offene Rückfrage meldet. Die Schließ-Hooks starten Node.js nur, wenn diese Datei existiert, und leeren sonst stdin, damit die CLI nie eine kaputte Pipe sieht:
Solange nichts offen ist, ist das einif [ -e /tmp/foxl-agent-prompt/open ]; then exec report-prompt; else cat >/dev/null; fitest -epro Tool-Aufruf. - Die Zugangsdaten aus der Befehlszeile heraushalten. Der Hook erbt die Umgebung der CLI, also wird das Token aus einer Umgebungsvariable gelesen und taucht nie in
psauf.
Wie sagen es Codex, OpenCode und Hermes?
Jede CLI hat ihren eigenen Erweiterungspunkt; wir haben jeden aus dem Release gelesen, das unsere Images pinnen. Codex hat eine Hook-Engine, die das Hook-Format von Claude Code annimmt. OpenCode und Hermes (die Agenten-CLI von Nous Research) führen in ihrer Terminal-Oberfläche keine Shell-Hooks aus; sie laden Plugins, und unsere Plugins übergeben demselben Meldebefehl ein normalisiertes Ereignis. Kiro, die Coding-CLI von AWS, hat kein Ereignis, auf das man hören könnte.
| CLI (Pin) | fragt | beantwortet | nicht gemeldet |
|---|---|---|---|
Codex 0.162.1, eine hooks.json auf Systemebene | PermissionRequest; Stop, dessen last_assistant_message mit ? endet | UserPromptSubmit, PostToolUse, Interrupt, SessionEnd | der Fragedialog im Plan-Modus |
| OpenCode 1.19.0, ein Server-Plugin | question.asked, permission.asked; session.status idle mit einer Antwort, die auf ? endet | question.replied oder rejected, permission.replied, session.status busy | - |
| Hermes 0.19.0, ein Python-Plugin | pre_tool_call für clarify, pre_approval_request, post_llm_call mit ? am Ende | post_tool_call für clarify, post_approval_response, pre_llm_call, ein unterbrochenes on_session_end | - |
| Kiro 2.29.1 | nichts | - | alles: kein Frage- oder Freigabe-Ereignis, und sein Stop trägt keinen Antworttext |
Codex. Codex prüft Hooks aus deiner eigenen Konfiguration, bevor es sie ausführt: Neue oder geänderte Hooks „werden zur Prüfung markiert und übersprungen, bis ihnen vertraut wird“. Einem verwalteten Hook, der in der Konfiguration auf Systemebene steht, wird per Richtlinie vertraut, also installieren wir unsere so. Der Meldebefehl selbst wird nur in Terminals installiert, in denen Foxl Code Meldungen über Rückfragen angefordert hat. Gemessen auf 0.162.1 führt auch das nicht interaktive codex exec verwaltete Hooks aus und schreibt pro Tool-Aufruf zwei Zeilen darüber in seine Ausgabe, deshalb schalten wir Hooks für die Läufe ab, die Foxl Code mit codex exec startet. Laut dem Quellcode von 0.162.1 zeigt die Terminal-Oberfläche von Codex jeden Hook an, der länger als 300 ms läuft, deshalb entscheidet der Meldebefehl, ob es eine Rückfrage gibt, schreibt seine Markierungsdatei und übergibt die Netzwerkanfrage an eine abgekoppelte Kopie seiner selbst.
Der Fragedialog im Plan-Modus von Codex wird bewusst nicht gemeldet, weil sein PreToolUse-Hook feuert, bevor Codex entscheidet, ob die Frage erlaubt ist, und außerhalb des Plan-Modus lehnt Codex sie ab. Gemessen auf 0.162.1 feuerte der Hook mit der Frage, und dann antwortete Codex "request_user_input is unavailable in Default mode". Die Terminals von Foxl Code starten im Default-Modus, eine Meldung dieses Hooks würde also eine Frage auf dein Handy schicken, die nie jemandem gestellt wurde. Der Preis dafür: Bei einem Codex-Terminal im Plan-Modus landet der Fragedialog nicht in „Braucht dich“.
OpenCode. Unser Plugin hört auf den Event-Bus von OpenCode. Die Frage-Ereignisse stehen nicht in der Ereignisliste der Plugin-Dokumentation von OpenCode; sie stehen im Schema-Quellcode von v1.19.0, und den haben wir gelesen. Ein Idle-Status beendet einen Durchgang, und der Durchgang zählt als Frage, wenn seine letzte Antwort auf ? endet. Solange ein Frage- oder Berechtigungsdialog offen ist, werden Statuswechsel ignoriert, damit der Agent, der rund um den Dialog busy oder idle wird, ihn nicht schließt. Ereignisse aus der Sitzung eines Subagenten werden übersprungen.
Hermes. Anders als der Name vermuten lässt, feuert on_session_end von Hermes auf 0.19.0 am Ende jedes Durchgangs, direkt nach der Antwort. Als unser Plugin es als Schließen behandelte, zog es die Frage zurück, die der Durchgang gerade gestellt hatte: 7 von 12 Fragen wurden sofort geschlossen, und in 1 von 12 Fällen erreichte die Frage den Server erst nach ihrem eigenen Schließen, blieb also offen, ohne dass noch etwas sie schließen konnte. Jetzt zählt nur ein unterbrochenes Sitzungsende als Schließen, und Meldungen gehen eine nach der anderen in der Reihenfolge hinaus, in der Hermes sie ausgelöst hat.
Kiro ist nicht abgedeckt, weil seine Hooks kein Frage- oder Freigabe-Ereignis haben und sein Stop-Payload keinen Antworttext trägt. Ein Hook könnte weder eine Rückfrage eröffnen noch eine Frage von einer Antwort unterscheiden. Das einzige Signal ist eine interne Sitzungsdatei in einem unveröffentlichten Format, und wir haben uns entschieden, sie nicht zu parsen.
Was passiert, sobald Foxl Bescheid weiß?
Jede Meldung geht an einen Endpunkt auf dem Server von Foxl Code, authentifiziert mit den eigenen Zugangsdaten der jeweiligen Aufgabe, und öffnet oder schließt einen Eintrag in derselben Liste „Braucht dich“, in der die anderen Fragen der Agenten stehen. Die Aufgabe wird als wartend auf deine Antwort markiert, wie in der Abbildung.

Eine Frage am Ende einer Antwort kannst du in „Braucht dich“ oder auf dem Handy beantworten. Foxl tippt die Antwort als eine Zeile in das Terminal der Aufgabe und schickt die Eingabetaste eine Sekunde später separat, weil ein einzelner Block mitsamt Enter als Einfügen behandelt und nie abgeschickt wird. Bei einem Frage- oder Berechtigungsdialog rät Foxl nie die Tastendrücke, die die Terminal-Oberfläche erwartet. Stattdessen listet seine Karte in „Braucht dich“ die Auswahlmöglichkeiten auf, sagt, dass im Terminal geantwortet werden soll, und hat eine Schaltfläche, die das Terminal öffnet. Eine Antwort im Terminal schließt die Karte über dieselben Hooks.
Das Handy wird nur über Rückfragen benachrichtigt, die übersehen werden können. Ein Frage- oder Berechtigungsdialog, der 15 Sekunden nachdem Foxl davon erfährt noch offen ist, löst eine Benachrichtigung aus, denn wer aufs Terminal schaut, antwortet innerhalb von Sekunden. Ein Berechtigungsdialog von Claude Code wird etwa sechs Sekunden nach dem Öffnen gemeldet, seine Benachrichtigung kommt also nach etwa 21 Sekunden. Eine Antwort, die mit einer Frage endet, erscheint in „Braucht dich“, wird aber nicht angekündigt, weil viele Antworten mit einer Frage enden. Die Frage vom 2026-10-21 war von dieser Art, sie würde jetzt also in „Braucht dich“ und an der Aufgabe erscheinen und das Handy trotzdem nicht klingeln lassen.

Was ist noch nicht verifiziert?
In unseren Tests lief der echte Meldebefehl auf den Payloads jeder gepinnten CLI, die Plugins liefen unter Node.js und Python auf den gepinnten Ereignisformaten, und der Endpunkt des Servers lief in einer lokalen Kopie der Laufzeitumgebung von Cloudflare. Was noch nicht passiert ist:
- Eine echte Frage aus einem echten Cloud-Terminal. Stand 2026-10-23 enthält die Produktionstabelle keine Rückfrage aus einem solchen, die Ende-zu-Ende-Prüfung an einem echten Terminal steht also noch aus.
- Claude Code, das diese Hooks ausführt. Die Details zu Claude Code, einschließlich der Verzögerung von sechs Sekunden und der Zeile für asynchrone Hooks, wurden aus dem Paket 2.1.296 gelesen, nicht an einem laufenden Terminal beobachtet. Wir haben einen Test, der diesen Build gegen diese Hooks laufen lässt; ausgeführt wurde er noch nicht.
- Die Terminals der anderen CLIs. Mehrere Details zu Codex, OpenCode und Hermes wurden aus dem Quellcode gelesen, auch, dass OpenCode die Frage-Ereignisse unter genau diesen Namen liefert; ausgeführt wurde nur
codex exec.
Wenn du Agenten in eigenen Terminals laufen lässt, ist die Tabelle der Hooks von Claude Code der Teil zum Kopieren. Verbinde die drei Hooks mit dem, was dich erreicht, ignoriere idle_prompt, gib nichts aus, beende mit 0 und warte ein paar Sekunden, bevor du einen Alarm schickst. Zur Terminal-Seite von Foxl Code erklärt unser Beitrag darüber, warum jeder Tastendruck einmal auf der falschen Maschine landete (auf Englisch), wie Tastatureingaben überhaupt zu einem Remote-Agenten gelangen.
Quellen und weiterführende Lektüre
- Claude Code: Hooks-ReferenzDokumentation
- Codex: HooksDokumentation
- OpenCode: PluginsDokumentation
- Hermes Agent (Nous Research)Referenz
- Release Foxl v0.9.3-beta.5Release