Deutsch

Hooks

Führen Sie während des Codex-Lebenszyklus deterministische Skripte aus

Hooks sind ein Erweiterungsframework für Codex. Sie ermöglichen es Ihnen, eigene Skripte in die Agentenschleife einzubinden und dadurch Funktionen wie die folgenden zu realisieren:

  • Senden Sie den Chat an eine benutzerdefinierte Protokollierungs-/Analyse-Engine
  • Prüfen Sie die Prompts Ihres Teams, um das versehentliche Einfügen von API keys zu verhindern
  • Fassen Sie Chats zusammen, um automatisch dauerhafte Erinnerungen zu erstellen
  • Führen Sie beim Beenden eines Chat-Durchlaufs eine benutzerdefinierte Validierungsprüfung aus, um Standards durchzusetzen
  • Passen Sie Prompts an, wenn Sie sich in einem bestimmten Verzeichnis befinden

Beachten Sie folgendes Laufzeitverhalten:

  • Alle übereinstimmenden Hooks aus mehreren Dateien werden ausgeführt.
  • Mehrere übereinstimmende Befehls-Hooks für dasselbe Ereignis werden gleichzeitig gestartet, sodass ein Hook den Start eines anderen übereinstimmenden Hooks nicht verhindern kann.
  • Nicht verwaltete Befehls-Hooks müssen vor ihrer Ausführung überprüft und als vertrauenswürdig eingestuft werden.

Hooks werden zu verschiedenen Zeitpunkten einer Unterhaltung ausgeführt:

Zeitpunkt Hooks
Während eines Durchlaufs PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop
Beim Start einer Sitzung oder eines Subagenten SessionStart, SubagentStart
Beim Ende des Haupt-Threads SessionEnd (wird für Subagenten nicht ausgeführt)

Wo Codex nach Hooks sucht

Codex erkennt Hooks neben aktiven Konfigurationsebenen in einer der folgenden Formen:

  • hooks.json
  • Inline-Tabellen vom Typ [hooks] innerhalb von config.toml

Installierte Plugins können über ihr Plugin-Manifest oder eine standardmäßige Datei hooks/hooks.json ebenfalls Lebenszykluskonfigurationen bündeln. Die Regeln für die Plugin-Paketierung finden Sie unter Plugins erstellen.

In der Praxis sind die vier nützlichsten Speicherorte:

  • ~/.codex/hooks.json
  • ~/.codex/config.toml
  • <repo>/.codex/hooks.json
  • <repo>/.codex/config.toml

Wenn mehrere Hook-Quellen vorhanden sind, lädt Codex alle übereinstimmenden Hooks. Konfigurationsebenen mit höherer Priorität ersetzen Hooks aus Ebenen mit niedrigerer Priorität nicht. Wenn eine einzelne Ebene sowohl hooks.json als auch Inline-[hooks] enthält, führt Codex sie zusammen und gibt beim Start eine Warnung aus. Verwenden Sie vorzugsweise nur eine Darstellungsform pro Ebene.

Codex kann außerdem Hooks erkennen, die mit aktivierten Plugins gebündelt sind. Mit Plugins gebündelte Hooks werden zusammen mit anderen Hook-Quellen geladen und durchlaufen denselben Prozess zur Vertrauensprüfung wie andere nicht verwaltete Hooks.

Projektlokale Hooks werden nur geladen, wenn die Projektebene .codex/ als vertrauenswürdig eingestuft ist. In nicht vertrauenswürdigen Projekten lädt Codex weiterhin Benutzer- und System-Hooks aus deren eigenen aktiven Konfigurationsebenen.

Hooks überprüfen und als vertrauenswürdig einstufen

Codex führt konfigurierte Hooks auf, bevor entschieden wird, welche davon ausgeführt werden dürfen. Bevor ein nicht verwalteter Befehls-Hook ausgeführt werden kann, müssen Sie die genaue Hook-Definition überprüfen und als vertrauenswürdig einstufen. Codex speichert die Vertrauensentscheidung für den aktuellen Hash des Hooks, sodass neue oder geänderte Hooks zur Überprüfung markiert und übersprungen werden, bis sie als vertrauenswürdig eingestuft wurden.

Verwenden Sie /hooks in der CLI, um Hook-Quellen zu untersuchen, neue oder geänderte Hooks zu überprüfen, Hooks als vertrauenswürdig einzustufen oder einzelne nicht verwaltete Hooks zu deaktivieren. Wenn Hooks beim Start überprüft werden müssen, gibt Codex eine Warnung aus, die Sie zum Öffnen von /hooks auffordert.

Verwaltete Hooks aus System-, MDM-, Cloud- oder requirements.toml-Quellen werden als verwaltet markiert, gelten gemäß Richtlinie als vertrauenswürdig und können nicht über den Hook-Browser des Benutzers deaktiviert werden.

Für einmalige Automatisierungen, bei denen Hook-Quellen bereits außerhalb von Codex geprüft werden, übergeben Sie --dangerously-bypass-hook-trust, um aktivierte Hooks für diesen Aufruf ohne gespeicherte Hook-Vertrauensentscheidung auszuführen.

