Codex exec --json event cheatsheet
codex exec --json writes one JSON object per line (JSONL) to stdout. Each line is a top-level thread event with a type field.
codex exec --json writes one JSON object per line (JSONL) to stdout. Each
line is a top-level thread event with a type field.
Below: required + commonly emitted fields for every line type plus a
full-line example for each shape that can be emitted. Fields noted as
optional may be omitted (or null) depending on Codex version and lifecycle.
Unknown fields may appear; ignore what you don’t use.
Top-level event lines (non-item)
thread.started
Fields:
typethread_id
Example:
{"type":"thread.started","thread_id":"0199a213-81c0-7800-8aa1-bbab2a035a53"}
turn.started
Fields:
type
Example:
{"type":"turn.started"}
turn.completed
Fields:
typeusage.input_tokensusage.cached_input_tokensusage.output_tokens
Example:
{"type":"turn.completed","usage":{"input_tokens":24763,"cached_input_tokens":24448,"output_tokens":122}}
turn.failed
Fields:
typeerror.message
Example:
{"type":"turn.failed","error":{"message":"model response stream ended unexpectedly"}}
error
Fields:
typemessage
Example:
{"type":"error","message":"stream error: broken pipe"}
Note: Codex may emit transient reconnect notices as type="error" with messages
like "Reconnecting... 1/5" while it retries a dropped stream. Treat those as
non-fatal progress updates (the turn continues).
Item event lines (item.*)
Every item line includes:
type(item.started,item.updated, oritem.completed)item.iditem.type- fields for the specific
item.typebelow
item.id is stable for the item; updates/completion reuse the same id.
agent_message (only item.completed)
Fields:
item.text
Example:
{"type":"item.completed","item":{"id":"item_3","type":"agent_message","text":"Done. I updated the docs and added examples."}}
reasoning (only item.completed, if enabled)
Fields:
item.text
Example:
{"type":"item.completed","item":{"id":"item_0","type":"reasoning","text":"**Scanning docs for exec JSON schema**"}}
command_execution (item.started and item.completed)
Fields:
item.commanditem.aggregated_outputitem.exit_code(null or omitted until completion)item.status(in_progress,completed,failed)
Example (started):
{"type":"item.started","item":{"id":"item_1","type":"command_execution","command":"bash -lc ls","aggregated_output":"","exit_code":null,"status":"in_progress"}}
Example (completed, success):
{"type":"item.completed","item":{"id":"item_1","type":"command_execution","command":"bash -lc ls","aggregated_output":"docs\nsrc\n","exit_code":0,"status":"completed"}}
Example (completed, failure):
{"type":"item.completed","item":{"id":"item_2","type":"command_execution","command":"bash -lc false","aggregated_output":"","exit_code":1,"status":"failed"}}
Note: aggregated_output is truncated to 64 KiB; truncated output ends with
\n...(truncated).
file_change (only item.completed)
Fields:
item.changes[].pathitem.changes[].kind(add,delete,update)item.status(completed,failed)
Example:
{"type":"item.completed","item":{"id":"item_4","type":"file_change","changes":[{"path":"docs/exec-json-cheatsheet.md","kind":"add"},{"path":"docs/exec.md","kind":"update"}],"status":"completed"}}
mcp_tool_call (item.started and item.completed)
Fields:
item.serveritem.toolitem.arguments(JSON value; defaults tonullif absent)item.result(object ornull; may be omitted)item.result.content(array of MCP content blocks)item.result.structured_content(JSON value ornull)item.error(object ornull; may be omitted)item.error.message(iferroris present)item.status(in_progress,completed,failed)
Example (started):
{"type":"item.started","item":{"id":"item_5","type":"mcp_tool_call","server":"docs","tool":"search","arguments":{"q":"exec --json"},"result":null,"error":null,"status":"in_progress"}}
Example (completed, success):
{"type":"item.completed","item":{"id":"item_5","type":"mcp_tool_call","server":"docs","tool":"search","arguments":{"q":"exec --json"},"result":{"content":[{"type":"text","text":"Found 3 matches.","annotations":{"audience":["assistant"],"lastModified":"2025-01-01T00:00:00Z","priority":0.5}}],"structured_content":{"matches":3}},"error":null,"status":"completed"}}
Example (completed, failure):
{"type":"item.completed","item":{"id":"item_6","type":"mcp_tool_call","server":"docs","tool":"search","arguments":{"q":"exec --json"},"result":null,"error":{"message":"tool timeout"},"status":"failed"}}
web_search (only item.completed)
Fields:
item.query
Example:
{"type":"item.completed","item":{"id":"item_7","type":"web_search","query":"codex exec --json schema"}}
todo_list (item.started, item.updated, and item.completed)
Fields:
item.items[].textitem.items[].completed
Example (started):
{"type":"item.started","item":{"id":"item_8","type":"todo_list","items":[{"text":"Scan docs","completed":false},{"text":"Write cheatsheet","completed":false}]}}
Example (updated):
{"type":"item.updated","item":{"id":"item_8","type":"todo_list","items":[{"text":"Scan docs","completed":true},{"text":"Write cheatsheet","completed":false}]}}
Example (completed):
{"type":"item.completed","item":{"id":"item_8","type":"todo_list","items":[{"text":"Scan docs","completed":true},{"text":"Write cheatsheet","completed":true}]}}
error (non-fatal warning as an item; only item.completed)
Fields:
item.message
Example:
{"type":"item.completed","item":{"id":"item_9","type":"error","message":"command output truncated"}}
MCP content block shapes (mcp_tool_call.result.content)
result.content is an array of content blocks. Each block is one of the
types below; all optional fields may appear depending on the server.
Text content
Fields:
typetextannotations.audience(optional)annotations.lastModified(optional)annotations.priority(optional)
Example block:
{"type":"text","text":"Hello","annotations":{"audience":["assistant"],"lastModified":"2025-01-01T00:00:00Z","priority":0.5}}
Image content
Fields:
typedata(base64)mimeTypeannotations.*(same as above, optional)
Example block:
{"type":"image","data":"<base64>","mimeType":"image/png","annotations":{"audience":["assistant"]}}
Audio content
Fields:
typedata(base64)mimeTypeannotations.*(optional)
Example block:
{"type":"audio","data":"<base64>","mimeType":"audio/wav","annotations":{"audience":["assistant"]}}
Resource link
Fields:
typenameuridescription(optional)mimeType(optional)size(optional)title(optional)annotations.*(optional)
Example block:
{"type":"resource_link","name":"docs/exec.md","uri":"file:///repo/docs/exec.md","description":"Exec docs","mimeType":"text/markdown","size":1234,"title":"exec.md","annotations":{"audience":["assistant"]}}
Embedded resource
Fields:
typeresource(either text or blob contents)annotations.*(optional)
Example block (embedded text):
{"type":"resource","resource":{"uri":"file:///repo/README.md","text":"Hello","mimeType":"text/markdown"},"annotations":{"audience":["assistant"]}}
Example block (embedded blob):
{"type":"resource","resource":{"uri":"file:///repo/image.png","blob":"<base64>","mimeType":"image/png"},"annotations":{"audience":["assistant"]}}
Consumer considerations (rendering + success/failure)
Use this section to decide what to surface to end users vs. what to treat as machine-only metadata.
What to render for users
- Final answer: render
item.completedwhereitem.type = "agent_message"as the main response. - Progress updates (optional):
item.completedwithitem.type = "reasoning"can be shown as brief activity breadcrumbs (only if you want to expose reasoning summaries).item.started/item.completedwithitem.type = "command_execution"can be shown as “running command …” status lines without printing full output.item.completedwithitem.type = "file_change"can be rendered as a list of changed paths and kinds (add/update/delete).item.*withitem.type = "todo_list"can be shown as a progress checklist.
- Errors: render
type = "error"anditem.type = "error"as user-visible warnings or failures.
Fields you can safely skip for UX
command_execution.aggregated_outputis often noisy; many consumers omit or truncate it, and rely oncommand_execution.status+exit_codeinstead.mcp_tool_call.result.contentcan be large and tool-specific; consider showing only high-level status unless you know the tool’s schema.usagefields (turn.completed.usage.*) are typically telemetry-only.
Success and failure signals
- Turn success:
type = "turn.completed"indicates overall success. - Turn failure:
type = "turn.failed"witherror.messageindicates failure. - Item success/failure: use
item.statuson the item payload:command_execution.status:completed= success,failed= failure.file_change.status:completed= patch applied,failed= patch failed.mcp_tool_call.status:completed= tool succeeded,failed= tool failed.
- Fatal stream errors:
type = "error"means the JSONL stream itself hit an unrecoverable error (except transient"Reconnecting... X/Y"notices, which are non-fatal).
Suggested minimal rendering
If you want a compact UI, the following is usually enough:
- Thread/turn lifecycle:
thread.started,turn.started,turn.completedorturn.failed - Final answer:
item.completedwithitem.type = "agent_message" - Optional progress:
item.started/item.completedforcommand_executionandfile_change
Optional/conditional emission notes
turn.failedonly appears on failure; otherwiseturn.completedis emitted.reasoningitems only appear when reasoning summaries are enabled.todo_listitems only appear when the plan tool is active; they are the primary source ofitem.updated.file_changeandweb_searchitems are emitted only asitem.completedin the currentcodex exec --jsonstream.