How it works
One round
- Assayer reads the pull request with your
ghlogin and refuses, before spending any quota, if it is closed, carries theclaude_review_skiplabel, or already has a review from this engine on its head. - It checks out the head in a fresh directory and builds a manifest: which files changed and which of them are reviewable.
- The engine runs over the Agent Client Protocol with your own sign-in. Assayer passes it no GitHub credential:
GH_TOKENandGITHUB_TOKENare removed from its environment and itsghsees an empty config, so it cannot post. Every edit, write, web request, and shell command other than a short list ofghcommands that the engine asks for is refused. - The engine records each finding and a summary through two tools. Assayer checks every finding before anything is posted: a body that looks like a credential is dropped, and a finding it cannot anchor to a changed line is posted as a plain comment instead.
- With
--post, the findings land as inline comments under your login, each ending in a hiddenassayer-findingmarker, and a summary comment gives the coverage.
What the engine can read
The engine runs as your user. Where the engine has a control for it, Assayer keeps the engine in the review’s checkout; it adds no sandbox of its own. A symlink in the reviewed tree checks out as a plain file holding its target, so no engine can follow one out of the checkout. A pull request’s own engine configuration (.codex/ and .agents/) is replaced in the review’s checkout, so it cannot configure the engine that reviews it, and your own MCP servers are switched off for Codex rounds; the review still reads those files in the diff.
| Engine | Files outside the checkout | Network |
|---|---|---|
| Claude Code | Refused: reads outside the working directory are blocked, and the session runs in Always ask mode, so each shell command it asks for goes through Assayer’s allowlist. | Refused |
| OpenCode | Refused: external_directory is denied. |
Refused |
| Codex | Readable through its shell, except where credentials live: gh’s config, SSH, cloud CLIs, Docker, npm and git credentials, GnuPG, and the Claude Code and OpenCode sign-ins, which Codex’s sandbox refuses, unless your own Codex config sets sandbox_mode (Codex then ignores the profile, and Assayer warns each round). Codex cannot be kept to the checkout through its adapter today. |
Refused by the sandbox |
Each row is what a canary measured on 2026-10-13: marker files outside the checkout, a symlink to one, a subagent read, cat, gh auth status and curl.
gh keeps its token in a file when there is no keyring (common on Linux and WSL); every engine is refused that file, Codex only while its config does not set sandbox_mode. Assayer drops a finding or summary that looks like a credential, but it cannot recognise an encoded one. Codex can still read the rest of your files, so for a pull request from someone you do not trust, review with Claude Code or OpenCode.
After the review
Assayer does not yet re-check its own threads on a later round. Reply in a thread with the commit that fixes it, and resolve it yourself. --again runs a fresh review of a head this engine already reviewed.
Whose name is on it
A round posts under the gh login that ran it. There is no shared bot account. A finding is recognised as Assayer’s by its marker, not by who posted it.