Konfigurationsstruktur

Hooks sind auf drei Ebenen organisiert:

  • Ein Hook-Ereignis wie PreToolUse, PostToolUse, PreCompact, SubagentStart oder Stop
  • Eine Matcher-Gruppe, die bestimmt, wann dieses Ereignis übereinstimmt
  • Ein oder mehrere Hook-Handler, die ausgeführt werden, wenn die Matcher-Gruppe übereinstimmt
{
  "description": "Optional lifecycle hooks for this workspace.",
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup|resume",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.codex/hooks/session_start.py",
            "statusMessage": "Loading session notes",
            "additionalContextLimit": 5000
          }
        ]
      }
    ],
    "SessionEnd": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.codex/hooks/session_end.py",
            "timeout": 3
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py\"",
            "statusMessage": "Checking Bash command"
          }
        ]
      }
    ],
    "PermissionRequest": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/permission_request.py\"",
            "statusMessage": "Checking approval request"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use_review.py\"",
            "statusMessage": "Reviewing Bash output"
          }
        ]
      }
    ],
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/user_prompt_submit_data_flywheel.py\""
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/stop_continue.py\"",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

Hinweise:

  • description sind optionale Metadaten auf oberster Ebene für eine hooks.json-Datei. Sie ändern nicht, welche Hooks ausgeführt werden.
  • timeout wird in Sekunden angegeben.
  • Wenn timeout nicht angegeben ist, verwendet Codex für die meisten Hooks 600 Sekunden.
    • SessionEnd verwendet standardmäßig 1 Sekunde und unterstützt bis zu 3 Sekunden.
  • statusMessage ist optional.
  • additionalContextLimit legt fest, wie viel additionalContext ein Befehls-Hook an das Modell senden kann, bevor Codex den vollständigen Text auf dem Datenträger speichert und stattdessen eine kürzere Vorschau sendet. Siehe Umfangreiche Hook-Ausgabe.
  • commandWindows ist eine optionale, ausschließlich für Windows vorgesehene Befehlsüberschreibung. Verwenden Sie in TOML command_windows oder commandWindows.
  • Die Option async wird geparst, asynchrone Befehls-Hooks werden jedoch noch nicht unterstützt.
  • Derzeit werden nur type: "command"-Handler ausgeführt. prompt- und agent-Handler werden geparst, aber übersprungen.
  • Befehle werden mit dem cwd der Sitzung als Arbeitsverzeichnis ausgeführt.
  • Bei Repository-lokalen Hooks sollten Sie den Pfad vorzugsweise ausgehend vom Git-Stammverzeichnis auflösen, statt einen relativen Pfad wie .codex/hooks/... zu verwenden. Codex kann aus einem Unterverzeichnis gestartet werden, und ein auf dem Git-Stammverzeichnis basierender Pfad hält den Speicherort des Hooks stabil.

Entsprechendes Inline-TOML in config.toml:

[[hooks.SessionStart]]
matcher = "^compact$"

