Metadata-Version: 2.4
Name: openinference-instrumentation-codex
Version: 0.3.1
Summary: OpenInference instrumentation for Codex CLI/SDK telemetry
Author: OpenInference
License: Apache-2.0
License-File: LICENSE
Keywords: codex,openinference,opentelemetry,tracing
Requires-Python: <3.14,>=3.10
Requires-Dist: openinference-semantic-conventions>=0.1.0
Requires-Dist: opentelemetry-api>=1.25.0
Requires-Dist: opentelemetry-instrumentation>=0.46b0
Provides-Extra: otlp
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.25.0; extra == 'otlp'
Requires-Dist: opentelemetry-sdk>=1.25.0; extra == 'otlp'
Provides-Extra: test
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.25.0; extra == 'test'
Requires-Dist: opentelemetry-sdk>=1.25.0; extra == 'test'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
Requires-Dist: pytest>=8.0.0; extra == 'test'
Requires-Dist: ruff>=0.5.0; extra == 'test'
Description-Content-Type: text/markdown

# openinference-instrumentation-codex

- OpenInference instrumentation for Codex event streams
- OpenInference instrumentation for persisted local sessions

## Contents

- [Dependencies](#dependencies)
- [Modes](#modes)
- [Install](#install)
- [Shared Phoenix Setup](#shared-phoenix-setup)
- [CLI JSONL Proxy Quickstart](#cli-jsonl-proxy-quickstart)
- [Local JSONL forwarder Quickstart](#local-jsonl-forwarder-quickstart)
- [Library Surface](#library-surface)
- [Config](#config)
- [CodexOps Integration](#codexops-integration)
- [Development](#development)
- [Project Docs](#project-docs)

## Dependencies

| Dependency | Used by | Notes |
| --- | --- | --- |
| Python `>=3.10,<3.14` | Package runtime and tests | Declared in `pyproject.toml` |
| `uv` | Local dependency sync, test runs, and package builds | CI uses `astral-sh/setup-uv` |
| Docker-compatible runtime with Compose | Live Phoenix smoke and compose e2e | Use `docker compose`; the parent root Makefile can fall back to `docker-compose` |
| Codex CLI | Live CLI JSONL proxy smoke | Required only for live Codex-backed smoke flows |

## Modes

| Mode | Command | Root trace |
| --- | --- | --- |
| CLI JSONL proxy | `codex-otel-proxy --transport cli-jsonl` | one `codex.turn` per observed turn |
| Local JSONL forwarder | `codex-jsonl-forwarder --codex-home ~/.codex` | one `codex.turn` trace per persisted turn |

## Install

| Use case | Command |
| --- | --- |
| Base package | `pip install openinference-instrumentation-codex` |
| OTLP export support | `pip install "openinference-instrumentation-codex[otlp]"` |
| Local development | `uv sync --extra test` |

## Shared Phoenix Setup

- Starts a fresh Docker Phoenix container.
- Starts the repo-owned background JSONL forwarder.
- Targets persisted Codex sessions from `~/.codex` by default.

```bash
make phoenix-jsonl-start
```

- Phoenix: `localhost:6006`
- Container: `codex-phoenix`
- Project: `codex-local-jsonl-forwarder`
- State: cleared on `make phoenix-jsonl-start`
- Runtime state: `.run/codex-jsonl-forwarder-state.json`
- Runtime log: `.run/codex-jsonl-forwarder.log`
- Runtime pid: `.run/codex-jsonl-forwarder.pid`

### Useful Targets

| Target | Purpose |
| --- | --- |
| `make phoenix-jsonl-start` | Restart Phoenix and start a fresh JSONL forwarder watcher |
| `make phoenix-jsonl-stop` | Stop the repo-started forwarder and Phoenix container |
| `make phoenix-jsonl-status` | Check Phoenix and the repo-started forwarder |
| `make phoenix-start` / `make phoenix-stop` | Manage only the Phoenix container |
| `make jsonl-forwarder-start` / `make jsonl-forwarder-stop` | Manage only the local JSONL forwarder |

### Overrides

```bash
make phoenix-jsonl-start \
  JSONL_CODEX_HOME=/Users/justin.law/.codex \
  JSONL_PROJECT=codex-local-jsonl-forwarder
```

### Manual Setup

```bash
docker run -p 6006:6006 arizephoenix/phoenix:version-15.6.0
pip install "openinference-instrumentation-codex[otlp]"

export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:6006/v1/traces
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
export OTEL_RESOURCE_ATTRIBUTES='openinference.project.name=codex-local'

export OPENINFERENCE_CODEX_CAPTURE_INPUTS=true
export OPENINFERENCE_CODEX_CAPTURE_OUTPUTS=true
export OPENINFERENCE_CODEX_CAPTURE_TOOL_OUTPUTS=true
```

## CLI JSONL Proxy Quickstart

- Use when the caller already runs `codex exec --json`.
- Emits one `codex.turn` trace per observed turn.

```bash
codex exec --json "inspect the repo" \
  | codex-otel-proxy --transport cli-jsonl
```

### Caller Metadata

```bash
codex-otel-proxy \
  --transport cli-jsonl \
  --root-attribute codexops.investigation.name=investigation-otel \
  --root-attribute codexops.job.name=investigation-otel-job
```

- Root: one `codex.turn`
- Span kind: `LLM`
- Children: tool, file-change, MCP, and message spans
- Grouping: `session.id` / `codex.thread.id`
- Model fallback: `CODEX_MODEL`
- Cost mapping: `llm.model_name` uses the closest Phoenix cost-model name
- Original model: `codex.model.original`
- Selected cost model: `codex.model.cost_model`
- Parent context: `TRACEPARENT` and `TRACESTATE`
- Diagram: [docs/DIAGRAM.md](docs/DIAGRAM.md)

### Useful Flags

| Flag | Purpose |
| --- | --- |
| `--input-file PATH` | Read Codex JSONL events from a file instead of stdin |
| `--prompt-file PATH` | Attach the original prompt as root span input when input capture is enabled |
| `--exit-status-file PATH` | Mark the turn root as error when the recorded Codex process exit status is nonzero |
| `--no-forward` | Observe the event stream without forwarding lines to stdout |
| `--root-attribute KEY=VALUE` | Attach caller metadata, repeatable |
| `--transport cli-jsonl` | Select the only supported transport in this package version |

## Local JSONL forwarder Quickstart

- Use for ordinary local `codex` sessions.
- Does not change how the user launches Codex.

```bash
codex-jsonl-forwarder --codex-home ~/.codex
```

- Source: persisted interactive-session JSONL under `~/.codex/sessions/`
- Startup: backfills archived sessions
- Live safety: buffers likely active unterminated sessions
- Polling export: emits completed turns as soon as their turn terminal record is observed
- Shutdown export: flushes remaining buffered sessions
- Root: one `codex.turn`
- Span kind: `LLM`
- Children: message, reasoning, tool, and token event spans
- Partial turns: labeled during shutdown when no turn terminal exists
- Rich local Phoenix view: input, assistant output, and tool output enabled when capture env vars are unset
- Model fallback: JSONL metadata, then `OPENINFERENCE_CODEX_MODEL` or `CODEX_MODEL`
- Cost mapping: `llm.model_name` uses the closest Phoenix cost-model name
- Token attributes: `llm.token_count.prompt`, `llm.token_count.completion`, `llm.token_count.total`
- Cache attribute: `llm.token_count.prompt_details.cache_read`
- Original model: `codex.model.original`
- Selected cost model: `codex.model.cost_model`
- Reasoning text: unavailable when Codex stores only encrypted content
- Diagram: [docs/DIAGRAM.md](docs/DIAGRAM.md)

### Session File Discovery

- `--codex-home PATH` selects the Codex home; the default is `~/.codex`.
- The forwarder reads session files only from `PATH/sessions/**/*.jsonl`, recursively.
- It does not read shell history, logs, state files, or arbitrary JSONL outside that tree.
- State path flag: `--state-path`
- State default with `XDG_STATE_HOME`: `$XDG_STATE_HOME/openinference/codex-jsonl-forwarder/state.json`
- State default without `XDG_STATE_HOME`: `~/.local/state/openinference/codex-jsonl-forwarder/state.json`

### Useful Flags

```bash
codex-jsonl-forwarder \
  --codex-home ~/.codex \
  --state-path ~/.local/state/openinference/codex-jsonl-forwarder/state.json \
  --poll-interval 1 \
  --turn-idle-timeout 30 \
  --backfill-active-grace 300 \
  --health-port 8765
```

## Library Surface

| Surface | Purpose |
| --- | --- |
| `CodexCliJsonlAdapter` | Normalize `codex exec --json` events |
| `CodexCliInstrumentor` | Fallback subprocess wrapper for `codex exec` calls |
| `CodexTraceBuilder` | Build `codex.turn` trace trees from CLI events |
| `CodexTurnExporter` | Export one persisted local turn as a root `codex.turn` trace |
| `CodexSpanProcessor` | Fallback span processor for SDK-produced spans |
| `CodexInstrumentor` | Fallback SDK instrumentation |
| `instrument_codex` | Convenience wrapper around fallback SDK instrumentation |
| `TurnStarted`, `TurnCompleted`, `ItemStarted`, `ItemDelta`, `ItemCompleted`, `UsageUpdated` | Normalized event model used by adapters and tests |

## Config

- Base package capture defaults are opt-in.
- Local JSONL forwarder capture defaults are optimized for local Phoenix inspection.

| Env var | Default | Meaning |
| --- | ---: | --- |
| `OPENINFERENCE_CODEX_ENABLED` | `true` | Enable instrumentation |
| `OPENINFERENCE_CODEX_CAPTURE_INPUTS` | `false` | Capture prompt or user-message content |
| `OPENINFERENCE_CODEX_CAPTURE_OUTPUTS` | `false` | Capture assistant and reasoning-summary content |
| `OPENINFERENCE_CODEX_CAPTURE_TOOL_OUTPUTS` | `false` | Capture tool result content |
| `OPENINFERENCE_CODEX_REDACT_INPUTS` | `true` | Redact sensitive input patterns |
| `OPENINFERENCE_CODEX_MAX_ATTRIBUTE_LENGTH` | `4096` | Truncate serialized attributes |
| `OPENINFERENCE_CODEX_PRESERVE_ORIGINAL_ATTRIBUTES` | `true` | Preserve source attrs under `codex.original.*` |
| `OPENINFERENCE_CODEX_MODEL` | unset | Override model metadata when local forwarder backfills have no JSONL model |
| `OPENINFERENCE_CODEX_PROVIDER` | unset | Override `llm.provider` |
| `OPENINFERENCE_CODEX_DEBUG` | `false` | Enable instrumentation debug behavior |

- Input redaction applies to prompts, invocation parameters, and preserved original input attributes.
- Output capture and tool-result capture are separate from input redaction.
- Enable output and tool-result capture only for trusted sinks.
- `codex-jsonl-forwarder` treats unset capture env vars as enabled.
- Set any `OPENINFERENCE_CODEX_CAPTURE_*` env var to `false` to opt out for a local forwarder run.

- `OPENINFERENCE_CODEX_CAPTURE_RAW_RESPONSE_EVENTS` is not consumed by this package version.
- That env var is retained as a CodexOps root compatibility knob.

## CodexOps Integration

- CodexOps may consume a vendored wheel.
- CodexOps may consume the `OPENINFERENCE_CODEX_VERSION` image fallback.
- Verify `containers/codex-job/Dockerfile` before documenting deployed trace contracts.
- Verify any vendored wheel before documenting deployed trace contracts.
- Verify the built image before documenting deployed trace contracts.

## Development

| Command | Purpose |
| --- | --- |
| `make setup` | Sync local development dependencies |
| `make lint` | Lint the repo |
| `make test` | Run the Python test suite |
| `make test-unit` | Run non-integration Python tests |
| `make test-integration` | Run tests marked `integration` |
| `make test-jsonl-forwarder-phoenix` | Run the Phoenix-backed JSONL forwarder integration against `PHOENIX_BASE_URL` |
| `make compose-e2e` | Build the current wheel, install it with `[otlp,test]`, run wheel e2e coverage, and run the live Phoenix smoke |
| `make build` | Build source and wheel distributions |
| `make flight-check` | Standard local full check: setup, lint, tests, build, and compose e2e |

- Compose smoke host port: `6007`
- Override: `COMPOSE_PHOENIX_PORT`
- Reason: avoid collision with the local JSONL Phoenix viewer on `6006`

## Project Docs

| Doc | Purpose |
| --- | --- |
| [docs/DIAGRAM.md](docs/DIAGRAM.md) | System and trace boundary diagrams |
| [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) | Contribution and validation flow |
| [docs/SECURITY.md](docs/SECURITY.md) | Security scope and vulnerability reporting |
| [docs/CODE_OF_CONDUCT.md](docs/CODE_OF_CONDUCT.md) | Collaboration standards |
| [docs/CONTACT.md](docs/CONTACT.md) | Private maintainer contact |
| [AGENTS.md](AGENTS.md) | Repo-specific agent guidance |
