Codex is the adapter with the most moving parts, because Codex has three front ends and Runi cannot reach them the same way. All three are observed identically: Codex writes a rollout log whichever front end started it, and Runi reads that. What differs is how the briefing gets in.
The three front ends#
| Front end | Observed | Briefed |
|---|---|---|
| CLI, started through the Runi wrapper | Yes | Pushed, as a per-session profile, before the first turn |
| Codex Desktop | Yes | Pulled. The session asks, prompted by a rule block |
| Codex in VS Code | Yes | Pulled, the same as Desktop |
What Runi installs#
- A background rollout watcher that reads
~/.codex/sessions, so sessions from any front end are observed without launching anything through Runi. - An optional CLI wrapper at
~/.relay/relay-codex. - An MCP server entry in Codex's config, so any Codex session can ask Runi questions.
- A marked block in
~/.codex/AGENTS.md, which is Codex's global guidance file and not your repository's, asking new sessions to callruni_briefbefore reading the codebase andruni_team_statusbefore editing.
The CLI: push, and the good path#
Started through the wrapper, Codex gets the briefing the way Claude Code does. Handed over before it types a word:
$ ~/.relay/relay-codex "continue the retention parser work"
The wrapper runs Codex unmodified. It writes the briefing to a temporary
profile beside your Codex config, starts Codex against it, and deletes the
profile when you exit. Every flag you pass goes straight through, so anything
that worked with codex works here.
Afterwards Runi checks the session log to confirm Codex actually read the briefing, so a receipt that says delivered means delivered.
Tip
Alias it and forget it exists. Add
alias codex="$HOME/.relay/relay-codex" to your shell profile and
the good path becomes the default one. This is the highest-value thing a
Codex user can do with Runi.
Desktop and VS Code: pull, and why#
Runi does not launch those sessions, so nothing can hand them a packet. A hook
fired from a global path cannot know which repository a session belongs to
either. Instead Runi keeps a standing block in ~/.codex/AGENTS.md
telling every session to call runi_brief at the start. The result
enters the conversation through the tool, which beats a copied briefing.
Careful
Whether a given Codex build honours the global AGENTS.md is not yet
verified live. We would rather say that than imply a guarantee. The
receipt on each session tells you whether the brief was pulled. As a belt to
those braces, Settings → Agents → Copy block
gives you the same rules to paste into your repository's own
AGENTS.md.
Tool availability is not evidence of use. If the Runi tools are present in a Codex session but never called, check the guidance block is installed and start a fresh session.
Known limits#
- Runi cannot intercept a Codex edit the way the Claude Code and Cursor hooks can. Observation comes from the rollout log, so it lags by up to a few seconds.
- Pushed context, including a teammate's @Codex note from a task thread, is delivered only through the wrapper. A note queued mid-session arrives at the start of the next one.
- Only repositories your workspace tracks are published. Folders that are not clones must be mapped explicitly with
codexWatchPathsin~/.relay/config.json. - Context-window usage is not exposed by Codex, so Runi shows it as unknown instead of guessing.
Verify it#
$ runi doctor
…
ok codex watcher running, 1 live session(s), checked just now
ok adapter:codex ok (rollout-v2), last seen 4 min ago
Troubleshooting#
The detached watcher process is not alive. It reads the rollout log, and without it only wrapper-started CLI sessions are seen.
Open the Runi desktop app, which starts the watcher. If the app is open and the doctor still says this, disconnect and reconnect Codex in Settings → Agents.
Expected for Desktop and VS Code if the session never calls runi_brief. Nothing pushes to those front ends.
Three things, in order of effort: use the wrapper for work that matters; check the block in ~/.codex/AGENTS.md is present and start a new session; paste the same block into your repository's AGENTS.md.
The watcher maps a session to a repository by its path. A directory with no remote cannot be resolved to one.
Map it explicitly with codexWatchPaths in ~/.relay/config.json.