[[hooks.SessionStart.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/session_start.py"'
additionalContextLimit = 5000

[[hooks.PreToolUse]]
matcher = "^Bash$"

[[hooks.PreToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py"'
timeout = 30
statusMessage = "Checking Bash command"

[[hooks.PostToolUse]]
matcher = "^Bash$"

[[hooks.PostToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use_review.py"'
timeout = 30
statusMessage = "Reviewing Bash output"

Hooks deaktivieren

Hooks sind standardmäßig aktiviert. Um sie in config.toml zu deaktivieren, legen Sie Folgendes fest:

[features]
hooks = false

Verwenden Sie hooks als maßgeblichen Funktionsschlüssel. codex_hooks funktioniert weiterhin als veralteter Alias. Administratoren können Hooks auf dieselbe Weise in requirements.toml mit [features].hooks = false zwangsweise deaktivieren.

Verwaltete Hooks aus requirements.toml

Von Unternehmen verwaltete Anforderungen können Hooks auch inline unter [hooks] definieren. Dies ist nützlich, wenn Administratoren die Hook-Konfiguration erzwingen und die eigentlichen Skripte über MDM oder ein anderes Geräteverwaltungssystem bereitstellen möchten. Um verwaltete Hooks auch für Benutzer zu erzwingen, die Hooks lokal deaktiviert haben, fixieren Sie [features].hooks = true in requirements.toml zusammen mit [hooks]. Um Benutzer-, Projekt-, Sitzungs- und Plugin-Hooks zu ignorieren, während von Administratoren verwaltete Hooks weiterhin zugelassen werden, legen Sie allow_managed_hooks_only = true fest.

allow_managed_hooks_only = true

[features]
hooks = true

[hooks]
managed_dir = "/enterprise/hooks"
windows_managed_dir = 'C:\enterprise\hooks'

[[hooks.PreToolUse]]
matcher = "^Bash$"

[[hooks.PreToolUse.hooks]]
type = "command"
command = "python3 /enterprise/hooks/pre_tool_use_policy.py"
command_windows = 'py -3 C:\enterprise\hooks\pre_tool_use_policy.py'
timeout = 30
statusMessage = "Checking managed Bash command"

Hinweise zu verwalteten Hooks:

  • managed_dir wird unter macOS und Linux verwendet.
  • windows_managed_dir wird unter Windows verwendet.
  • Codex verteilt die Skripte in managed_dir nicht; Ihre Unternehmenswerkzeuge müssen sie separat installieren und aktualisieren.
  • Befehle verwalteter Hooks sollten absolute Skriptpfade unterhalb des konfigurierten verwalteten Verzeichnisses verwenden.
  • allow_managed_hooks_only = true überspringt Hooks aus Benutzer-, Projekt-, Sitzungs- und Plugin-Quellen, lädt jedoch weiterhin verwaltete Hooks aus requirements.toml und anderen verwalteten Konfigurationsebenen.

Mit Plugins gebündelte Hooks

Wenn ein Plugin aktiviert ist, kann Codex Lebenszyklus-Hooks aus diesem Plugin zusammen mit Benutzer-, Projekt- und verwalteten Hooks laden.

Standardmäßig sucht Codex innerhalb des Plugin-Stammverzeichnisses nach hooks/hooks.json. Ein Plugin- Manifest kann diesen Standard mit einem hooks-Eintrag in .codex-plugin/plugin.json überschreiben. Der Manifest-Eintrag kann ein mit ./ beginnender Pfad, ein Array aus mit ./ beginnenden Pfaden, ein Inline-Hook-Objekt oder ein Array aus Inline- Hook-Objekten sein.

{
  "name": "repo-policy",
  "hooks": "./hooks/hooks.json"
}

Hook-Pfade im Manifest werden relativ zum Plugin-Stammverzeichnis aufgelöst und müssen innerhalb dieses Stammverzeichnisses bleiben. Wenn ein Manifest hooks definiert, verwendet Codex diese Manifest- Einträge anstelle des standardmäßigen hooks/hooks.json.

Plugin-Hook-Befehle erhalten diese Umgebungsvariablen:

  • PLUGIN_ROOT ist eine Codex-spezifische Erweiterung, die auf das Stammverzeichnis des installierten Plugins verweist.
  • PLUGIN_DATA ist eine Codex-spezifische Erweiterung, die auf das beschreibbare Datenverzeichnis des Plugins verweist.
  • Codex legt außerdem CLAUDE_PLUGIN_ROOT und CLAUDE_PLUGIN_DATA fest, um die Kompatibilität mit vorhandenen Plugin-Hooks zu gewährleisten.

Plugin-Hooks verwenden dasselbe Ereignisschema wie andere Hooks. Durch das Installieren oder Aktivieren eines Plugins werden dessen Hooks nicht automatisch als vertrauenswürdig eingestuft; Codex überspringt mit dem Plugin gebündelte Hooks, bis Sie die aktuelle Hook-Definition überprüft und als vertrauenswürdig eingestuft haben.

Matcher-Muster

Das Feld matcher ist eine Regex-Zeichenfolge, die filtert, wann Hooks ausgelöst werden. Verwenden Sie "*", "" oder lassen Sie matcher vollständig weg, um jedes Auftreten eines unterstützten Ereignisses abzugleichen.

Nur einige der aktuellen Codex-Ereignisse berücksichtigen matcher:

Ereignis Was matcher filtert Hinweise
PermissionRequest Toolname Unterstützt werden unter anderem Bash, apply_patch* und Namen von MCP-Tools
PostToolUse Toolname Siehe Toolabdeckung
PostCompact Auslöser der Komprimierung Werte sind manual oder auto
PreCompact Auslöser der Komprimierung Werte sind manual oder auto
PreToolUse Toolname Siehe Toolabdeckung
SessionEnd Beendigungsgrund Derzeit nur other
SessionStart Startquelle Werte sind startup, resume, clear und compact
SubagentStart Subagent-Typ Die Werte hängen vom gestarteten Subagent ab
SubagentStop Subagent-Typ Die Werte hängen vom beendeten Subagent ab
UserPromptSubmit nicht unterstützt Für dieses Ereignis wird jedes konfigurierte matcher ignoriert
Stop nicht unterstützt Für dieses Ereignis wird jedes konfigurierte matcher ignoriert

*Für apply_patch können matcher-Werte auch Edit oder Write verwenden.

Beispiele:

  • Bash
  • ^apply_patch$
  • Edit|Write
  • mcp__filesystem__read_file
  • mcp__filesystem__.*
  • startup|resume|clear|compact
  • manual|auto

Toolabdeckung

PreToolUse und PostToolUse können mehr als Shell- und MCP-Aufrufe beobachten. Die meisten lokalen Funktionstools verwenden denselben Hook-Pfad, sodass Sie ihren Toolnamen abgleichen, ihre JSON-Argumente prüfen und den Aufruf bei PreToolUse blockieren oder umschreiben können.

Toolpfad PreToolUse PostToolUse Hinweise
Shell-Befehle Ja Ja Als Bash abgleichen.
Vereinheitlichte Ausführung (exec_command) Ja Ja Als Bash abgleichen. Eine spätere write_stdin-Abfrage kann nach Abschluss des ursprünglichen Befehls dessen PostToolUse liefern.
apply_patch Ja Ja Als apply_patch, Edit oder Write abgleichen.
MCP-Tools Ja Ja Den Namen des MCP-Tools abgleichen, beispielsweise mcp__filesystem__read_file.
Andere lokale Funktionstools Ja Ja Den Namen des Funktionstools abgleichen, beispielsweise update_plan. spawn_agent stimmt auch mit Agent überein.
Gehostete Tools wie WebSearch Nein Nein Diese verwenden nicht den Hook-Pfad für lokale Funktionstools.

write_stdin dient als Transport für eine bestehende Unified-Exec-Sitzung. Es führt PreToolUse nicht erneut aus, wenn es Eingaben sendet oder einen Befehl abfragt, der PreToolUse bereits durchlaufen hat.

Einige spezialisierte Toolpfade können den standardmäßigen Hook-Pfad umgehen. Betrachten Sie Tool- Hooks als nützliche Schutzmaßnahme, nicht als vollständige Durchsetzungsgrenze.

Gemeinsame Eingabefelder

Jeder Befehlshook empfängt ein JSON-Objekt über stdin.

Dies sind die gemeinsamen Felder, die Sie üblicherweise verwenden:

Feld Typ Bedeutung
session_id string ID der aktuellen Codex-Sitzung. Subagent-Hooks verwenden die ID der übergeordneten Sitzung.
transcript_path string | null Pfad zur Sitzungsprotokolldatei, sofern vorhanden
cwd string Arbeitsverzeichnis der Sitzung
hook_event_name string Name des aktuellen Hook-Ereignisses
model string Codex-spezifische Erweiterung. Slug des aktiven Modells

Auf einzelne Turns begrenzte Hooks führen turn_id in ihren ereignisspezifischen Tabellen als Codex-spezifische Erweiterung auf.

SessionStart, PreToolUse, PermissionRequest, PostToolUse, UserPromptSubmit, SubagentStart, SubagentStop und Stop enthalten außerdem permission_mode, das den aktuellen Berechtigungsmodus als default, acceptEdits, plan, dontAsk oder bypassPermissions beschreibt.

transcript_path verweist der Einfachheit halber auf ein Chatprotokoll, doch das Protokollformat ist keine stabile Schnittstelle für Hooks und kann sich im Laufe der Zeit ändern.

Das vollständige Übertragungsformat finden Sie unter Schemas.

Gemeinsame Ausgabefelder

SessionStart, PreCompact, PostCompact, UserPromptSubmit, SubagentStop und Stop unterstützen diese gemeinsamen JSON-Felder. SubagentStart akzeptiert dieselbe Struktur für systemMessage und Hook-spezifischen Kontext, aber continue: false beendet den Subagent nicht:

{
  "continue": true,
  "stopReason": "optional",
  "systemMessage": "optional",
  "suppressOutput": false
}
Feld Wirkung
continue Markiert diesen Hook-Lauf bei false als beendet
stopReason Wird als Grund für die Beendigung aufgezeichnet
systemMessage Wird in der UI oder im Ereignisstream als Warnung angezeigt
suppressOutput Wird derzeit geparst, ist aber noch nicht implementiert

Das Beenden mit 0 ohne Ausgabe wird als Erfolg behandelt und Codex fährt fort.

PreToolUse und PermissionRequest unterstützen systemMessage, aber continue, stopReason und suppressOutput werden für diese Ereignisse derzeit nicht unterstützt. Wenn ein PreToolUse-Hook eines dieser nicht unterstützten Felder zurückgibt, markiert Codex diesen Hook-Lauf als fehlgeschlagen, meldet den Fehler und setzt den Toolaufruf fort.

PostToolUse unterstützt systemMessage, continue: false und stopReason. suppressOutput wird geparst, aber für dieses Ereignis derzeit nicht unterstützt.

Große Hook-Ausgaben

Standardmäßig begrenzt Codex jede für das Modell sichtbare Hook-Ausgabemeldung auf ungefähr 2.500 Token. Gibt ein Hook mehr zurück, speichert Codex den vollständigen Text unter <temp_dir>/hook_outputs/<session_id>/<uuid>.txt und stellt dem Modell eine Vorschau von Anfang und Ende mit dem Pfad der gespeicherten Datei bereit. Dieses Verhalten wird als Auslagern bezeichnet: Codex speichert übergroße Ausgaben auf dem Datenträger und ersetzt sie durch eine kürzere, für das Modell sichtbare Vorschau. Kann die Datei nicht geschrieben werden, erhält das Modell dennoch eine gekürzte Vorschau.

Legen Sie für jeden Befehlshook, der additionalContext zurückgibt, additionalContextLimit im Handler fest, um den ungefähren Token- Schwellenwert anzupassen:

{
  "type": "command",
  "command": "python3 ~/.codex/hooks/session_start.py",
  "additionalContextLimit": 5000
}

Lassen Sie additionalContextLimit weg, um den standardmäßigen Schwellenwert von 2500 Token zu verwenden. Verwenden Sie eine positive Ganzzahl, um einen anderen Schwellenwert auszuwählen, oder 0, um den vollständigen zusätzlichen Kontext des Handlers direkt an das Modell zu übergeben. Codex wertet jeden übereinstimmenden Handler unabhängig aus. Bei Ereignissen, die keinen zusätzlichen Kontext erzeugen können, ignoriert Codex additionalContextLimit und meldet eine Konfigurationswarnung.

Die Einstellung gilt nur für additionalContext. Toolfeedback und Fortsetzungs- Prompts behalten den Standardgrenzwert bei.

Da übergroße Ausgaben auf den Datenträger geschrieben werden können, sollten Sie keine Geheimnisse oder anderen vertraulichen Daten in Hook-Ausgaben zurückgeben.

Hooks

SessionStart

Für dieses Ereignis wird matcher auf source angewendet.

Felder zusätzlich zu den gemeinsamen Eingabefeldern:

Feld Typ Bedeutung
source string Art des Sitzungsstarts: startup, resume, clear oder compact

Nur-Text auf stdout wird als zusätzlicher Entwicklerkontext hinzugefügt.

JSON auf stdout unterstützt gemeinsame Ausgabefelder und diese Hook-spezifische Struktur:

{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "Load the workspace conventions before editing."
  }
}

Dieser additionalContext-Text wird als zusätzlicher Entwicklerkontext hinzugefügt.

Nachdem Codex eine Stammsitzung komprimiert hat, werden SessionStart-Hooks, die mit source: "compact" übereinstimmen, vor der nächsten Modellanfrage ausgeführt. Dies gilt auch, wenn eine automatische Komprimierung mitten in einem Turn erfolgt: Codex übermittelt den zusätzlichen Kontext des Hooks an die unmittelbare Fortsetzung, anstatt bis zu einem späteren Benutzer-Turn zu warten. Gibt der Hook continue: false zurück, beendet Codex den Turn, ohne eine weitere Modellanfrage zu senden.

SessionEnd

Mit SessionEnd können Sie beim Ende einer Sitzung einen Befehl ausführen, etwa um abschließende Notizen zu speichern oder Dateien zu bereinigen. Der Hook wird für den Hauptthread ausgeführt, wenn Sie eine noch geöffnete Unterhaltung archivieren oder löschen, wenn Codex regulär beendet wird oder nachdem eine Unterhaltung 30 Minuten lang inaktiv war und in keinem verbundenen Client geöffnet ist. Für Subagents wird er nicht ausgeführt.

Wenn Sie zu einer anderen Unterhaltung wechseln oder thread/unsubscribe aufrufen, endet die Sitzung nicht sofort, daher wird SessionEnd nicht unmittelbar ausgeführt. Ihr Hook kann während seiner Ausführung weiterhin das Sitzungsprotokoll lesen.

Für dieses Ereignis filtert matcher nach reason. Derzeit ist reason immer other. Sie können matcher weglassen oder other verwenden, um den Hook bei jedem SessionEnd-Ereignis auszuführen.

Felder zusätzlich zu den gemeinsamen Eingabefeldern:

Feld Typ Bedeutung
reason string Grund für das Sitzungsende: other

Ein SessionEnd-Befehl erhält beispielsweise:

{
  "session_id": "thr_123",
  "transcript_path": "/workspace/.codex/rollout.jsonl",
  "cwd": "/workspace",
  "hook_event_name": "SessionEnd",
  "reason": "other"
}

SessionEnd-Hooks dienen nur als Hinweis. Ihre Ausgabe steuert Codex nicht und hält den Thread nicht geöffnet. Wenn ein Befehl das Zeitlimit überschreitet oder mit einem Fehler beendet wird, meldet Codex dies als Hook-Fehler.

SubagentStart

Für dieses Ereignis wird matcher auf agent_type angewendet.

Felder zusätzlich zu den gemeinsamen Eingabefeldern:

Feld Typ Bedeutung
turn_id string Codex-spezifische Erweiterung. ID des aktiven Codex-Turns
agent_id string Kennung des Subagent
agent_type string Subagent-Typ oder -Profil
permission_mode string Aktueller Berechtigungsmodus

Nur-Text auf stdout wird als zusätzlicher Entwicklerkontext für den Subagent hinzugefügt.

JSON auf stdout unterstützt systemMessage und diese Hook-spezifische Struktur:

{
  "hookSpecificOutput": {
    "hookEventName": "SubagentStart",
    "additionalContext": "Review the repository test conventions first."
  }
}

Dieser additionalContext-Text wird als zusätzlicher Entwicklerkontext für den Subagenten hinzugefügt. continue: false wird aus Kompatibilitätsgründen geparst, verhindert jedoch nicht, dass der Subagent startet.

PreToolUse

PreToolUse kann Bash, über apply_patch vorgenommene Dateiänderungen, MCP-Tool-Aufrufe und andere lokale Funktionstools abfangen. Unter Tool- Abdeckung finden Sie die unterstützten Pfade und Ausnahmen.

matcher wird auf tool_name und Matcher-Aliasse angewendet. Bei Dateiänderungen über apply_patch können matcher-Werte apply_patch, Edit oder Write verwenden; die Hook-Eingabe meldet weiterhin tool_name: "apply_patch".

Zusätzliche Felder zu den allgemeinen Eingabefeldern:

Feld Typ Bedeutung
turn_id string Codex-spezifische Erweiterung. ID des aktiven Codex-Turns
tool_name string Kanonischer Hook-Tool-Name, beispielsweise Bash, apply_patch oder ein MCP-Name wie mcp__fs__read
tool_use_id string Tool-Aufruf-ID für diesen Aufruf
tool_input JSON value Tool-spezifische Eingabe. Bash und apply_patch verwenden tool_input.command. MCP und andere lokale Funktionstools senden ihre Argumente.

Klartext auf stdout wird ignoriert.

JSON auf stdout kann systemMessage verwenden. Um einen unterstützten Tool-Aufruf abzulehnen, geben Sie diese Hook-spezifische Struktur zurück:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Destructive command blocked by hook."
  }
}

Codex akzeptiert außerdem diese ältere Blockstruktur:

{
  "decision": "block",
  "reason": "Destructive command blocked by hook."
}

Sie können auch den Exit-Code 2 verwenden und den Grund für die Blockierung in stderr schreiben.

Um für das Modell sichtbaren Kontext hinzuzufügen, ohne zu blockieren, geben Sie hookSpecificOutput.additionalContext zurück:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "additionalContext": "The pending command touches generated files."
  }
}

Um einen unterstützten Tool-Aufruf umzuschreiben, ohne ihn zu blockieren, geben Sie permissionDecision: "allow" mit updatedInput zurück:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "updatedInput": {
      "command": "echo rewritten"
    }
  }
}

