Zum Hauptinhalt springenZum Inhalt springen
Deep Dive

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.

Foxl Team12 Min. Lesezeit

Ein handgezeichnetes Terminalfenster, dessen Cursor unter einem Fragezeichen steht; eine Linie aus dem Fenster endet in einem Haken, der ein Handy mit einer Glocke darauf gefangen hat.
Auf dieser Seite
Am 23. Oktober 2026 anhand der ausgelieferten Implementierung und der erhaltenen Tests geprüft.

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.

Hookwas er bedeutetwir behandeln ihn als
PreToolUse, Matcher AskUserQuestionder Fragedialog öffnet sich gleich; tool_input enthält die Fragen und ihre Optioneneine Frage, mit ihren Auswahlmöglichkeiten
Notification, Matcher permission_promptein Berechtigungsdialog ist seit etwa sechs Sekunden ohne Tastendruck offen (aus dem Paket gelesen)eine Berechtigungsanfrage
Stopdie Antwort ist fertig; last_assistant_message ist ihr Texteine Frage, wenn der Text mit ? endet, sonst das Ende eines Durchgangs
UserPromptSubmit, PostToolUse, PostToolUseFailure, SessionEnddie Person hat getippt, das freigegebene Tool ist gelaufen oder gescheitert, die CLI wurde beendetbeantwortet
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 UserPromptSubmit und 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": true laufen, 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 mit timeout: 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. PostToolUse feuert 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:
    if [ -e /tmp/foxl-agent-prompt/open ]; then exec report-prompt; else cat >/dev/null; fi
    Solange nichts offen ist, ist das ein test -e pro 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 ps auf.

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)fragtbeantwortetnicht gemeldet
Codex 0.162.1, eine hooks.json auf SystemebenePermissionRequest; Stop, dessen last_assistant_message mit ? endetUserPromptSubmit, PostToolUse, Interrupt, SessionEndder Fragedialog im Plan-Modus
OpenCode 1.19.0, ein Server-Pluginquestion.asked, permission.asked; session.status idle mit einer Antwort, die auf ? endetquestion.replied oder rejected, permission.replied, session.status busy-
Hermes 0.19.0, ein Python-Pluginpre_tool_call für clarify, pre_approval_request, post_llm_call mit ? am Endepost_tool_call für clarify, post_approval_response, pre_llm_call, ein unterbrochenes on_session_end-
Kiro 2.29.1nichts-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.

Die Seite Arbeit von Foxl Code. In der Spalte „Needs you“ steht auf einer Karte „Claude Code is asking“ mit einer Ja-oder-Nein-Frage zu einem Job, der absichtlich fehlschlägt, und einem Antwortfeld mit „Send“. Eine zweite Karte zeigt „Claude Code is asking“ mit einer Frage und drei aufgelisteten Auswahlmöglichkeiten, gefolgt von „Answer this in the terminal.“ und einer Schaltfläche „Show terminal“. In der Spalte „In flight“ zeigen zwei Aufgaben „Waiting for your answer“.
Abbildung 1. Die Seite Arbeit von Foxl Code aus dem Build des Pull Requests, mit Beispielfragen. Eine Frage in einer Antwort lässt sich hier beantworten; ein Dialog wird im Terminal beantwortet.

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.

Ein Ablauf von links nach rechts. Vier CLIs, Claude Code, Codex, OpenCode und Hermes, melden jeweils über ihren eigenen Hook oder ihr Plugin an einen kleinen Befehl in der Maschine des Agenten. Der Befehl öffnet oder schließt mit den Zugangsdaten der Aufgabe eine Rückfrage auf dem Server von Foxl Code. Der Server zeigt sie in „Needs you“ und an der Aufgabe und benachrichtigt das Handy nur, wenn ein Dialog 15 Sekunden nach der Meldung noch offen ist.
Abbildung 2. Vier CLIs melden über einen Befehl; das Handy erfährt von einem Dialog nur, wenn ihn 15 Sekunden nach der Meldung noch niemand beantwortet hat.

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

  1. Claude Code: Hooks-ReferenzDokumentation
  2. Codex: HooksDokumentation
  3. OpenCode: PluginsDokumentation
  4. Hermes Agent (Nous Research)Referenz
  5. Release Foxl v0.9.3-beta.5Release