openqodex 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/agents.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Agents
2
2
 
3
- OpenQodex runs from Claude Code, Cursor, Codex CLI and Cline. `openqodex init` installs it into each one it finds. Whichever agent asks for the review, the review itself runs in a reviewer process OpenQodex starts: Claude Code, on your Claude Code login, with no other key. Codex and Cursor are not used as reviewers yet (`security` says why); in Cursor, Codex and Cline the review works when Claude Code is installed too. Without it, `review` names the command with which the agent you are in reviews the change itself (see "Who reviews, by what is installed").
3
+ OpenQodex runs from Claude Code, Cursor, Codex CLI and Cline. `openqodex init` installs it into each one it finds. Whichever agent asks for the review, the review itself runs in a reviewer process OpenQodex starts: Claude Code or Codex, on your own login, with no other key. Cursor is not used as a reviewer (`security` says why); in Cursor and Cline the review works when Claude Code or Codex is installed too. Without either, `review` names the command with which the agent you are in reviews the change itself (see "Who reviews, by what is installed").
4
4
 
5
5
  ## Run init
6
6
 
@@ -46,22 +46,24 @@ The section goes into `CLAUDE.md` and `AGENTS.md` at the root of the repository,
46
46
  <!-- openqodex:end -->
47
47
  ```
48
48
 
49
- The two files show in `git status`, and `init` says to commit them. `init` writes neither file through a symbolic link. A section you edited is yours: a later `init` and `--uninstall` leave it as it is. `--uninstall` removes our untouched section, and deletes a file only when `init` created it and nothing else is in it. In project scope the same two files carry the instruction section instead, never both.
49
+ The two files show in `git status`, and `init` says to commit them. When git ignores one of them in this repository, `init` says so instead, since your team does not get it. `init` writes neither file through a symbolic link. A section you edited is yours: a later `init` and `--uninstall` leave it as it is. `--uninstall` removes our untouched section, and deletes a file only when `init` created it and nothing else is in it. In project scope the same two files carry the instruction section instead, never both.
50
50
 
51
51
  ## The review runs in its own reviewer process
52
52
 
53
- The skill tells the agent to run one command, `review`, wait for it, and show you the report exactly as printed. The agent does not review the change itself and starts no subagent. `review` starts a fresh Claude Code process with no memory of the agent's session, none of your settings or instruction files, and read, search and list tools only, inside a frozen copy of the change. The report says which reviewer ran; the tool writes that line, never the model.
53
+ The skill tells the agent to run one command, `review`, wait for it, and show you the report exactly as printed. The agent does not review the change itself and starts no subagent. `review` starts a fresh reviewer process with no memory of the agent's session, inside a frozen copy of the change. Claude Code starts with none of your settings or instruction files and read, search and list tools only. Codex starts in a read-only sandbox with none of your config or the repository's instruction files; it still loads your global `~/.codex/AGENTS.md`. The report says which reviewer ran; the tool writes that line, never the model.
54
54
 
55
55
  A review takes one to three minutes. Agents often stop a command after two minutes, so the skill tells the agent to allow up to ten minutes or run it in the background; `review` prints a line every 15 seconds while the reviewer works.
56
56
 
57
- The reviewer runs nothing: no tests, no scripts, no shell.
57
+ The reviewer edits nothing and runs none of the repository's code. Claude Code has no shell. Codex has a shell whose commands can read the copy of the change and the system folders, and cannot write or reach the network.
58
58
 
59
59
  ## Who reviews, by what is installed
60
60
 
61
61
  | Installed | What `review` gives you |
62
62
  |---|---|
63
63
  | Claude Code, logged in | A fresh Claude Code process that OpenQodex starts reviews the change. |
64
- | Only Codex or only Cursor (or Claude Code logged out) | "Full review unavailable", exit 2, and a fallback: run `review --agent` and the agent you are in follows the brief it prints, then `review --finalize`. That report says on its first line after the verdict "Reviewed by the coding agent you are using." |
64
+ | Codex, logged in, and no Claude Code (or Claude Code logged out) | A fresh Codex process that OpenQodex starts reviews the change. |
65
+ | Both, logged in | The agent you run `review` from reviews: Codex from Codex, Claude Code from Claude Code. From anywhere else, Claude Code. `--reviewer codex` or `reviewer: codex` in `~/.openqodex/config.yaml` picks Codex. |
66
+ | Only Cursor (or both logged out), or Codex inside Codex's own sandbox | "Full review unavailable", exit 2, and a fallback: run `review --agent` and the agent you are in follows the brief it prints, then `review --finalize`. That report says on its first line after the verdict "Reviewed by the coding agent you are using." |
65
67
  | None of them | "Full review unavailable", exit 2, and the scanner findings saved to a file as unchecked candidates, never as a review. The fallback line prints too, but no agent is there to follow it. |
66
68
 
67
69
  The skill tells the agent to follow the fallback when `review` prints it. The push hooks count a fallback review as reviewed, with one line naming who reviewed.
@@ -125,7 +127,7 @@ Codex runs a new hook only after you trust it. Open Codex, run `/hooks`, and tru
125
127
  | Skill | `~/.cursor/skills/openqodex/SKILL.md` | `.agents/skills/openqodex/SKILL.md` |
126
128
  | Rule | `.cursor/rules/openqodex.mdc` in the repository, excluded from git | `.cursor/rules/openqodex.mdc` |
127
129
 
128
- Cursor has no rule file in the home folder, so the rule always goes in the repository. In user scope, run `init` inside each repository where you want the rule. The rule applies to every chat, carries the instruction section, and tells Cursor to run `review` before any `git push`. The review itself needs Claude Code installed: `cursor-agent` cannot be held to reading only, so it is not a reviewer.
130
+ Cursor has no rule file in the home folder, so the rule always goes in the repository. In user scope, run `init` inside each repository where you want the rule. The rule applies to every chat, carries the instruction section, and tells Cursor to run `review` before any `git push`. The review itself needs Claude Code or Codex installed: `cursor-agent` cannot be held to reading only, so it is not a reviewer.
129
131
 
130
132
  OpenQodex writes no Cursor hook. The rule asks Cursor to review, but nothing stops a push from Cursor.
131
133
 
@@ -169,7 +171,7 @@ Before each push it runs `openqodex hook pre-push` through the launcher. For eac
169
171
 
170
172
  ## Inside a sandbox
171
173
 
172
- Some agents run commands in a sandbox that cannot reach the network or write outside the project. There, the first review cannot download scanners, and the reviewer may not reach its model or write in `~/.openqodex/`. Each scanner reports why it was left out. Run this once in your own terminal for the scanners, and run `review` there when the reviewer cannot start inside the sandbox:
174
+ Some agents run commands in a sandbox that cannot reach the network or write outside the project. There, the first review cannot download scanners, and the reviewer may not reach its model or write in `~/.openqodex/`. Inside Codex's sandbox a second Codex does not start at all: with Codex as the reviewer, `review` prints "Full review unavailable" and the fallback. Each scanner reports why it was left out. Run this once in your own terminal for the scanners, and run `review` there when the reviewer cannot start inside the sandbox:
173
175
 
174
176
  ```
175
177
  npx openqodex doctor --install