Für Bash-Befehle und apply_patch muss updatedInput ein command-Feld vom Typ String enthalten. Für MCP und andere lokale Funktionstools ist updatedInput das Ersatzargumentobjekt. Geben Sie updatedInput nur zusammen mit permissionDecision: "allow" zurück; andere updatedInput-Strukturen werden als Fehler gemeldet.

permissionDecision: "ask", das veraltete decision: "approve", continue: false, stopReason und suppressOutput werden geparst, aber noch nicht unterstützt. Codex kennzeichnet die Hook-Ausführung als fehlgeschlagen, meldet den Fehler und setzt den Tool-Aufruf fort.

PermissionRequest

PermissionRequest wird ausgeführt, wenn Codex im Begriff ist, um eine Genehmigung zu bitten, etwa für eine Shell-Eskalation oder eine Genehmigung für ein verwaltetes Netzwerk. Der Hook kann die Anfrage zulassen, ablehnen oder auf eine Entscheidung verzichten und die normale Genehmigungsabfrage fortsetzen lassen. Für Befehle, die keine Genehmigung benötigen, wird er nicht ausgeführt.

matcher wird auf tool_name und Matcher-Aliasse angewendet. Zu den aktuellen kanonischen Werten gehören Bash, apply_patch und MCP-Tool-Namen wie mcp__server__tool; apply_patch stimmt außerdem mit Edit und Write überein.

