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.
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:
- type
- thread_id
Example:
{"type":"thread.started","thread_id":"0199a213-81c0-7800-8aa1-bbab2a035a53"}
turn.started¶
Fields:
- type
Example:
{"type":"turn.started"}
turn.completed¶
Fields:
- type
- usage.input_tokens
- usage.cached_input_tokens
- usage.output_tokens
Example:
{"type":"turn.completed","usage":{"input_tokens":24763,"cached_input_tokens":24448,"output_tokens":122}}
turn.failed¶
Fields:
- type
- error.message
Example:
{"type":"turn.failed","error":{"message":"model response stream ended unexpectedly"}}
error¶
Fields:
- type
- message
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, or item.completed)
- item.id
- item.type
- fields for the specific item.type below
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.command
- item.aggregated_output
- item.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[].path
- item.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.server
- item.tool
- item.arguments (JSON value; defaults to null if absent)
- item.result (object or null; may be omitted)
- item.result.content (array of MCP content blocks)
- item.result.structured_content (JSON value or null)
- item.error (object or null; may be omitted)
- item.error.message (if error is 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[].text
- item.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:
- type
- text
- annotations.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:
- type
- data (base64)
- mimeType
- annotations.* (same as above, optional)
Example block:
{"type":"image","data":"<base64>","mimeType":"image/png","annotations":{"audience":["assistant"]}}
Audio content¶
Fields:
- type
- data (base64)
- mimeType
- annotations.* (optional)
Example block:
{"type":"audio","data":"<base64>","mimeType":"audio/wav","annotations":{"audience":["assistant"]}}
Resource link¶
Fields:
- type
- name
- uri
- description (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:
- type
- resource (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.completed or
turn.failed
- Final answer: item.completed with item.type = "agent_message"
- Optional progress: item.started / item.completed for command_execution
and file_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.