A lightweight Neovim integration for Codex built around the official codex app-server --listen and codex --remote workflow.
- Starts
codex app-server --listen ws://127.0.0.1:<port>inside Neovim - Starts
codex --remote ws://127.0.0.1:<proxy-port>in a side terminal - Proxies remote traffic through a local WebSocket relay owned by the plugin
- Logs raw transport events to
<project_root>/.codex/transport.jsonl - Stores session metadata in
<project_root>/.codex/session.json - Leaves a
transform_framehook for future context injection or protocol rewriting
This MVP is intentionally observation-first. It records and relays traffic, but does not mutate protocol payloads unless the user provides a custom hook.
Neovim plugin
├─ runtime/process_manager.lua
│ ├─ starts `codex app-server --listen`
│ └─ starts local WebSocket proxy
├─ terminal/*.lua
│ └─ opens `codex --remote` in a lightweight side terminal
└─ proxy/server.lua
├─ accepts `--remote` WebSocket connection
├─ dials upstream `app-server`
└─ logs raw frames to `.codex/transport.jsonl`
:Codex- start runtime if needed, then open or toggle the side terminal:CodexStop- stop the runtime:CodexRestart- restart the runtime:CodexStatus- show current runtime status:CodexLogs- open.codex/transport.jsonl
require("codex").setup({
terminal_cmd = "codex",
mappings = {
enabled = true,
toggle = "<leader>cx",
},
runtime = {
auto_start = false,
host = "127.0.0.1",
project_root = nil,
app_port = nil,
proxy_port = nil,
},
proxy = {
mode = "observe",
transform_frame = nil,
},
terminal = {
provider = "auto",
split_side = "right",
split_width_percentage = 0.30,
},
})By default, codex.nvim safely registers one normal-mode mapping:
<leader>cx- toggle Codex; first use starts the runtime and shows the terminal, later uses toggle visibility
If the key is already mapped by the user or declared through lazy.nvim, codex.nvim will skip creating it.
Disable or customize it like this:
require("codex").setup({
mappings = {
enabled = false,
-- toggle = "<leader>cx",
},
}).codex/transport.jsonlstores UTF-8 payloads directly; non-UTF8 payloads are base64 encoded.- The proxy currently treats file diff inspection as an editor-side concern. It does not ask Codex for a separate diff API.
transform_frameis reserved for future invasive context injection or request rewriting experiments.
- Detailed startup sequence and runtime data flow: docs/startup-sequence.md