Zusätzliche Felder zu den allgemeinen Eingabefeldern:

Feld Typ Bedeutung
turn_id string Codex-spezifische Erweiterung. ID des aktiven Codex-Turns
tool_name string Kanonischer Hook-Tool-Name, beispielsweise Bash, apply_patch oder ein MCP-Name wie mcp__fs__read
tool_input JSON value Tool-spezifische Eingabe. Bash und apply_patch verwenden tool_input.command, während MCP-Tools alle Argumente senden.
tool_input.description string | null Für Menschen verständlicher Genehmigungsgrund, sofern Codex einen bereitstellt

Klartext auf stdout wird ignoriert.

Einige Tool-Eingaben können eine für Menschen verständliche Beschreibung enthalten. Verlassen Sie sich jedoch nicht bei jedem Tool auf ein tool_input.description-Feld.

Um die Anfrage zu genehmigen, geben Sie Folgendes zurück:

{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "allow"
    }
  }
}

Um die Anfrage abzulehnen, geben Sie Folgendes zurück:

{
  "hookSpecificOutput": {
    "hookEventName": "PermissionRequest",
    "decision": {
      "behavior": "deny",
      "message": "Blocked by repository policy."
    }
  }
}

Wenn mehrere übereinstimmende Hooks Entscheidungen zurückgeben, hat jede deny-Entscheidung Vorrang. Andernfalls kann die Anfrage mit allow fortgesetzt werden, ohne dass die Genehmigungsabfrage angezeigt wird. Wenn kein übereinstimmender Hook eine Entscheidung trifft, verwendet Codex den normalen Genehmigungsablauf.

