The connector hooks into Codex CLI’s event system and captures structured data from each session. This page documents what events are captured and how they map to Infinium traces.

Hook Events

The connector listens for these Codex CLI hook events:

EventWhen It FiresWhat’s Captured
SessionStartCodex CLI session begins (startup or resume)Session ID, model, working directory, source (startup/resume)
UserPromptSubmitUser sends a promptPrompt text
PreToolUseBefore a tool executes (Bash)Tool name, tool_input.command
PostToolUseAfter a tool completesSuccess/failure (tool_response is a boolean from Codex)
StopAssistant finishes respondingFinal assistant message, triggers trace send

Codex has no explicit SessionEnd event. The connector handles cleanup via Stop and a stale-session timer.

tool_response from Codex is a booleantrue for success, false for failure. The connector translates this into "Command succeeded" / "Command failed" output summaries. The actual command output isn’t available to hooks.

How Events Become Traces

Events are grouped into turns — each turn is one prompt-response cycle:

Turn 1:
  UserPromptSubmit  → "Fix the failing npm test"
  PreToolUse        → Bash("npm test")
  PostToolUse       → true                ← Command succeeded
  Stop              → "All tests passed after fixing..."

                    Trace sent to Infinium

Turn 2:
  UserPromptSubmit  → "Now add a regression test"
  PreToolUse        → Bash("touch test_auth.py")
  PostToolUse       → true
  PreToolUse        → Bash("git diff")
  PostToolUse       → true
  Stop              → "Regression test added..."

                    Trace sent to Infinium

Each Stop event triggers a trace send. Background workers do the aggregation + send so Codex CLI is never blocked.

Timestamps

Codex CLI does not include timestamps in hook events. The connector injects an ISO-8601 timestamp as each event arrives, so every event has a reliable ordering in the JSONL session file and the trace.

Trace Structure

Each trace sent to Infinium contains:

Top-Level Fields

FieldSourceExample
nameFirst user prompt (truncated to 30 chars)"Fix the failing npm test"
descriptionFirst user prompt (full)"Fix the failing npm test"
durationSession timing15.2 (seconds)
input_summaryFirst prompt"Fix the failing npm test"
output_summaryLast assistant message"All tests pass"

Execution Steps

Each trace includes an ordered list of steps:

Step TypeActionFields
User promptuser_promptdescription, input_preview, output_preview
Tool calltool_usedescription (e.g. "Tool: Bash"), input_preview (the command), output_preview, duration_ms
Tool errortool_use with errorerror.error_type = "ToolError", error.message = "Command failed", error.recoverable = true

Environment Context

Every trace includes environment metadata:

TagValue
modelCodex model (e.g. gpt-5-codex)
session_idCodex session identifier
working_directoryProject directory path
permission_modeCodex permission mode (e.g. workspace-write)
session_sourcestartup or resume
framework"codex-cli"

LLM Usage

On flush, the connector reads Codex’s session transcript (a JSONL file containing turn.completed entries) and attaches cumulative token usage to the trace:

FieldSource
prompt_tokensSum of usage.input_tokens across turn.completed entries
completion_tokensSum of usage.output_tokens
cached_input_tokensSum of usage.cached_input_tokens (preserved in custom_tags since the SDK has no dedicated field)
api_calls_countNumber of turn.completed entries
provider"openai"
modelFrom session events

For per-turn traces, the delta against the previous snapshot is sent so totals don’t double-count.

Error Tracking

Tool failures (PostToolUse with tool_response: false) are captured as structured errors:

FieldDescription
error_type"ToolError"
message"Command failed"
recoverabletrue

Data Truncation

To keep payloads manageable, the connector truncates:

  • Prompt text: First 200 characters (configurable via CONNECTOR_MAX_INPUT_PREVIEW)
  • Tool output preview: First 300 characters (configurable via CONNECTOR_MAX_OUTPUT_PREVIEW)
  • Payload size: Progressive truncation if the total payload exceeds ~950KB

Full data is never sent — only summaries that give Maestro enough context to evaluate quality.