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 vonconfig.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,SubagentStartoderStop - 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:
descriptionsind optionale Metadaten auf oberster Ebene für einehooks.json-Datei. Sie ändern nicht, welche Hooks ausgeführt werden.timeoutwird in Sekunden angegeben.- Wenn
timeoutnicht angegeben ist, verwendet Codex für die meisten Hooks600Sekunden.SessionEndverwendet standardmäßig1Sekunde und unterstützt bis zu3Sekunden.
statusMessageist optional.additionalContextLimitlegt fest, wie vieladditionalContextein 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.commandWindowsist eine optionale, ausschließlich für Windows vorgesehene Befehlsüberschreibung. Verwenden Sie in TOMLcommand_windowsodercommandWindows.- Die Option
asyncwird geparst, asynchrone Befehls-Hooks werden jedoch noch nicht unterstützt. - Derzeit werden nur
type: "command"-Handler ausgeführt.prompt- undagent-Handler werden geparst, aber übersprungen. - Befehle werden mit dem
cwdder 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 = falseVerwenden 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_dirwird unter macOS und Linux verwendet.windows_managed_dirwird unter Windows verwendet.- Codex verteilt die Skripte in
managed_dirnicht; 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 ausrequirements.tomlund 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_ROOTist eine Codex-spezifische Erweiterung, die auf das Stammverzeichnis des installierten Plugins verweist.PLUGIN_DATAist eine Codex-spezifische Erweiterung, die auf das beschreibbare Datenverzeichnis des Plugins verweist.- Codex legt außerdem
CLAUDE_PLUGIN_ROOTundCLAUDE_PLUGIN_DATAfest, 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|Writemcp__filesystem__read_filemcp__filesystem__.*startup|resume|clear|compactmanual|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