Geben Sie für PermissionRequest nicht updatedInput, updatedPermissions oder interrupt zurück; diese Felder sind für zukünftiges Verhalten reserviert und führen derzeit zur sicheren Ablehnung.

PostToolUse

PostToolUse wird ausgeführt, nachdem unterstützte Tools eine Ausgabe erzeugt haben, darunter Bash, apply_patch, MCP-Tool-Aufrufe und andere lokale Funktionstools. Bei Bash wird der Hook auch nach Befehlen ausgeführt, die mit einem von null verschiedenen Status beendet werden. Er kann Nebenwirkungen eines bereits ausgeführten Tools nicht rückgängig machen. Unter Tool-Abdeckung finden Sie die unterstützten Pfade und Ausnahmen.

matcher wird auf tool_name und Matcher-Aliasse angewendet. Bei Dateiänderungen über apply_patch können matcher-Werte apply_patch, Edit oder Write verwenden; die Hook-Eingabe meldet weiterhin tool_name: "apply_patch".

Zusätzliche Felder zu den allgemeinen Eingabefeldern:

Feld Typ Bedeutung
turn_id string Codex-spezifische Erweiterung. ID des aktiven Codex-Turns
tool_name string Kanonischer Hook-Tool-Name, beispielsweise Bash, apply_patch oder ein MCP-Name wie mcp__fs__read
tool_use_id string Tool-Aufruf-ID für diesen Aufruf
tool_input JSON value Tool-spezifische Eingabe. Bash und apply_patch verwenden tool_input.command. MCP und andere lokale Funktionstools senden ihre Argumente.
tool_response JSON value Tool-spezifische Ausgabe. MCP-Tools senden das Ergebnis des MCP-Aufrufs. Andere lokale Funktionstools senden normalerweise ihre für das Modell bestimmte Ausgabe.