package/docs/cli.md CHANGED
@@ -51,8 +51,8 @@ openqodex review [--all | --base <ref> | --uncommitted] [--reviewer auto|claude|
51
51
  openqodex review <branch | #number | pull request link> [--base <ref>] [--reviewer auto|claude|codex|cursor] [--timeout <seconds>] [--no-graph] [--only <list>] [--skip <list>]
52
52
  ```
53
53
 
54
- - The whole review in one run. OpenQodex copies the change into a temporary snapshot in `~/.openqodex/checkouts/`, runs the scanners and the code graph on it, and starts a reviewer: Claude Code (`claude`), as a separate process with no window that can only read, search and list files in the snapshot. A script checks the reviewer's answer and sends problems back at most twice. The report goes to stdout; progress goes to stderr: one line per stage (for the scanners, for example "Scanners: 6 ran, 5 had nothing to check, 14 candidates to check"), and a line every 15 seconds while the reviewer works. The snapshot is deleted at the end. A review is complete only when every scanner candidate was raised or dropped and every changed range was given to the reviewer; otherwise it says what is missing and exits 2. With no reviewer installed and logged in, it prints "Full review unavailable", what is missing, the path of a file with the unchecked scanner candidates, and a fallback: the `review --agent` command for the agent you are in to review the change itself, and exits 2. `docs/internal-reviewer-drivers.md` records how the reviewer is started and isolated.
55
- - `--reviewer auto|claude|codex|cursor`: the reviewer to start. Without it, `reviewer:` in `~/.openqodex/config.yaml` decides, else `auto`. `auto` picks the agent running the command when it can tell and its reviewer is enabled, else the first enabled one. Only `claude` is enabled today: `codex` and `cursor` say why they are not and exit 2 ("Full review unavailable"). `reviewer_web: on` in the same file gives the reviewer Claude Code's web tools; it is off by default (`security` says why).
54
+ - The whole review in one run. OpenQodex copies the change into a temporary snapshot in `~/.openqodex/checkouts/`, runs the scanners and the code graph on it, and starts a reviewer as a separate process with no window: Claude Code (`claude`), which can only read, search and list files in the snapshot, or Codex (`codex exec`), whose commands can read the snapshot and cannot write or reach the network. A script checks the reviewer's answer and sends problems back at most twice, with any changed lines the reviewer was not yet given. The report goes to stdout; progress goes to stderr: one line per stage (for the scanners, for example "Scanners: 6 ran, 5 had nothing to check, 14 candidates to check"), and a line every 15 seconds while the reviewer works. The snapshot is deleted at the end. A review is complete only when every scanner candidate was raised or dropped and every changed range was given to the reviewer; otherwise it says what is missing and exits 2. With no reviewer installed and logged in, it prints "Full review unavailable", what is missing, the path of a file with the unchecked scanner candidates, and a fallback: the `review --agent` command for the agent you are in to review the change itself, and exits 2. `docs/internal-reviewer-drivers.md` records how the reviewer is started and isolated.
55
+ - `--reviewer auto|claude|codex|cursor`: the reviewer to start. Without it, `reviewer:` in `~/.openqodex/config.yaml` decides, else `auto`. `auto` picks the agent running the command when it can tell (Claude Code or Codex) and its reviewer can start, else Claude Code, else Codex. `cursor` is not enabled: it says why and exits 2 ("Full review unavailable"). `codex` exits the same way when the command runs inside Codex's own sandbox, where a second Codex cannot start. The report names the reviewer and its version. With Codex it prints "not recorded by Codex" for file reads, because Codex's event stream does not show every command. The reviewer gets its agent's web tools by default (Claude Code's WebSearch and WebFetch, or Codex's cached web search); `reviewer_web: off` in the same file removes them (`security` says why you might).
56
56
  - `--timeout <seconds>`: stop the reviewer after this long. The default is 600.
57
57
  - `<branch>`, `#<number>` or a pull request link: review that branch or pull request instead of your own change. See "Reviewing a branch or a pull request".
58
58
  - `--base`, `--uncommitted`: see "Which change is checked".
package/docs/config.md CHANGED
@@ -222,8 +222,8 @@ The code graph lists the callers and importers of the code a change touches, for
222
222
  One file in your home folder holds what is yours, not the team's. `OPENQODEX_HOME` moves it with the rest of `~/.openqodex/`.
223
223
 
224
224
  - `update`: `on` or `off`. The default is `on`. `off` stops the daily version check. `openqodex update --off` and `--on` write it.
225
- - `reviewer`: `auto`, `claude`, `codex` or `cursor`. The default is `auto`. The agent `review` starts as its reviewer; `--reviewer` on the command line wins. Only `claude` is enabled today; `codex` and `cursor` make `review` say why and exit 2.
226
- - `reviewer_web`: `on` or `off`. The default is `off`. `on` gives the reviewer Claude Code's WebSearch and WebFetch. A reviewer that reads private code and untrusted text and can open web addresses can be talked into sending the code out, so leave it off unless you accept that (`security`).
225
+ - `reviewer`: `auto`, `claude`, `codex` or `cursor`. The default is `auto`. The agent `review` starts as its reviewer; `--reviewer` on the command line wins. `claude` and `codex` are enabled; `cursor` makes `review` say why and exit 2. `auto` picks the agent running the command, then Claude Code, then Codex.
226
+ - `reviewer_web`: `on` or `off`. The default is `on`: the reviewer gets Claude Code's WebSearch and WebFetch, or Codex's cached web search. `off` removes them. A reviewer that reads private code and untrusted text and can open web addresses can be talked into sending the code out, so set `off` if you do not accept that (`security`).
227
227
 
228
228
  A file that does not parse, or an `update` value that is neither `on` nor `off`, turns updates off until it is fixed. `openqodex doctor` says why updates are off. A file that does not parse, or a `reviewer` or `reviewer_web` value not listed above, stops `review` with one line naming the file.
229
229
 
@@ -85,7 +85,7 @@ The repository also ships a pre-commit hook for the pre-push stage. Add this to
85
85
  ```yaml
86
86
  repos:
87
87
  - repo: https://github.com/openqodex/openqodex
88
- rev: v0.5.0
88
+ rev: v0.6.0
89
89
  hooks:
90
90
  - id: openqodex-scan
91
91
  ```
@@ -1,6 +1,6 @@
1
1
  # Reviewer drivers
2
2
 
3
- This page is for contributors. It records how `openqodex review` starts its own reviewer process, and what was observed with the real binary before a driver was enabled. A driver is enabled only when every property below was shown by a real run.
3
+ This page is for contributors. It records how `openqodex review` starts its own reviewer process, and what was observed with the real binary before a driver was enabled. A driver is enabled only when its isolation was shown by a real run. A limit that no setting removes is stated below and in the user docs.
4
4
 
5
5
  The reviewer is a separate coding-agent process that openqodex starts, without a window, for one review. It reads a frozen copy of the change (the snapshot) and answers with one JSON object. The trace is the agent's own event stream: every tool call, its input and whether it succeeded.
6
6
 
@@ -33,7 +33,7 @@ The child gets an environment built from an allowlist (`reviewerEnv` in `package
33
33
  | `--output-format stream-json --verbose` | One JSON event per line: an `init` event (tools, MCP servers, plugins, permission mode, memory paths, version), every `tool_use` with its input, every `tool_result` with `is_error`, a `permission_denied` event for each refusal, and a `result` event with the final text, turns, usage and cost. For a Read, `tool_use_result.file` gives the path, `startLine` and `numLines` delivered. |
34
34
  | `--tools Read,Grep,Glob` | The `init` event lists exactly `Glob`, `Grep`, `Read`. Asked to run `ls /` and to write a file, the model answered that it has no Bash or Write tool; no such tool call appears in the trace. The `Agent` tool is absent, so no subagent can start. |
35
35
  | `--permission-mode dontAsk` | Reads inside the working directory succeed. A Read of an absolute path outside it (`/tmp/.../outside/secret.txt`, `/etc/hosts`, a decoy ssh config), a relative path that leaves it (`../outside/secret.txt`), a Read through a link inside the folder that points outside, and a Grep or Glob rooted outside (`/tmp/...`, `/`) were each refused with a `permission_denied` event and an error result. A recursive Grep and a `**/*` Glob in the folder did not follow the link out. |
36
- | `--tools Read,Grep,Glob,WebSearch,WebFetch --allowedTools WebSearch,WebFetch` (only with `reviewer_web: on`) | The `init` event lists the five tools. Without `--allowedTools`, `dontAsk` refused both web tools ("Permission to use WebFetch has been denied because Claude Code is running in don't ask mode"); with it, a WebFetch of example.com and a WebSearch both returned results (2026-10-03). |
36
+ | `--tools Read,Grep,Glob,WebSearch,WebFetch --allowedTools WebSearch,WebFetch` (the default; dropped with `reviewer_web: off`) | The `init` event lists the five tools. Without `--allowedTools`, `dontAsk` refused both web tools ("Permission to use WebFetch has been denied because Claude Code is running in don't ask mode"); with it, a WebFetch of example.com and a WebSearch both returned results (2026-10-03). |
37
37
  | `--setting-sources ""` | No user, project or local settings file is read. In the same folder, a run without this flag loaded the project `CLAUDE.md` canary (the answer ended with the canary word) and the user's global instructions (the answer quoted them, about 155,000 input tokens); with it, the input was about 4,500 tokens and neither canary nor any sentence of the global file appeared anywhere in the event stream. With `--include-hook-events`, a run reading user settings showed 11 hook events; this run showed none. |
38
38
  | `--settings {"autoMemoryEnabled":false,"hooks":{},"disableAllHooks":true}` | The `init` event has no `memory_paths`: auto memory is off. With `disableAllHooks`, a SessionStart hook that a terminal wrapper (cmux) added to every `claude` it starts no longer ran: 2 hook events without it, 0 with it (2026-10-04, Claude Code 2.1.289). The driver also stops the run if any hook event appears in the stream. A repository `AGENTS.md` with a canary instruction was not followed. |
39
39
  | `--strict-mcp-config --mcp-config {"mcpServers":{}}` | The `init` event lists no MCP server. |
@@ -80,11 +80,11 @@ With `--no-session-persistence` and auto memory off, real runs with Claude Code
80
80
 
81
81
  ## Codex
82
82
 
83
- Not enabled. Tested with codex-cli 0.160.0 (`/opt/homebrew/bin/codex --version`) on macOS, 2026-10-03, logged in with a ChatGPT account, on a throwaway folder under `~/.openqodex/` with canaries. `--reviewer codex` names it, `auto` never picks it, and its `detect()` says why it is off. Two properties failed; the rest held.
83
+ Enabled since 0.6.0, with two stated limits. Tested with codex-cli 0.160.0 (`/opt/homebrew/bin/codex --version`) on macOS, 2026-10-03 and 2026-10-04, logged in with a ChatGPT account, on throwaway folders under `~/.openqodex/` with canaries. The driver is `packages/cli/src/reviewers/codex.ts`. It refuses a Codex older than 0.160.0, and a Codex whose `--version` prints no version number.
84
84
 
85
- ### The command line that was tested
85
+ ### The command line
86
86
 
87
- Started without a shell, from an environment built with `env -i` (`PATH`, `HOME`, `USER`, `LOGNAME`, `TMPDIR`, `LANG`), the prompt on standard input:
87
+ The driver starts this command without a shell, with the snapshot as the working directory, and writes the prompt to standard input. Its environment comes from an allowlist (`codexEnv`): `PATH`, `HOME`, `USER`, `LOGNAME`, `SHELL`, `TMPDIR`, locale, `TERM`, `TZ`, `CODEX_HOME`, `CODEX_CA_CERTIFICATE`, `SSL_CERT_FILE` and proxy settings, plus `OPENQODEX_REVIEW_DEPTH=1`. No `OPENAI_API_KEY`, no `CODEX_THREAD_ID` and no `CODEX_SANDBOX` reach it. Only absolute `PATH` entries are kept: an empty or relative one would resolve inside the snapshot.
88
88
 
89
89
  ```
90
90
  codex exec --json --color never --ephemeral --skip-git-repo-check
@@ -93,7 +93,7 @@ codex exec --json --color never --ephemeral --skip-git-repo-check
93
93
  -c approval_policy="never"
94
94
  -c default_permissions="openqodex_review"
95
95
  -c permissions.openqodex_review.filesystem={":minimal"="read",":project_roots"="read","/tmp"="deny"}
96
- -c web_search="disabled"
96
+ -c web_search="disabled" (web_search="cached" unless reviewer_web: off)
97
97
  -c project_doc_max_bytes=0
98
98
  -c allow_login_shell=false
99
99
  -c shell_environment_policy.inherit="core"
@@ -110,34 +110,67 @@ codex exec --json --color never --ephemeral --skip-git-repo-check
110
110
 
111
111
  | Part | Observed |
112
112
  |---|---|
113
- | `exec --json` | One JSON event per line: `thread.started`, `turn.started`, `item.started` and `item.completed` for messages and commands, `turn.completed` with `usage` (`input_tokens`, `cached_input_tokens`, `output_tokens`, `reasoning_output_tokens`). The run ends after one answer. |
114
- | `--ephemeral` | No rollout file was written for the test folder. A follow-up in the same session is not possible, so a correction round would need a new run that carries the previous answer. A subagent cannot start: `spawn_agent` failed with "no rollout found for thread id". |
115
- | `-s read-only` alone | Writes and network were refused, but every read was allowed: `cat` of a file in another `/tmp` folder, of `/etc/hosts` and `ls ~/.ssh` all succeeded. |
116
- | the `openqodex_review` permission profile | Reads outside the folder were refused (`Operation not permitted`): a file in a home folder outside it, `~/.ssh`, `~/.codex`, `~/Projects`, `$TMPDIR`, and `/tmp` with the `/tmp` deny entry. Reads inside it worked. `/etc` and the system folders `:minimal` names stay readable; without `:minimal` no command could start. `touch` was refused. `curl` could not resolve a host. The patch tool was refused ("writing is blocked by read-only sandbox"). |
113
+ | `exec --json` | One JSON event per line: `thread.started`, `turn.started`, `item.started` and `item.completed` for messages, commands and web searches, `turn.completed` with `usage` (`input_tokens`, `cached_input_tokens`, `cache_write_input_tokens`, `output_tokens`, `reasoning_output_tokens`). `cached_input_tokens` is part of `input_tokens`. A run can print more than one `agent_message`; the last one is the answer. The run ends after one answer. |
114
+ | `--ephemeral` | No rollout file was written for the test folder. A follow-up in the same session is not possible, so each correction round is a new run that carries the brief, every earlier answer and every earlier correction, in order. A subagent cannot start: `spawn_agent` failed with "no rollout found for thread id". |
115
+ | `-s read-only` alone | Writes and network were refused, but every read was allowed: `cat` of a file in another `/tmp` folder, of `/etc/hosts` and `ls ~/.ssh` all succeeded. So the driver does not use it. |
116
+ | the `openqodex_review` permission profile | Reads outside the folder were refused (`Operation not permitted`): a file in a home folder outside it, `~/.ssh`, `~/.codex`, `~/Projects`, `$TMPDIR`, and `/tmp` with the `/tmp` deny entry. Reads inside it worked. `/etc` and the system folders `:minimal` names stay readable; without `:minimal` no command could start. `touch` was refused. `curl` could not resolve a host. The patch tool was refused ("writing is blocked by read-only sandbox"). Programs outside those folders do not start: in a real review `rg` was "command not found", and the model used `ls`, `find` and `sed`. |
117
117
  | `web_search="disabled"` | The model reported no web search tool. |
118
+ | `web_search="cached"` | Asked to search, the model ran one search; the stream showed a `web_search` item with the query and its results (2026-10-04). Shell commands still had no network: the profile has no network entry. |
118
119
  | `project_doc_max_bytes=0` | A canary `AGENTS.md` in the folder did not appear in the prompt input or the answer. |
119
120
  | `skills.include_instructions=false` | Without it, a canary skill in the folder's `.agents/skills/` was listed to the model, which then followed it. With it, the skills block is gone from the prompt input. |
120
121
  | `--ignore-user-config` | The developer's `config.toml` (MCP servers, plugins, model, trusted projects) is not read. A canary `developer_instructions` in the folder's `.codex/config.toml` did not appear either way: the folder is not a trusted project. |
121
122
 
122
- ### Why it is not enabled
123
+ ### The per-run probe of the boundary
124
+
125
+ The read confinement rests on two `-c` keys (`default_permissions` and `permissions.openqodex_review.filesystem`). A newer Codex could rename or ignore them, and the event stream would not show it. So every review proves the boundary before the first model run (`probeSandbox`). It runs one command, with no model, under `codex sandbox` with the same two keys, in the snapshot folder:
126
+
127
+ - it reads a canary file that openqodex writes in its home folder (`~/.openqodex/.openqodex-probe-<random>`, mode 0600, random content), outside the snapshot;
128
+ - it reads a file with random content that openqodex writes inside the snapshot;
129
+ - it tries to create a file inside the snapshot;
130
+ - it prints a random marker as its last act.
131
+
132
+ The script runs every program by absolute path (`/bin/cat`) with `PATH=/usr/bin:/bin`, so a program committed in the snapshot cannot stand in for one. It handles each expected refusal itself, so the marker prints only when every step ran. The review starts only when the probe exits 0 with no signal, the marker came back, the inside read worked, the canary's content did not come back and no file was created. Any other result, a probe that cannot start, or one that runs past 30 seconds ends the run as "Full review unavailable" with "Codex's sandbox did not confine reads to the review copy; the review did not start" and the `review --agent` fallback. The canary and both probe files are removed whatever happened, before the snapshot is hashed. A Ctrl-C or a kill during the probe ends the probe's process group and removes the files before `review` exits. `codex sandbox` passes on the command's exit status (3 for `exit 3`, 137 for a killed shell).
133
+
134
+ Observed with codex-cli 0.160.0 (2026-10-04):
135
+
136
+ - With the review profile, `cat` of the canary printed "Operation not permitted", `cat` of the inside file printed its content, and the write printed "Operation not permitted".
137
+ - With a profile that adds `"/"="read"`, the canary's content came back, so the probe refuses it. `packages/cli/test/codex-stream.test.ts` runs both against the real binary when Codex is installed (skipped in CI).
138
+ - `codex sandbox -c default_permissions="nope"` stops with "default_permissions refers to undefined profile `nope`". With the key misspelled it stops with "config defines `[permissions]` profiles but does not set `default_permissions`". Both print no canary content, so the probe refuses them.
139
+ - `codex sandbox` takes the same `-c` keys but has no `--ignore-user-config`: the probe reads the developer's `config.toml`, while `codex exec` does not. The `-c` keys override the same keys in that file. The probe proves that this Codex binary applies these keys to a sandboxed command; it runs through `codex sandbox`, not through `codex exec` itself, which cannot run a command without a model.
140
+ - Each probe took well under a second.
141
+
142
+ ### The two limits
123
143
 
124
- 1. The developer's global instructions are loaded. `~/.codex/AGENTS.md` (or `$CODEX_HOME/AGENTS.md`) appeared in the prompt input with every flag above, and the model quoted its first sentence. No configuration key removed it (`instructions`, `user_instructions`, `agents_md.enabled`, `include_agents_md`, `features.agents_md` were tried). Only a different `CODEX_HOME` leaves it out, and that moves the login: a copy of `auth.json` would refresh its token on its own and can leave the developer's real login with a used refresh token.
125
- 2. The event stream does not show every command. Every current model in the catalog (`codex debug models`) has `tool_mode: code_mode_only` except gpt-5.5: the shell is a nested tool inside a code tool. In one run, two shell commands ran (their output came back in the answer) and no `command_execution` event appeared in the stream. So neither the alarm (every read checked from the trace) nor coverage from the trace can be computed. `--disable code_mode_host` removes the shell altogether ("code-mode host is disabled").
144
+ 1. The developer's global instructions are loaded. `~/.codex/AGENTS.md` (or `$CODEX_HOME/AGENTS.md`) appeared in the prompt input with every flag above, and the model quoted its first sentence. No configuration key removed it (`instructions`, `user_instructions`, `agents_md.enabled`, `include_agents_md`, `features.agents_md` were tried). Only a different `CODEX_HOME` leaves it out, and that moves the login: a copy of `auth.json` would refresh its token on its own and can leave the developer's real login with a used refresh token. The driver keeps the developer's `CODEX_HOME`. In one real run the model looked for `CLAUDE.md` and `AGENT.md` files in the snapshot because the global file told it to.
145
+ 2. The event stream does not show every command. Every current model in the catalog (`codex debug models`) has `tool_mode: code_mode_only` except gpt-5.5: the shell is a nested tool inside a code tool. In one run on 2026-10-03, two shell commands ran (their output came back in the answer) and no `command_execution` event appeared in the stream. In the runs on 2026-10-04 every command did appear. Nothing guarantees it, so the driver says `traced: false`.
126
146
 
127
- Read confinement, by contrast, held: the permission profile is a real boundary, stronger than `-s read-only`. The code tool's own JavaScript runtime has no file or network access (`require`, `import("node:fs")` and `fetch` were all undefined or refused).
147
+ What `traced: false` changes in the run (`packages/cli/src/review-run.ts`, `packages/core/src/completion.ts`):
128
148
 
129
- ### Where it was run
149
+ - No read in the stream counts as coverage. A changed range counts only when its diff is in the brief or the run sent it in a correction round. A range still not sent after two rounds makes the review incomplete ("not given to the reviewer").
150
+ - The commands and searches the stream shows are kept in `trace.json` with `inside: null` and their input under `detail`. They never pass or fail a review: there is no "read outside the snapshot" alarm and no "tool it was not given" check. The sandbox is the boundary.
151
+ - The completion record holds `trace_complete: false`, and empty `files_read` and `files_not_read`. The report prints "Files read: not recorded by Codex" and "Reads outside the snapshot: not recorded by Codex".
152
+
153
+ Read confinement held in every test: the permission profile is a real boundary, stronger than `-s read-only`. The code tool's own JavaScript runtime has no file or network access (`require`, `import("node:fs")` and `fetch` were all undefined or refused).
154
+
155
+ ### Detecting it
156
+
157
+ - `codex --version` prints `codex-cli 0.160.0`.
158
+ - `codex login status` prints "Logged in using ChatGPT" and exits 0 when logged in. With an empty `CODEX_HOME` it prints "Not logged in" and exits 1. The driver takes exit 0 as logged in.
159
+ - A Codex session sets these variables for the commands it runs (seen in a `codex exec` run, 2026-10-04): `CODEX_THREAD_ID` and `CODEX_SESSION_ID` (the thread id), `CODEX_VERSION` and `CODEX_CI=1`. Under a sandbox it also sets `CODEX_SANDBOX=seatbelt`, and `CODEX_SANDBOX_NETWORK_DISABLED=1` when network is off. `hostAgent` takes `CODEX_THREAD_ID` as "running inside Codex". The interactive Codex was not run for this; the binary holds the same name.
160
+
161
+ ### Where it works
130
162
 
131
- From a Bash tool inside a running Claude Code session, through `env -i`: it worked. A plain terminal was not tried separately, because the driver stays off.
163
+ - Started from a Bash tool inside a running Claude Code session, with the allowlist environment: it works.
164
+ - Started from inside a Codex sandbox (`codex sandbox -- codex exec ...`), with network off, and again with `workspace-write` and network on: `codex exec` exits 1 at once with "Error: failed to initialize in-process app-server client: Operation not permitted (os error 1)" and prints no event. `codex --version` and `codex login status` still work there. So `detect` reports Codex as unavailable whenever `CODEX_SANDBOX` is set, and `review` prints "Full review unavailable" with the `review --agent` fallback instead of starting a run that cannot answer.
132
165
 
133
166
  ### Usage
134
167
 
135
- Each `turn.completed` event carries `usage`. The test runs used 51,000 to 92,000 input tokens (most of them cached) and 600 to 950 output tokens per run, in 45 seconds or less.
168
+ Each `turn.completed` event carries `usage`. The driver adds `input_tokens` and `output_tokens` over all runs of a review and counts one turn per run. A ChatGPT login has no price per run, so the report shows no cost. The test runs on 2026-10-03 used 51,000 to 92,000 input tokens (most of them cached) and 600 to 950 output tokens per run, in 45 seconds or less. The web search run on 2026-10-04 used 52,911 in and 207 out. A real review of a six-line change with one planted SQL injection took 31 seconds, one run, 50,384 tokens in and 641 out, and reported the injection (2026-10-04).
136
169
 
137
- ### What would enable it
170
+ ### What would remove the limits
138
171
 
139
- A switch that leaves out `$CODEX_HOME/AGENTS.md` without moving the login, and an event for every command the code tool runs. Re-run the checks above on each new Codex version.
172
+ A switch that leaves out `$CODEX_HOME/AGENTS.md` without moving the login, and an event for every command the code tool runs. Re-run the checks above on each new Codex version before raising the tested version.
140
173
 
141
174
  ## Cursor
142
175
 
143
- Not enabled. `cursor-agent` 2025.09.18-7ae6800 was on this Mac and not logged in. Its help shows `-p` ("Has access to all tools, including write and bash"), `--output-format stream-json`, `--model`, `--force` and `--resume`: no option to limit its tools, no read-only sandbox, no switch to skip the repository's rules or the developer's settings. None of the checks above can pass with those options, so no invocation was built. Cursor users get the full review through Claude Code when it is installed.
176
+ Not enabled. `cursor-agent` 2025.09.18-7ae6800 was on this Mac and not logged in. Its help shows `-p` ("Has access to all tools, including write and bash"), `--output-format stream-json`, `--model`, `--force` and `--resume`: no option to limit its tools, no read-only sandbox, no switch to skip the repository's rules or the developer's settings. None of the checks above can pass with those options, so no invocation was built. Cursor users get the full review through Claude Code or Codex when one is installed.
package/docs/plumbing.md CHANGED
@@ -64,7 +64,7 @@ openqodex hook uninstall
64
64
  - `hook install` refuses to replace a hook it did not write. `--force` replaces it and keeps the old hook as `pre-push.openqodex.bak`.
65
65
  - `hook uninstall`: remove that hook and put back the one it replaced. A hook you edited after install is left in place.
66
66
 
67
- When the repository uses husky or lefthook, `hook install` writes nothing. It prints the line to add to their pre-push hook: `npx -y openqodex@<version> hook pre-push || [ $? -ne 1 ]`. The part after `||` makes the line stop the push only on exit 1, as the hook `hook install` writes does: a lookup that fails for its own reasons (exit 2) never stops the push.
67
+ When the repository uses husky or lefthook, `hook install` writes nothing. It prints the line to add to their pre-push hook. For husky it is `npx -y openqodex@<version> hook pre-push "$@" || [ $? -ne 1 ]`, so the hook gets the remote's name, which picks the base for a new branch. For lefthook the line has no `"$@"`: lefthook puts git's hook arguments into its command line as raw text, so a remote URL could carry shell code into it. Without the arguments, the hook looks the push up against `origin`, so a push to another remote is checked as if it went to `origin`. The part after `||` makes the line stop the push only on exit 1, as the hook `hook install` writes does: a lookup that fails for its own reasons (exit 2) never stops the push.
68
68
 
69
69
  `init` asks whether to install the git hook. `agents` explains the push gate.
70
70
 
@@ -12,7 +12,7 @@ The agent installs the skill, runs the review and tells you the result. The step
12
12
  ## Before you start
13
13
 
14
14
  - Node 22 or newer, and git.
15
- - Claude Code, installed and logged in. It is the reviewer OpenQodex starts. Without it, `review` runs the scanners, says "Full review unavailable", and names the command with which the agent you are in reviews the change itself.
15
+ - Claude Code or Codex, installed and logged in. It is the reviewer OpenQodex starts. Without either, `review` runs the scanners, says "Full review unavailable", and names the command with which the agent you are in reviews the change itself.
16
16
  - macOS or Linux. On Windows, use WSL.
17
17
  - A git repository with a change in it.
18
18
 
@@ -46,7 +46,7 @@ Say to your agent:
46
46
  review my change with openqodex
47
47
  ```
48
48
 
49
- The agent runs `openqodex review` and shows you the report it prints. That one command works out the change, copies it to a temporary folder, runs the scanners and the code graph, and starts its own reviewer: a separate Claude Code process that can only read that copy. The reviewer checks every scanner finding and reads every changed line; a script checks its answer, and OpenQodex prints the report. It takes one to three minutes and uses your Claude Code plan. You can run the same command in your terminal.
49
+ The agent runs `openqodex review` and shows you the report it prints. That one command works out the change, copies it to a temporary folder, runs the scanners and the code graph, and starts its own reviewer: a separate Claude Code or Codex process that reads that copy. The reviewer checks every scanner finding and is given every changed line; a script checks its answer, and OpenQodex prints the report. It takes one to three minutes and uses your Claude Code or Codex plan. You can run the same command in your terminal.
50
50
 
51
51
  To review the whole repository instead of one change, say:
52
52
 
@@ -67,7 +67,7 @@ The agent runs `openqodex review feature/login` or `openqodex review '#42'`. Ope
67
67
 
68
68
  ## 3. Read the report
69
69
 
70
- The agent shows you the report as OpenQodex printed it: the verdict, the counts, and for each finding where it is, the problem, why it matters and the fix. A complete review means every stage ran, every scanner finding was checked and every changed line was read; anything not covered is named. It does not mean nothing was missed. The same report is in `.openqodex/reviews/<time>-<id>/report.md` in your repo. `.openqodex/.gitignore` keeps the reports out of git; `git status` shows only the two files above and that `.gitignore`, the first time.
70
+ The agent shows you the report as OpenQodex printed it: the verdict, the counts, and for each finding where it is, the problem, why it matters and the fix. A complete review means every stage ran, every scanner finding was checked and every changed line was put in front of the reviewer; anything not covered is named. It does not mean nothing was missed. The same report is in `.openqodex/reviews/<time>-<id>/report.md` in your repo. `.openqodex/.gitignore` keeps the reports out of git; `git status` shows only the two files above and that `.gitignore`, the first time.
71
71
 
72
72
  The verdict is `passed` unless `.openqodex/config.yaml` sets `review.block_on_severity` and a finding meets it. With no config, OpenQodex warns and never blocks.
73
73
 
package/docs/security.md CHANGED
@@ -29,7 +29,7 @@ Agents that follow the OpenQodex skill are told never to run `openqodex trust` w
29
29
 
30
30
  ## What is sent where
31
31
 
32
- OpenQodex and the built-in scanners send no code anywhere. The review runs on the model your Claude Code login uses: the reviewer process sends it the brief and what the reviewer reads (see "The reviewer process"). A custom scanner you approved does whatever its own command does.
32
+ OpenQodex and the built-in scanners send no code anywhere. The review runs on the model your Claude Code or Codex login uses: the reviewer process sends it the brief and what the reviewer reads (see "The reviewer process"). By default the reviewer can also search the web, and Claude Code can open web pages; `reviewer_web: off` in `~/.openqodex/config.yaml` removes that. A custom scanner you approved does whatever its own command does.
33
33
 
34
34
  OpenQodex and the built-in scanners use the network for these things only:
35
35
 
@@ -37,6 +37,7 @@ OpenQodex and the built-in scanners use the network for these things only:
37
37
  - Semgrep rule packs. semgrep fetches `p/default`, `p/security-audit` and `p/secrets` from the Semgrep registry on each run. Its metrics are off. The rules are never bundled in the package.
38
38
  - The dependency check. When the change holds a lockfile, osv-scanner sends the names and versions of the dependencies in it to osv.dev. It never sends code.
39
39
  - Custom scanners. `openqodex trust` reads the release from the GitHub API and downloads the asset. After approval, a custom scanner does whatever its own command does.
40
+ - The problem report, only when you choose it. When OpenQodex fails, a scanner breaks, or you run `openqodex report`, it prints the GitHub issue it would create and two choices. Nothing is sent unless you press 1 or run `openqodex report --send-last`. Then, when the GitHub CLI `gh` is installed and signed in, `gh` creates the issue in `openqodex/openqodex` with your GitHub account. Otherwise OpenQodex opens GitHub's new-issue page in your browser, or prints its link, with the title and body filled in, and you submit it there. The issue holds the OpenQodex version, the command and its arguments with paths and secrets taken out, the part of OpenQodex that failed, a scrubbed error line, the scanner statuses and your platform (OS, CPU type, Node major version). It never holds code, file names, paths, repository names, config or secrets.
40
41
  - The daily version check, for an install made with `init`. See "Updates" below.
41
42
  - A review of a branch or a pull request (`review <branch>`, `review '#<number>'`). git fetches the branch or `pull/<number>/head` from your remote with its own credentials, and `gh`, when it is installed and signed in, is asked for the pull request's base. OpenQodex reads no token. The target is checked out in `~/.openqodex/checkouts/`, a folder only you can open, with every git hook and filter switched off, so checking it out runs nothing from it, and a link in it becomes a small plain file. The scanners you approved for this repository do run on the target's files, with this repository's settings; one named only in the target's config never runs. If you review pull requests from people you do not trust, approve only custom scanners that do not execute the code they scan.
42
43
 
@@ -71,16 +72,35 @@ OpenQodex sends no telemetry. See `telemetry`.
71
72
 
72
73
  ## The reviewer process
73
74
 
74
- `openqodex review` starts Claude Code (`claude -p`) as its reviewer. Codex and Cursor are not used as reviewers: with the versions tested, one loads your global instructions and does not report every command it runs, and the other cannot be limited to reading. `docs/internal-reviewer-drivers.md` in the repository records the tests. It sends the review brief and the files the reviewer reads to the model your Claude Code login uses, as any Claude Code session does. The reviewer:
75
+ `openqodex review` starts Claude Code (`claude -p`) or Codex (`codex exec`) as its reviewer. Cursor is not used as a reviewer: with the version tested, it cannot be limited to reading. `docs/internal-reviewer-drivers.md` in the repository records the tests.
76
+
77
+ ### Claude Code
78
+
79
+ Claude Code sends the review brief and the files the reviewer reads to the model your Claude Code login uses, as any Claude Code session does. The reviewer:
75
80
 
76
81
  - reads a snapshot of the change in `~/.openqodex/checkouts/`, never your folder. Secrets the scanners found are redacted in every file of the snapshot first, and a file too large to check is left out of it.
77
- - has the read, search and list tools only: no shell, no edits, no web, no MCP server, no subagent. The one exception is the web: `reviewer_web: on` in `~/.openqodex/config.yaml` adds Claude Code's WebSearch and WebFetch. It is off by default. A reviewer that reads private code and untrusted text from the change and can open web addresses can be talked into putting that code into a web address. Turn it on only when you accept that risk. Claude Code's own permission rules refuse a read outside the snapshot; that is the boundary. OpenQodex also checks every tool call in the agent's event stream and marks the review incomplete when one names a path outside the snapshot, an unknown tool or an input it cannot read; that is the alarm.
82
+ - has the read, search and list tools, plus Claude Code's WebSearch and WebFetch: no shell, no edits, no MCP server, no subagent. So the reviewer reads your code and can open web pages. A reviewer that reads private code and untrusted text from the change and can open web addresses can be talked into putting that code into a web address. `reviewer_web: off` in `~/.openqodex/config.yaml` removes the web tools; set it when you do not accept that risk. Claude Code's own permission rules refuse a read outside the snapshot; that is the boundary. OpenQodex also checks every tool call in the agent's event stream and marks the review incomplete when one names a path outside the snapshot, an unknown tool or an input it cannot read; that is the alarm.
78
83
  - loads none of your Claude Code settings, hooks, plugins, memory or `CLAUDE.md` files, and none of the repository's.
79
84
  - gets an environment built from a short allowlist: the variables Claude Code needs to run and find its login (`PATH`, `HOME`, `USER`, `CLAUDE_CONFIG_DIR`, proxy settings, `ANTHROPIC_*` keys, and cloud provider variables only when Claude Code is set to that provider). Other tokens in your shell, such as `GITHUB_TOKEN` or `NPM_TOKEN`, never reach it.
80
85
 
81
86
  The reviewer runs with session saving off (`--no-session-persistence`). After real runs with Claude Code 2.1.289, no transcript, history line or project entry for a snapshot was found in the Claude Code configuration folder. Claude Code's own logs and telemetry follow its own settings.
82
87
 
83
- The run folder of a review holds the brief, the scan, the reviewer's answer and the list of its tool calls (paths and line ranges, never file contents). Each file is created readable by you only, and secrets are redacted in all of them.
88
+ ### Codex
89
+
90
+ Codex sends the conversation to the model your Codex login uses, as any Codex session does. The conversation holds the review brief, your global `~/.codex/AGENTS.md` and the output of each command the reviewer runs. Each correction round is a new Codex run that carries the whole conversation so far. The reviewer:
91
+
92
+ - reads the same redacted snapshot in `~/.openqodex/checkouts/`, never your folder.
93
+ - runs under a Codex permission profile: its commands can read the snapshot and the system folders Codex's `:minimal` set names (such as `/usr` and `/etc`), and nothing else. `/tmp`, your home folder, `~/.ssh` and `~/.codex` are refused. Writes and network are refused. That sandbox is the boundary. Before each review, OpenQodex proves it with a command run under the same profile without a model: a read of a file outside the snapshot and a write inside it must both be refused, or the review does not start.
94
+ - loads your global `~/.codex/AGENTS.md` (or `$CODEX_HOME/AGENTS.md`). No Codex setting leaves it out. If you keep instructions there, the reviewer sees them, including the section `init` adds for Codex.
95
+ - loads none of your `config.toml`, rules, MCP servers, plugins, hooks, memories or skills, and none of the repository's `AGENTS.md` or skills.
96
+ - has Codex's web search by default, as the cached search, which answers from OpenAI's search index and opens no address the model names. `reviewer_web: off` removes it.
97
+ - gets an environment built from a short allowlist: `PATH`, `HOME`, `USER`, `CODEX_HOME`, proxy and certificate settings. Other tokens in your shell, including `OPENAI_API_KEY` and `GITHUB_TOKEN`, never reach it. Its commands see a smaller set still (Codex's `core` environment).
98
+
99
+ There is no alarm for Codex. Its event stream does not show every command it runs, so OpenQodex cannot check from it which files were read. The commands it does show are kept in the run folder as a list for you to read; they never pass or fail a review. Coverage counts only the changed lines in the brief and those OpenQodex sent in a correction round, and the report says file reads were not recorded by Codex.
100
+
101
+ Codex runs with `--ephemeral`: after real runs with codex-cli 0.160.0, no session file was written for the snapshot folder. Codex's own logs follow its own settings.
102
+
103
+ The run folder of a review holds the brief, the scan, the reviewer's answer and the list of its tool calls: paths and line ranges for Claude Code, and the command lines Codex showed for Codex, never their output. Each file is created readable by you only, and secrets are redacted in all of them.
84
104
 
85
105
  ## Secrets
86
106
 
@@ -100,7 +120,7 @@ In your home folder, under `~/.openqodex/` (`OPENQODEX_HOME` moves it):
100
120
  - `runtime/<version>/` and `bin/openqodex`: the copy of the package and the launcher that the hooks call, written by `init`. Updates add copies beside it; a copy is never changed after it is written. `init` and `openqodex update` remove copies older than 7 days, except the one `init` installed, the current one and the previous one.
101
121
  - `runtime/current`: the version the launcher runs, and on a second line the version a rollback goes back to.
102
122
  - `update.json`: the state of the version check, private to you.
103
- - `config.yaml`: your own settings: `update`, `reviewer` (which agent reviews) and `reviewer_web` (the reviewer's web tools, off by default).
123
+ - `config.yaml`: your own settings: `update`, `reviewer` (which agent reviews) and `reviewer_web` (the reviewer's web tools, on by default; `off` removes them).
104
124
  - `install.json`: what `init` and `hook install` wrote, so an uninstall removes only that.
105
125
  - `receipts/<repo id>/`: one small record per reviewed change, readable by you only, written by `review` at the end of a run (and by `review --finalize` for the older two-step protocol, only for a run whose scan this machine ran). The push hooks decide from these records only. The files under the repository's `.openqodex/` are the readable report, never the proof: a branch can carry those files, so a record found only there counts as no review. The check inside your agent is a reminder about your current work: it does not know what a push sends. For a plain `git push` it asks whether your current work has a passing review; any other push command it cannot tell, and says so (a deny when `block_on_severity` is set). The git pre-push hook that `init` offers is the check that sees the exact commits a push sends, and `git push --no-verify` skips it. `init` and `openqodex update` remove records older than 30 days.
106
126
  - `runs/<repo id>/`: one record per `review --agent` run, readable by you only: the change and the hashes of the run files it wrote, so `review --finalize` can tell a run this machine scanned from one a branch carries. Removed with the receipts.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openqodex",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Open source code review that runs inside your coding agent, before you push.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: openqodex
3
- description: Review the current code change before it is pushed. One command runs the security and lint scanners that fit the changed files, a separate reviewer that checks every scanner finding and reads every changed line, and prints the report. Use before every git push, when asked to review changes, and when a push was blocked or warned by OpenQodex.
3
+ description: Review the current code change before it is pushed. One command runs the security and lint scanners that fit the changed files, a separate reviewer that checks every scanner finding and is given every changed line, and prints the report. Use before every git push, when asked to review changes, and when a push was blocked or warned by OpenQodex.
4
4
  ---
5
5
 
6
6
  # OpenQodex: review the change before it is pushed
7
7
 
8
- OpenQodex reviews a change in one command. It takes a frozen copy of the change, runs the deterministic scanners that fit the changed files (gitleaks, semgrep, bandit, hadolint, shellcheck, actionlint, osv-scanner and others), keeps what they report on changed lines, and starts its own reviewer: a separate Claude Code process that reads only that copy. The reviewer checks every scanner finding, reads every changed line and answers in a fixed shape; OpenQodex checks the answer with scripts and prints one report. No key and no account are needed beyond the developer's Claude Code login. The code goes only to the model that login uses. One scanner goes online: when the change touches a dependency file, osv-scanner asks osv.dev about the names and versions of the dependencies; `--offline` skips that lookup.
8
+ OpenQodex reviews a change in one command. It takes a frozen copy of the change, runs the deterministic scanners that fit the changed files (gitleaks, semgrep, bandit, hadolint, shellcheck, actionlint, osv-scanner and others), keeps what they report on changed lines, and starts its own reviewer: a separate Claude Code or Codex process that reads only that copy. The reviewer checks every scanner finding, is given every changed line and answers in a fixed shape; OpenQodex checks the answer with scripts and prints one report. No key and no account are needed beyond the developer's Claude Code or Codex login. The code goes to the model that login uses. The reviewer can also search the web and open web pages unless `reviewer_web: off` is set in `~/.openqodex/config.yaml`. Two scanners go online, and neither sends code: semgrep downloads its rule packs from the Semgrep registry on each run, and when the change touches a dependency file, osv-scanner sends the names and versions of the dependencies to osv.dev. `--offline` skips both scanners.
9
9
 
10
10
  ## When to run
11
11
 
@@ -16,7 +16,7 @@ OpenQodex reviews a change in one command. It takes a frozen copy of the change,
16
16
 
17
17
  ## Who reviews
18
18
 
19
- OpenQodex starts its own reviewer process for every review, with no memory of this session and none of your instructions. You do not start a subagent for it and you do not review the change yourself: run the command and show what it prints.
19
+ OpenQodex starts its own reviewer process for every review, with no memory of this session. You do not start a subagent for it and you do not review the change yourself: run the command and show what it prints.
20
20
 
21
21
  If `review` says "Full review unavailable" and prints a way to review with the agent you are in, follow it: run the command it names and do what the brief it prints says.
22
22
 
@@ -27,13 +27,13 @@ When the file `~/.openqodex/bin/openqodex` exists, run it in place of `npx -y op
27
27
  1. From the repository, run:
28
28
 
29
29
  ```
30
- npx -y openqodex@0.5.0 review
30
+ npx -y openqodex@0.6.0 review
31
31
  ```
32
32
 
33
33
  It reviews the change: the commits not yet pushed plus everything uncommitted, untracked files included. To review the whole repository instead, run:
34
34
 
35
35
  ```
36
- npx -y openqodex@0.5.0 review --all
36
+ npx -y openqodex@0.6.0 review --all
37
37
  ```
38
38
 
39
39
  2. Wait for it. A review takes one to three minutes. Many agents stop a command after two minutes, so give it up to ten minutes, or run it in the background and wait until it exits. While the reviewer works, it prints a progress line every 15 seconds on stderr. Do not start it a second time while one runs.
@@ -50,8 +50,8 @@ When the file `~/.openqodex/bin/openqodex` exists, run it in place of `npx -y op
50
50
  When the developer asks you to review a branch or a pull request that is not their current work, name it:
51
51
 
52
52
  ```
53
- npx -y openqodex@0.5.0 review feature/login
54
- npx -y openqodex@0.5.0 review '#42'
53
+ npx -y openqodex@0.6.0 review feature/login
54
+ npx -y openqodex@0.6.0 review '#42'
55
55
  ```
56
56
 
57
57
  Quote `#42`: in a shell `#` starts a comment. A pull request link works too. OpenQodex fetches the target, checks it out in a temporary folder and reviews what it added since it left its base. This is someone else's code: never run its tests, scripts, builds or services, and never edit it.
@@ -62,19 +62,19 @@ Quote `#42`: in a shell `#` starts a comment. A pull request link works too. Ope
62
62
  - Never run `openqodex trust` without asking the developer first. It approves a custom scanner, which is a command that runs on their machine.
63
63
  - Never set `OPENQODEX_SKIP`. It is the developer's switch, not yours.
64
64
  - When the verdict is `blocked`, do not push unless the developer says so after seeing the findings.
65
- - When OpenQodex prints "OpenQodex had a problem. Nothing has been sent." with `1 create a GitHub issue` and `2 ignore`, tell the developer in one line what went wrong and give them the two choices. Never choose 1 yourself. If they say 1, run `npx -y openqodex@0.5.0 report --send-last` from the same folder. Anything else means 2: do nothing.
65
+ - When OpenQodex prints "OpenQodex had a problem. Nothing has been sent." with `1 create a GitHub issue` and `2 ignore`, tell the developer in one line what went wrong and give them the two choices. Never choose 1 yourself. If they say 1, run `npx -y openqodex@0.6.0 report --send-last` from the same folder. Anything else means 2: do nothing.
66
66
 
67
67
  ## Reading the report
68
68
 
69
69
  - The report is in `.openqodex/reviews/<time>-<id>/` in the repository: `report.md` to read, `report.json` and `report.sarif` for tools. `.openqodex/latest.json` points at the newest review. The reports never show in `git status`: `.openqodex/.gitignore` keeps them out. The two other files in that folder, `config.yaml` and `custom-instructions.md`, are the team's and are meant to be committed.
70
70
  - The verdict is `passed` (with or without warnings) or `blocked`. It is `blocked` only when the repository's config (`.openqodex/config.yaml`, or `.openqodex.yaml` at the root) sets `block_on_severity` and a finding is at or above it. With no config, OpenQodex warns and never blocks.
71
- - A complete review means every stage ran, every scanner finding was checked and every changed line was read; anything not covered is named in the report. It does not mean nothing was missed: no review finds everything.
71
+ - A complete review means every stage ran, every scanner finding was checked and every changed line was put in front of the reviewer; anything not covered is named in the report. It does not mean nothing was missed: no review finds everything.
72
72
  - The coverage list says, for each scanner, whether it ran. A scanner that did not run has a one-line reason:
73
73
  - `no matching files`: nothing in the change is the kind of file it reads.
74
74
  - `installing`: it is being downloaded for the first time; it is included from the next run. Say so to the developer rather than waiting.
75
75
  - `not installed`: it could not be installed here; the reason says why.
76
76
  - `needs Ruby 2.7+` or `needs Go`: brakeman and rubocop need Ruby, golangci-lint needs Go. OpenQodex does not install language runtimes. If the developer wants those scanners, they install Ruby or Go the usual way for their system (for example `brew install ruby go` on a Mac) and run the review again.
77
- - `untrusted`: a custom scanner from the repo's config that the developer has not approved. Tell the developer; approving it is their decision (`npx -y openqodex@0.5.0 trust`).
77
+ - `untrusted`: a custom scanner from the repo's config that the developer has not approved. Tell the developer; approving it is their decision (`npx -y openqodex@0.6.0 trust`).
78
78
  - `failed`: the scanner ran and broke; the reason has its error. A scanner problem never changes the exit code.
79
79
 
80
80
  ## Inside a sandbox
@@ -82,11 +82,11 @@ Quote `#42`: in a shell `#` starts a comment. A pull request link works too. Ope
82
82
  Some agents run commands in a sandbox that cannot reach the network or write outside the project. There the first run cannot download the scanners, and the reviewer may not reach its model. Tell the developer to run this once in their own terminal, outside the agent:
83
83
 
84
84
  ```
85
- npx -y openqodex@0.5.0 doctor --install
85
+ npx -y openqodex@0.6.0 doctor --install
86
86
  ```
87
87
 
88
- It downloads every scanner that fits the machine into `~/.openqodex/tools/`. If the review still says "Full review unavailable" inside the sandbox, the developer runs `npx -y openqodex@0.5.0 review` in their own terminal.
88
+ It downloads every scanner that fits the machine into `~/.openqodex/tools/`. If the review still says "Full review unavailable" inside the sandbox, the developer runs `npx -y openqodex@0.6.0 review` in their own terminal.
89
89
 
90
90
  ## More
91
91
 
92
- `npx -y openqodex@0.5.0 guide` prints this guide. `npx -y openqodex@0.5.0 guide <topic>` prints a page of the docs, offline: `quickstart`, `config`, `scanners`, `custom-scanners`, `security`, `agents`, `cli`.
92
+ `npx -y openqodex@0.6.0 guide` prints this guide. `npx -y openqodex@0.6.0 guide <topic>` prints a page of the docs, offline: `quickstart`, `config`, `scanners`, `custom-scanners`, `security`, `agents`, `cli`.