# lumen for Codex
Hook lumen into [OpenAI Codex](https://github.com/openai/codex)'s `Stop`
event. Codex finishes a turn → lumen pops up on the uncommitted diff
→ you annotate → press `s` → annotations are injected as the next user
message and Codex continues in the same turn.
```
agent stops → lumen opens → review → `s`
→ Codex sees your annotations as if you typed them → agent fixes them
```
**The agent never knows lumen exists.** It just receives feedback that
looks exactly like a user message.
## How it works
Codex `Stop` hooks can return:
```json
{ "decision": "block", "reason": "<text>" }
```
…which makes Codex *not* stop and instead inject `reason` as the next
user message. `lumen diff --hook codex-stop` handles this protocol:
| No uncommitted changes | `{}` (TUI skipped entirely) | Turn ends normally |
| User pressed `s`, sent feedback | `{"decision":"block","reason":"<annotations>"}` | Continues with text |
| User pressed `q`, dismissed | `{}` | Turn ends normally |
## Install
Enable Codex hooks (experimental, behind a feature flag):
`~/.codex/config.toml` (or repo-local `.codex/config.toml`):
```toml
[features]
hooks = true
```
Register the hook — either copy [`hooks/hooks.json`](./hooks/hooks.json)
to `~/.codex/hooks.json`, or paste this:
```json
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "lumen diff --hook codex-stop",
"timeout": 345600
}
]
}
]
}
}
```
Restart Codex. Done.
### Notes
- Use an absolute path to `lumen` (e.g. `/opt/homebrew/bin/lumen`) if
you launch Codex Desktop — app-launched processes don't always
inherit your shell `PATH`.
- `timeout` is in seconds; the large value lets you take your time
reviewing without Codex killing the hook.
- Codex hooks are currently disabled on Windows in the official docs.
## Test it without Codex
The hook contract is `stdin = event JSON, stdout = response JSON`, so
you can drive it from a shell:
```bash
# Inside a repo with uncommitted changes:
- TUI opens (on `/dev/tty`, since stdout is captured).
- Annotate, press `s` → `Enter`.
- Stdout receives `{"decision":"block","reason":"# ...\n\n**file** line N\n\n...comment..."}`.
- Press `q` instead → stdout receives `{}`.
In a clean working tree the same command returns `{}` instantly without
opening the TUI.