Klartext auf stdout wird ignoriert.

JSON auf stdout kann systemMessage und diese Hook-spezifische Struktur verwenden:

{
  "decision": "block",
  "reason": "The Bash output needs review before continuing.",
  "hookSpecificOutput": {
    "hookEventName": "PostToolUse",
    "additionalContext": "The command updated generated files."
  }
}

Dieser additionalContext-Text wird als zusätzlicher Entwicklerkontext hinzugefügt.

Bei diesem Ereignis macht decision: "block" den abgeschlossenen Bash-Befehl nicht rückgängig. Stattdessen zeichnet Codex das Feedback auf, ersetzt das Tool-Ergebnis durch dieses Feedback und setzt das Modell mit der vom Hook bereitgestellten Nachricht fort.

Sie können auch den Exit-Code 2 verwenden und den Feedbackgrund in stderr schreiben.

Um die normale Verarbeitung des ursprünglichen Tool-Ergebnisses zu stoppen, nachdem der Befehl bereits ausgeführt wurde, geben Sie continue: false zurück. Codex ersetzt das Tool-Ergebnis durch Ihr Feedback oder Ihren Stopptext und fährt von dort aus fort.

updatedMCPToolOutput und suppressOutput werden geparst, aber noch nicht unterstützt. Codex kennzeichnet die Hook-Ausführung als fehlgeschlagen, meldet den Fehler und setzt die normale Verarbeitung des Tool-Ergebnisses fort.

Tool-Aufrufe aus dem Codemodus

Wenn ein Modell im Codemodus ein Tool aus JavaScript aufruft, gelten Hook-Entscheidungen für diesen verschachtelten Aufruf. PreToolUse kann das Tool stoppen, bevor es ausgeführt wird, oder seine Eingabe umschreiben. Eine blockierende PostToolUse-Entscheidung kann die Nebenwirkungen des Tools nicht rückgängig machen, aber sie kann verhindern, dass das ursprüngliche Ergebnis das laufende Skript erreicht.

Hook-Ergebnis Was der Codemodus sieht
PreToolUse blockiert Das Tool-Promise wird abgelehnt, bevor das Tool ausgeführt wird.
PreToolUse gibt updatedInput zurück Das Tool wird mit der umgeschriebenen Eingabe ausgeführt und das Promise mit diesem Ergebnis aufgelöst.
PostToolUse gibt decision: "block" zurück oder wird mit Code 2 beendet Das Tool wird ausgeführt, anschließend wird das Promise mit dem Hook-Grund abgelehnt.
PostToolUse gibt continue: false zurück Codex verwendet das Hook-Feedback als für das Modell sichtbares Ergebnis, lehnt das verschachtelte Tool-Promise jedoch nicht ab.

PreCompact

PreCompact wird ausgeführt, bevor Codex den Chat komprimiert. matcher wird auf trigger angewendet, dessen Werte manual und auto sind.

Zusätzliche Felder zu den allgemeinen Eingabefeldern:

Feld Typ Bedeutung
turn_id string Codex-spezifische Erweiterung. ID des aktiven Codex-Turns
trigger string Auslöser der Komprimierung: manual oder auto

