feat: add Codex Desktop hooks integration#245
Conversation
|
@codex is attempting to deploy a commit to the rohitg00's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds Codex CLI/Desktop integration: a README guide for MCP tools + hook bridge, a Node.js CLI that forwards Codex lifecycle hooks to agentmemory REST endpoints with optional context injection and truncation, and Vitest tests validating mapping, auth, stdout injection, and timeout behavior. ChangesCodex Integration
Sequence Diagram(s)sequenceDiagram
participant Codex
participant HookBridge
participant AgentMemory
participant Viewer
Codex->>HookBridge: send hook JSON via stdin (lifecycle events)
HookBridge->>AgentMemory: POST /agentmemory/session/start or /agentmemory/observe
AgentMemory-->>HookBridge: optional session context
HookBridge-->>Codex: stdout injection (if enabled)
AgentMemory->>Viewer: session data available for inspection
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@integrations/codex/agentmemory-codex-hook.mjs`:
- Around line 71-78: The sessionStartContext hook is passing result.context
(likely an object) directly as additionalContext, which must be a string; update
sessionStartContext to ensure additionalContext is always a string by
stringifying non-string inputs (e.g., use JSON.stringify for objects) and
preserve existing string values as-is so the hook outputs
hookSpecificOutput.hookEventName "SessionStart" with additionalContext set to a
plain string.
- Around line 14-19: The constants MAX_TOOL_OUTPUT_CHARS and
MAX_ASSISTANT_MESSAGE_CHARS can become NaN when the env vars are non-numeric
which breaks truncate (slice with NaN -> 0); fix by parsing and validating the
env values when initializing those constants (use parseInt(..., 10) or
Number(...) then check Number.isFinite and >= 0), and fall back to the default
numeric values (8000 and 12000) if the parsed value is invalid; also ensure the
truncate function uses these validated integer values (and optionally
Math.floor/clamp) so slice never receives NaN or negative numbers.
- Around line 60-69: observe() currently falls back to the static "unknown" when
data.session_id is missing, causing observations to be orphaned from the
generated codex_<timestamp> sessionId created in main() (SessionStart); change
observe(sessionData, hookType, observedData) to accept an explicit sessionId (or
pass the computed sessionId as an additional argument), use that sessionId as
the fallback instead of "unknown", and update all call-sites in main() that call
observe(...) so they pass the same sessionId value generated for the
SessionStart event.
In `@README.md`:
- Line 398: Update the ambiguous config path in the README table cell: replace
the project-scoped string ".codex/config.toml" with the user-global path
"~/.codex/config.toml" so it matches integrations/codex/ and the intended MCP
server scope; update the table row containing "Codex CLI / Desktop" (the line
with `codex mcp add agentmemory -- npx -y `@agentmemory/mcp``) to reference
"~/.codex/config.toml" instead of ".codex/config.toml".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: bebe0feb-bd44-45e7-a592-83d0c55657a5
📒 Files selected for processing (3)
README.mdintegrations/codex/README.mdintegrations/codex/agentmemory-codex-hook.mjs
|
Thanks @vybie — Codex Desktop / Codex CLI parity is on the Q3 Breadth roadmap and an early arrival is welcome. The two-layer setup (MCP for explicit tools + lifecycle hooks for auto-capture) is exactly the right shape, mirroring how the Claude Code plugin and the OpenCode plugin work. What I like:
Asks before merge: 1. Test coverage for the hook bridge. The OpenCode plugin (#237) ships with the gap-analysis README; the OpenClaw plugin has its own dispatch. For Codex, please add at least:
2. Codex API stability disclaimer in the integration README. Codex hook event names and payload shape have moved a few times; please add a "tested against Codex Desktop X / Codex CLI Y" note so users know what version this works against. Same pattern as the OpenCode plugin badge. 3. 4. Avoid hardcoded Once those land, this is in scope for Q3 and a clean addition. Holding for @rohitg00 to merge. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
test/codex-hook.test.ts (1)
53-83: ⚡ Quick winAdd a per-process watchdog in
runHookto avoid rare full-test stalls.If the hook process regresses and never exits, this helper can block until Vitest’s global timeout. A local timeout makes failures fast and diagnosable.
Proposed change
function runHook( payload: unknown, env: Record<string, string>, ): Promise<HookResult> { return new Promise((resolve, reject) => { const start = Date.now(); const child = spawn(process.execPath, [HOOK_PATH], { env: { PATH: process.env["PATH"] ?? "", ...env, }, stdio: ["pipe", "pipe", "pipe"], }); + const watchdogMs = 5000; + const watchdog = setTimeout(() => { + child.kill("SIGKILL"); + reject(new Error(`hook subprocess timed out after ${watchdogMs}ms`)); + }, watchdogMs); let stdout = ""; let stderr = ""; child.stdout.on("data", (chunk) => { stdout += chunk.toString(); }); child.stderr.on("data", (chunk) => { stderr += chunk.toString(); }); - child.on("error", reject); + child.on("error", (err) => { + clearTimeout(watchdog); + reject(err); + }); child.on("close", (exitCode) => { + clearTimeout(watchdog); resolve({ stdout, stderr, exitCode, tookMs: Date.now() - start }); }); child.stdin.write(JSON.stringify(payload)); child.stdin.end(); }); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/codex-hook.test.ts` around lines 53 - 83, In runHook, add a per-process watchdog timer so a hung child is killed and the promise settles instead of stalling the whole test run: start a setTimeout (e.g., WATCHDOG_MS) when spawning the child, call child.kill() and either reject or resolve with a clear timeout-specific HookResult (include stderr/stdout/exitCode hint or a distinct error) if the timer fires, and clearTimeout on normal 'close' or 'error' handlers; reference the runHook function, the spawned child variable, child.kill(), and the existing child.on('close')/child.on('error') handlers to integrate the watchdog and ensure the timer is cleared on normal completion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@test/codex-hook.test.ts`:
- Around line 53-83: In runHook, add a per-process watchdog timer so a hung
child is killed and the promise settles instead of stalling the whole test run:
start a setTimeout (e.g., WATCHDOG_MS) when spawning the child, call
child.kill() and either reject or resolve with a clear timeout-specific
HookResult (include stderr/stdout/exitCode hint or a distinct error) if the
timer fires, and clearTimeout on normal 'close' or 'error' handlers; reference
the runHook function, the spawned child variable, child.kill(), and the existing
child.on('close')/child.on('error') handlers to integrate the watchdog and
ensure the timer is cleared on normal completion.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d19deef9-6edb-4bd4-9ea2-8c5df7900d80
📒 Files selected for processing (3)
integrations/codex/README.mdintegrations/codex/agentmemory-codex-hook.mjstest/codex-hook.test.ts
✅ Files skipped from review due to trivial changes (1)
- integrations/codex/README.md
🚧 Files skipped from review as they are similar to previous changes (1)
- integrations/codex/agentmemory-codex-hook.mjs
Summary
Adds a Codex integration guide and hook bridge so Codex Desktop / Codex CLI users can use agentmemory in a Claude Code-style workflow.
This documents a two-layer setup:
memory_save,memory_recall,memory_smart_search, etc.)What changed
integrations/codex/agentmemory-codex-hook.mjs, a best-effort Codex hook bridge that translates Codex hook payloads into agentmemory REST API calls.integrations/codex/README.mdwith end-to-end setup steps for Codex Desktop and Codex CLI.Setup covered in the guide
Start the full agentmemory server:
Add the MCP server to
~/.codex/config.toml:Copy the hook bridge into
~/.codex/hooks/.Enable Codex hooks:
Register
SessionStart,UserPromptSubmit,PreToolUse,PostToolUse, andStophooks to call the bridge script.Verify captured sessions in the viewer at
http://localhost:3113or viaGET /agentmemory/export.Behavior
The bridge maps Codex events to agentmemory observations:
SessionStart/agentmemory/session/start, optionally injects recalled contextUserPromptSubmitprompt_submitobservationPreToolUsepre_tool_useobservationPostToolUsepost_tool_useobservationStopstopobservationThe bridge truncates large tool outputs and never throws or blocks Codex if agentmemory is down.
Validation
node --check integrations/codex/agentmemory-codex-hook.mjsUserPromptSubmitpayload.GET /agentmemory/export.Notes
Codex hooks currently expose fewer lifecycle events than the Claude Code plugin, so this is not a byte-for-byte replacement. It does cover the main loop users need: automatic capture, session registration, startup context recall, and explicit MCP memory tools.
Summary by CodeRabbit
Documentation
New Features
Tests