Repository navigation
fix(hook): check the files a Codex apply_patch changes; init offers an AGENTS.md section - #182
Merged
Merged
Conversation
…AGENTS.md section in init Codex installs the Claude Code plugin and runs its hook on apply_patch, which matches Write|Edit, but the patch is in tool_input.command and the hook read only tool_input.file_path, so it exited 0 on every Codex edit. The hook now reads the files a patch adds, updates or moves, checks each .tsx or .jsx file in one run per project, and holds an updated file to the lines its hunks change. It also reads path or filePath when the tool's input carries the text it wrote. init, in a terminal, offers to add a marked onsystem section to AGENTS.md or CLAUDE.md, with the MCP and CLI forms, and updates it in place on later runs. OS2-38
…arker, and skip deletion-only hunks - The hook no longer treats a `code` field as a whole-file write. VS Code's insert_edit_into_file sends a snippet with `...existing code...` lines, and check_ui sends unsaved code, so such a call blocked on findings the edit did not cause. Only `content` and `file_text` count as the file. - init pairs the agent-rules END marker with the nearest BEGIN before it, so a BEGIN whose END was deleted no longer makes a later run replace the user's text after it. - A patch hunk that only deletes lines is not looked for when placing a file's edits, so its repeated context no longer turns the file's errors into a non-blocking note. - docs/clients.md and the changeset name the markers without `<!--`, which the site keeps out of llms-full.txt.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Roadmap item: OS2-38 (wave 2: the Codex
apply_patchfix and the opt-in AGENTS.md section ininit).What was wrong
Codex installs the Claude Code plugin from the same marketplace and runs its
hooks/hooks.json. Itsapply_patchmatches ourWrite|Editmatcher (Codex aliases them), but the hook input carries the patch intool_input.command, andcheck-ui.mjsread onlytool_input.file_path, so it exited 0 with no output on every Codex edit. In Codex's source,core/src/tools/handlers/apply_patch.rsbuilds the PostToolUse input as{"command": <patch>}, andhooks/src/engine/dispatcher.rsmatchesEditandWritetoapply_patch.Repro on
examples/shadcn-demowith the built CLI (ONSYSTEM_BIN=dist/cli.js) and a Codex-shaped payload (tool_name: "apply_patch",tool_input.command= an*** Update File:patch that turnsvariant="destructive"intovariant="danger"on line 18 ofapp/settings/danger-zone.tsx):What changed
Hook (
plugins/onsystem/hooks/check-ui.mjs)apply_patch, it reads the files from the patch's*** Add File:,*** Update File:and*** Move to:lines. A deleted file is skipped, and a moved file is checked at its new path.-lines are the old text, and its context and+lines are the new text. So a Codex edit is not blamed for older findings in the file. When a hunk's new text appears more than once in the file, the findings go back as a non-blocking note, as for an Edit.checkonce per project with all of them, and the results are matched back to each file. A single-file run behaves as before, byte for byte (the existing hook tests pass unchanged).tool_input.pathandtool_input.filePath, as the brief asked, but only when the input carries the text the tool wrote (new text,contentorfile_text). VS Code ignores hook matchers and runs hooks after every tool, and itsread_filenames the filefilePath. Without this condition, reading a.tsxfile there would run the check and block.oldString/newStringandold_str/new_strcount as an Edit's old and new text. Acodefield is not read as the file: VS Code'sinsert_edit_into_filesends a snippet with...existing code...lines, and onsystem's owncheck_uisends unsaved code with apath, so both stay silent.hooks.jsonis unchanged: Codex's matcher aliases already routeapply_patchtoWrite|Edit, and a test pins the matcher.init(src/init.ts)In a terminal, after the baseline question,
initoffers (default yes) to add a marked section to the root'sAGENTS.mdand/orCLAUDE.md. It does nothing when neither file exists. The section:A later run replaces the section between the markers. An END marker is paired with the nearest BEGIN before it, so a BEGIN whose END was deleted is not treated as a section, and the text after it is kept. If the section is already current, nothing is asked. A
CLAUDE.mdthat importsAGENTS.md(an@AGENTS.mdline) is left alone. Next's own block inAGENTS.mdis kept as is.--yesand runs with no terminal never write it. The brief allowed a flag to write the section with--yes, but that flag would live insrc/cli.ts, which is outside this item's files, so it can follow separately if wanted. create-next-app 16.4.0 writesAGENTS.mdonly: I checked its publisheddist/index.js, which writesAGENTS.mdand never mentionsCLAUDE.md.Docs:
docs/clients.md(intro, the "Plugins for other agents" lead, the Codex entry with the one-time/hookstrust step, and the closing paragraph on theinitsection),docs/plugin.md(a "Codex runs it too" bullet) and one README sentence. Changeset: patch.Not in this PR
plugins/onsystem/README.mdandSKILL.mdstill describe the hook as Claude Code's only. Both are outside this item's files, so they are a follow-up./hooks.How it was tested
New tests:
test/hook-apply-patch.test.tshas 9 tests. 7 of them fail on main. Two pass there because main is silent: the one that checks a patch with no UI files, and the one that checks a code snippet. They cover:path/filePathwrites, andread_file/view, which stay silent{ filePath, code }snippet (insert_edit_into_file) and acheck_uicall withcodeandpath, on files with older findings, which stay silenttest/init-agents-md.test.tshas 4 tests, and all 4 fail on main. They cover:AGENTS.md, and leaving aCLAUDE.mdthat imports it aloneCLAUDE.mddoes not importAGENTS.md--yes, no terminal, and no fileGate, all passing:
pnpm install --frozen-lockfile --prefer-offlinepnpm format:checkpnpm lintpnpm typecheckpnpm test: 78 files passed, 1 skipped; 1012 tests passed, 3 skippedpnpm build:schema.jsonunchangedpnpm smoke: smoke test passedpnpm build:pnpm --filter site generate,pnpm --filter site test(16 files, 269 tests passed),pnpm --filter site typecheck,pnpm --filter site lintandpnpm --filter site buildall pass. The built/docs/clientspage, its.mdandllms-full.txtcarry the newinitsentence, with no<!--in it.Also on
examples/shadcn-demowith the built CLI: aninsert_edit_into_filepayload ({ explanation, filePath, code }) whose snippet holds only the<CardTitle>line ofapp/settings/danger-zone.tsxexits 0 with no output. The Codex repro above still exits 2 with the one18:25error.