Klartext auf stdout wird ignoriert.

JSON auf stdout unterstützt allgemeine Ausgabefelder. Wenn ein übereinstimmender PreCompact-Hook continue: false zurückgibt, hält Codex vor der Komprimierung an.

PostCompact

PostCompact wird ausgeführt, nachdem Codex den Chat komprimiert hat. matcher wird auf trigger angewendet, dessen Werte manual und auto sind.

Zusätzliche Felder zu den allgemeinen Eingabefeldern:

Feld Typ Bedeutung
turn_id string Codex-spezifische Erweiterung. ID des aktiven Codex-Turns
trigger string Auslöser der Komprimierung: manual oder auto

Klartext auf stdout wird ignoriert.

JSON auf stdout unterstützt allgemeine Ausgabefelder. Wenn ein übereinstimmender PostCompact-Hook continue: false zurückgibt, hält Codex nach der Komprimierung an.

UserPromptSubmit

matcher wird derzeit für dieses Ereignis nicht verwendet.

Zusätzliche Felder zu den allgemeinen Eingabefeldern:

Feld Typ Bedeutung
turn_id string Codex-spezifische Erweiterung. ID des aktiven Codex-Turns
prompt string Benutzer-Prompt, der gleich gesendet wird

Klartext auf stdout wird als zusätzlicher Entwicklerkontext hinzugefügt.

JSON auf stdout unterstützt allgemeine Ausgabefelder und diese Hook-spezifische Struktur:

{
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "additionalContext": "Ask for a clearer reproduction before editing files."
  }
}

Dieser additionalContext-Text wird als zusätzlicher Entwicklerkontext hinzugefügt.

Um den Prompt zu blockieren, geben Sie Folgendes zurück:

{
  "decision": "block",
  "reason": "Ask for confirmation before doing that."
}

Sie können auch den Exit-Code 2 verwenden und den Grund für die Blockierung in stderr schreiben.

SubagentStop

matcher wird für dieses Ereignis auf agent_type angewendet.

Felder zusätzlich zu den allgemeinen Eingabefeldern:

Feld Typ Bedeutung
turn_id string Codex-spezifische Erweiterung. ID des aktiven Codex-Turns
agent_id string Kennung des Subagenten
agent_type string Typ oder Profil des Subagenten
agent_transcript_path string | null Pfad zur Transkriptdatei des Subagenten, sofern vorhanden
stop_hook_active boolean Gibt an, ob dieser Subagent bereits fortgesetzt wurde
last_assistant_message string | null Neueste Assistentennachricht des Subagenten, sofern verfügbar

SubagentStop erwartet beim Beenden mit 0 JSON auf stdout. Eine Klartextausgabe ist für dieses Ereignis ungültig.

JSON auf stdout unterstützt allgemeine Ausgabefelder. Um Codex anzuweisen, den Subagenten-Ablauf fortzusetzen, geben Sie Folgendes zurück:

{
  "decision": "block",
  "reason": "Run one more focused pass inside the subagent."
}

Sie können auch den Exit-Code 2 verwenden und den Grund für die Fortsetzung in stderr schreiben.

Wenn ein übereinstimmender SubagentStop-Hook continue: false zurückgibt, hat dies Vorrang vor Fortsetzungsentscheidungen anderer übereinstimmender SubagentStop- Hooks.

Stop

matcher wird derzeit für dieses Ereignis nicht verwendet.

Felder zusätzlich zu den allgemeinen Eingabefeldern:

Feld Typ Bedeutung
turn_id string Codex-spezifische Erweiterung. ID des aktiven Codex-Turns
stop_hook_active boolean Gibt an, ob dieser Turn bereits durch Stop fortgesetzt wurde
last_assistant_message string | null Text der neuesten Assistentennachricht, sofern verfügbar

Stop erwartet beim Beenden mit 0 JSON auf stdout. Eine Klartextausgabe ist für dieses Ereignis ungültig.

JSON auf stdout unterstützt allgemeine Ausgabefelder. Damit Codex fortfährt, geben Sie Folgendes zurück:

{
  "decision": "block",
  "reason": "Run one more pass over the failing tests."
}

Sie können auch den Exit-Code 2 verwenden und den Grund für die Fortsetzung in stderr schreiben.

Bei diesem Ereignis lehnt decision: "block" den Turn nicht ab. Stattdessen wird Codex angewiesen, fortzufahren, und automatisch ein neuer Fortsetzungs-Prompt erstellt, der als neuer Benutzer-Prompt fungiert und Ihren reason als Prompt-Text verwendet.

Wenn ein übereinstimmender Stop-Hook continue: false zurückgibt, hat dies Vorrang vor Fortsetzungsentscheidungen anderer übereinstimmender Stop-Hooks.

Schemas

Wenn Sie das exakte aktuelle Übertragungsformat benötigen, finden Sie die generierten Schemas im Codex GitHub-Repository.

Klartext-Aliasse

  • string | null