Share a masked, read-only live view of a local Codex thread. The host continues using Codex normally while codex-share tails its rollout JSONL and serves an authenticated viewer.
Install the Rust toolchain and one tunnel provider:
- Cloudflare Tunnel (
cloudflared) for a no-account Quick Tunnel. - ngrok (
ngrok) if you have configured an authtoken.
Confirm that the provider is available before starting a share:
cargo run --release -- --check-tunnelsThen create a public share. This opens the interactive thread picker:
cargo run --release -- --tunnel cloudflareOr use ngrok:
cargo run --release -- --tunnel ngrokSelect a recent thread and codex-share prints an authenticated public URL. The share ends when the process exits.
Conversation-only is the default. Grant only the additional information a viewer needs:
| Permission | Viewer can see |
|---|---|
conversation |
User and assistant messages, plus a coarse working/idle indicator. |
activity |
Conversation plus tool names and started/completed state. |
diffs |
Conversation plus masked file paths and patch content. |
activity-diffs |
Conversation, activity, and diffs. |
cargo run --release -- --tunnel cloudflare --permission activity
cargo run --release -- --tunnel cloudflare --permission diffs
cargo run --release -- --tunnel cloudflare --permission activity-diffsNo permission exposes command output, tool arguments, environment/configuration, internal instructions, or reasoning. Diffs are capped at 100 files and 256 KiB per event.
Run without a tunnel for a local-only share:
cargo run --releaseUse an explicit rollout file when scripting or sharing a known thread:
cargo run --release -- --file ~/.codex/sessions/2026/10/02/rollout-....jsonlSkip the picker and share the newest session:
cargo run --release -- --latestShow more than the default 12 recent threads:
cargo run --release -- --recent 20The viewer opens on the newest events, follows them while the viewer remains at the bottom, progressively loads older retained events near the top, and shows an in-thread working state during active turns. The retained window defaults to 2,000 normalized events and can be changed with --history.
Add literal values that should always be masked:
cargo run --release -- --redact customer-name --redact internal.example.com
CODEX_SHARE_REDACT=customer-name,internal.example.com cargo run --releaseRaw rollout records are never sent to the browser. The local process can project only:
- user and assistant message text;
- tool name plus started/completed state, when activity is granted;
- structured file paths and patch content, when diffs are granted;
- coarse working/idle state for the in-thread live indicator.
The default conversation grant exposes messages plus that coarse turn state. It does not expose which tools are running. Internal instructions, reasoning records, environment/configuration, command arguments, command output, and unknown future record types are always dropped. Allowed message and diff text is then masked for home-directory paths, common token formats, secret assignments, URL credentials, and user-supplied literal values.
Permissions are enforced by the server for both the snapshot and live WebSocket stream. Each capability token is minted with its scope (cs1_c_…, cs1_ca_…, cs1_cd_…, or cs1_cad_…); changing that visible scope marker invalidates the token. No scope exposes command output, raw tool arguments, or reasoning. Diff scopes expose masked file paths and patch content, capped at 100 files and 256 KiB per event.
Share tokens have 192 bits of entropy, live in the URL path, are checked by the local server, and expire when the process exits. The server binds to 127.0.0.1:48123 by default.
This is defense in depth, not a guarantee that arbitrary prose contains no sensitive information. Review what the agent is discussing before sharing it.
