Repository navigation
feat(codex): full Codex support via --ide=codex (hooks, config.toml, AGENTS.md) - #161
Merged
Merged
Conversation
…AGENTS.md)
- codex hook adapter: Codex's hook protocol is Claude-Code-compatible, so the
output adapter is re-exported; the input adapter normalizes apply_patch
(patch text in tool_input.command, several files per call) to Edit with
every touched path in NormalizedHookEvent.filePaths; MCP tool calls fall
through the safety switch untouched
- setup --ide=codex writes .codex/config.toml ([mcp_servers.axme] with an
absolute, PATH-independent command), .codex/hooks.json (SessionStart +
PreToolUse + PostToolUse + SessionEnd; SessionEnd timeout 3s, Codex's cap)
and the "## AXME Code" section in AGENTS.md (refreshes only our section)
- new `hook session-start`: prints the axme_context nudge, which Codex
injects as developer context
- checkBash: shell-side enforcement of anchored denied paths ("/...", "~/...")
since Codex has no Read tool; basename patterns (.env, *.pem) excluded to
keep commit messages and heredocs that mention them unblocked
- pre/post-tool-use iterate filePaths for multi-file edits
- tests: adapter unit tests, writer tests, hooks e2e (spawned CLI with Codex
payloads: force-push deny, shell denied-path deny, apply_patch tracking,
session-start), ide-detect + safety additions; docs + changelog
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…heck, platform-independent test paths checkShellPaths compared homedir()-expanded tokens (backslashes on Windows) against deny patterns written with '/', so 'cat ~/.ssh/id_rsa' was never blocked there. Both sides now go through expandHome + normalizePathForSafety and matchesPattern directly. Tests: expected paths built with path.resolve, no RegExp from a temp dir path, filesChanged compared separator-agnostic. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Summary
Full Codex (OpenAI) support, CLI-first, mirroring the Cursor Phase 1 shape (D-143/D-144/D-145) and recorded as D-160:
writes three project-level files and leaves Claude Code's untouched:
.codex/config.toml—[mcp_servers.axme]with an absolute, PATH-independentnode <cli> servecommand (Codex launched from the IDE extension or desktop app does not necessarily see the login-shell PATH)..codex/hooks.json—SessionStart,PreToolUse,PostToolUse(matcherapply_patch|Edit|Write),SessionEnd(timeout 3s, Codex's hard cap; measured 0.12s).AGENTS.md— the## AXME Codesection (CLAUDE.md analogue) plus the#!axmegit gate rule. The writer refreshes only our section and keeps user content after it.What changed
src/hooks/adapters/codex.ts— Codex's hook protocol is Claude-Code-compatible (PascalCase events, samehooks.jsonshape, samehookSpecificOutput.permissionDecisiondeny envelope), so the output adapter is the Claude Code one re-exported. The input adapter normalizesapply_patch(patch text intool_input.command, several files per call) toEditand lists every touched path in a newNormalizedHookEvent.filePaths, resolved against the payloadcwd.pre-tool-use/post-tool-use/session-end— select the codex adapter; the Edit/Write branches iteratefilePaths(Claude Code / Cursor keep the singlefile_pathpath).src/hooks/session-start.ts+hook session-start— prints[AXME Code] Knowledge base ready. Call axme_context now.; Codex injects SessionStart stdout as developer context.checkBashshell-side denied paths — Codex has noReadtool, every read is a shell command, so the filesystem deny rules did not apply there at all.checkBashnow runs anchored deny patterns (/...,~/...) against path-like shell tokens (quote-aware tokenizer, socat "~/.ssh/id_rsa"is caught). Bare basename patterns (.env,*.pem) are deliberately excluded: matched against free text they would block commit messages and heredocs that merely mention a file. This also closes the same gap forBashon Claude Code and Cursor.IdeKindgains"codex";--ide=codexis accepted by setup and the hook dispatcher; no stdin heuristic for Codex on purpose (its payload is Claude-shaped), the writers always pass--ide codexexplicitly.docs/MULTI_CLIENT.mdCodex section + matrix, README matrix, CHANGELOG.Tests
npx tsc --noEmitclean,npm run buildclean.npm test: 650 tests, 649 pass, 1 fail —audit-dedup.test.ts › ensureAxmeSessionForClaude - parallel processes (E2E), a timing test that failed under full-suite load and passes in isolation (11/11). Unrelated to this change.test/codex-hook-adapter.test.ts,test/codex-setup-writers.test.ts,test/codex-hooks-e2e.test.ts(spawns the real CLI with Codex payloads: force-push deny, shell denied-path deny, apply_patch allowed and tracked into the AXME session, MCP tool call allowed, session-start output), additions toide-detectandsafety-bashtests.setup --ide=codexon this repo,codex mcp listshowsaxmefrom the trusted project config, session-start / pre-tool-use gate / session-end verified against the builtdist/cli.mjs.Notes for review
src/cli.ts(template constants) whichever merges second.codex execauditor backend (for users without Claude auth), and a Codex plugin (hooks-bearing plugins are not accepted in the public Codex directory anyway)..codex/layer only for trusted projects; setup prints the reminder.🤖 Generated with Claude Code