Runtime overview
Beacon supports Codex CLI runtime telemetry through local OTLP logs and one selective usage-bearing turn trace. Codex Desktop uses the same Codex OTLP configuration, and Beacon records its sessions ascodex_desktop and keeps them apart from codex_cli. A lightweight SessionStart hook records the local OS user for CLI token attribution, and a Stop hook records each turn’s final assistant reply, which Codex’s OTLP export does not carry.
Prerequisites
Before enabling Codex telemetry, make sure:- Codex CLI is installed and available as the
codexexecutable for the user or managed endpoint. - Codex Desktop is installed if you want Desktop telemetry.
- Codex CLI 0.149.1 or newer is used for verified turn-trace token attribution.
beacon endpoint installhas run so the local collector, endpoint config, and runtime log path exist.- The install includes the
codexharness, either through the default harness list or an explicit--harness codexvalue. - Your team has reviewed content handling and destination access for prompt telemetry.
Collection path
Codex CLI exports local OpenTelemetry logs and traces to Beacon’s localhost collector. Codex Desktop exports the same Codex semantic telemetry when user-level~/.codex/config.toml enables OTLP. Beacon uses Codex semantic logs for session, prompt, approval, and tool-result events. For tokens it keeps only the completed session_task.turn span carrying thread.id, turn.id, model, and usage; hundreds of transport and internal spans remain suppressed. The CLI SessionStart hook writes a metadata-only session.context event. The CLI Stop hook writes the turn’s final reply from the payload’s last_assistant_message as an agent.message event, and nothing for a turn that ended without one. Neither hook reads the transcript. Inventory is written by the scheduled inventory job, not by this hook.
Use --include-codex-spans during install or repair only when you need every raw Codex span for troubleshooting. It is not required for token attribution.
Codex CLI or Desktop
Codex CLI 0.158 and newer run on the same app-server as the desktop app, so both report the service namecodex-app-server, and that name alone does not say which one a session ran in. Beacon goes by the originator Codex reports instead: Codex_Desktop is recorded as codex_desktop, and codex-tui (the terminal), codex_exec (codex exec), codex_vscode (the IDE extension) and any other value as codex_cli. Codex’s log events and its legacy token metric carry the originator. The usage span does not, so it takes the surface its conversation’s logs named; if it reaches the collector before those logs, Beacon waits up to ten seconds for them before writing it, and a usage span whose logs never arrive is recorded as codex_cli. beacon endpoint codex sync names each rollout the same way, from the originator in its session_meta line (Codex Desktop for the desktop app). Token reports still drop usage a Desktop session reports twice, through a turn span and a legacy metric or through live capture and codex sync. Events already in the log keep the name they were written with, so CLI 0.158+ sessions recorded before Beacon v1.3.48 still show as codex_desktop, and Desktop rollouts codex sync read before it went by the originator still show as codex_cli.
Session-file recovery
Beacon can also recover Codex CLI activity from Codex’s local rollout files with an explicit command:$CODEX_HOME/sessions when CODEX_HOME is nonempty, otherwise ~/.codex/sessions and appends mapped events to the local runtime log with harness.collection_method=poll. It is useful for historical sessions or sessions that ran before OTLP was configured. The sync path is not part of hook execution and cannot approve, deny, or delay tool calls.
Use beacon endpoint codex sync --print to preview mapped events without writing the runtime log or advancing the cursor. Use beacon endpoint codex status to see which session files are present and how far Beacon has read each one.
Codex rollout files can contain prompts, assistant responses, tool inputs, command output, and code. Sync is therefore explicit: Beacon does not read ~/.codex/sessions during normal Codex hook execution, and it never reads ~/.codex/auth.json.
Install, hook install, discovery, inventory, session status, sync, handoff, and beacon mcp connect honor Codex’s literal CODEX_HOME directory: it must exist, and relative paths resolve from the current working directory. Unlike shell syntax, ~ and environment-variable references in the value are not expanded. Project-level .codex files are not affected. Pass --codex-dir <path> to select a session store explicitly.
The scheduled inventory job starts without your shell’s environment, so a per-user beacon endpoint install or repair writes the CODEX_HOME it resolved into the job’s launchd or systemd definition. If you change CODEX_HOME later, run beacon endpoint repair from a shell that has the new value. System-mode installs do not record it.
Token usage and cost
beacon endpoint install configures Codex’s log and trace exporters in $CODEX_HOME/config.toml (default ~/.codex/config.toml). Beacon normalizes the completed turn span into the same canonical gen_ai.usage fields used for Claude Code: uncached input_tokens, output_tokens, cache_read.input_tokens, cache_creation.input_tokens, and reasoning.output_tokens. Codex’s input count includes both cache reads and cache writes, so Beacon subtracts both before recording uncached input.
The span directly supplies the model and session.id (from Codex thread.id). Beacon joins the matching SessionStart context event to attribute local reports by OS user. The runtime log therefore contains both the token event and its session identity context, and both forward through configured JSONL shippers.
Codex still does not emit a cost signal on this span, so gen_ai.usage.cost_usd remains empty. Beacon never puts locally estimated pricing into that runtime-reported field.
Legacy codex.turn.token_usage metrics in older logs remain reportable, but they have no session or user identity. New Beacon-managed configuration uses traces as the single live token source so spans and metrics cannot double-count the same turn.
See How token attribution works for the cross-runtime model.
Rollout JSONL recovery behavior
The Codex session sync reads complete JSONL lines and checkpoints by file path and line number. It maps session metadata, prompts, assistant messages, custom tool calls and outputs, task completion, andtoken_usage_record rows. Token input is normalized into Beacon’s disjoint gen_ai.usage fields by subtracting cache reads and cache writes from Codex’s inclusive input count.
CI support
Beacon can also capture Codex telemetry in CI withbeacon ci start and beacon ci finish. In GitHub Actions, the Beacon action creates a temporary CODEX_HOME with Codex OTLP settings and exposes it as steps.<id>.outputs.codex-home for actions such as openai/codex-action.
Discovery and status
Beacon detects Codex CLI through thecodex executable and $CODEX_HOME/config.toml (default ~/.codex/config.toml). Codex Desktop shares the same user-level configuration file, so Desktop events appear once the app emits OTLP to Beacon’s local collector. Use beacon endpoint discover or beacon endpoint status to confirm that Codex configuration is present.
Install or configuration support
beacon endpoint install writes Codex OTLP exporter tables to $CODEX_HOME/config.toml (default ~/.codex/config.toml).
beacon endpoint install --harness codex installs the required user-level
session context and assistant response hooks with the OTLP configuration. To refresh
them independently, run:
SessionStart) and assistant response (Stop) hooks to $CODEX_HOME/hooks.json (default ~/.codex/hooks.json) or project .codex/hooks.json, depending on --level. A successful user-level install prints:
/hooks in Codex to trust the Beacon hooks after installing or upgrading; until then Codex skips them, and the assistant reply reaches the log only through beacon endpoint codex sync.
Telemetry coverage
Deployment notes
For MDM deployments, use the signed and notarized macOS.pkg so endpoint events land in /var/log/beacon-agent/runtime.jsonl. The package installs the endpoint agent under /opt/beacon, creates system endpoint configuration, and loads the local collector LaunchDaemon.
If a system collector is running while the CLI is reading the default per-user log, beacon endpoint status and the local dashboard surface a runtime-log source warning so you can tell where OTLP events are being written.
Related
Supported agent harnesses
Return to the runtime support overview.
Agent harness integration model
See how Beacon discovers and configures supported runtimes.