feat(plugin): ship Codex plugin manifest + marketplace#311
Conversation
OpenAI Codex shipped a plugin platform
(developers.openai.com/codex/plugins) with the same shape as Anthropic
Claude Code plugins: .codex-plugin/plugin.json manifest, optional
.mcp.json, hooks/hooks.json, and a skills/ directory.
Verified against openai/codex source
(codex-rs/hooks/src/engine/discovery.rs): Codex's hook engine
explicitly injects CLAUDE_PLUGIN_ROOT into hook subprocesses for
OOTB compat with existing Claude Code plugins. The wire-format
input schemas
(codex-rs/hooks/schema/generated/session-start.command.input.schema.json
and siblings) use the same field names as Claude Code
(session_id, cwd, hook_event_name, source, transcript_path, model,
permission_mode).
Net result: our existing plugin/ directory already works as a Codex
plugin with two small additions:
1. plugin/.codex-plugin/plugin.json — Codex manifest pointing at the
shared ./.mcp.json, ./skills/, and a Codex-specific ./hooks/
hooks.codex.json. Name (kebab-case), version, description match
the Claude Code manifest.
2. plugin/hooks/hooks.codex.json — Codex-compatible hook subset.
Drops SubagentStart, SubagentStop, SessionEnd, Notification,
TaskCompleted, PostToolUseFailure (Claude-Code-only). Keeps
SessionStart, UserPromptSubmit, PreToolUse, PostToolUse,
PreCompact, Stop. Adds Codex-specific `statusMessage` decorations
on the two hooks the user sees most (SessionStart + UserPromptSubmit).
The script commands themselves still reference ${CLAUDE_PLUGIN_ROOT}
because Codex's engine injects it.
3. .codex-plugin/marketplace.json at repo root — git-subdir source
pointing at ./plugin so `codex plugin marketplace add rohitg00/
agentmemory` works the same way `claude plugin marketplace add`
does. Mirrors the existing .claude-plugin/marketplace.json shape
but in Codex's marketplace schema (name + interface.displayName
+ plugins[].source.{source, url, path, ref} + plugins[].policy).
README updates:
- Codex CLI tile in the Works-with-every-agent grid now reads
"6 hooks + MCP + skills" instead of "MCP server" to surface the
upgraded surface.
- "Other agents" install table now distinguishes "Codex CLI (MCP
only)" (existing codex mcp add path) from "Codex CLI (full
plugin)" (new marketplace install).
- New Codex section in the "paste this prompt" block with the
two-command install (server + marketplace add + plugin install),
the list of registered surfaces, and the env-var-injection note
citing the Codex source line.
6 new tests in test/codex-plugin.test.ts cover:
1. .codex-plugin/plugin.json present with kebab-case name and
required references.
2. Manifest version matches main package.json (so future bumps
don't drift the Codex side).
3. Every path referenced in the manifest resolves to a real file or
directory on disk.
4. hooks.codex.json contains only events Codex supports — any
future addition has to be added to a Codex allowlist or the
test fails loudly.
5. Every ${CLAUDE_PLUGIN_ROOT}/scripts/* command references an
existing script file (catches typos before users hit them).
6. .codex-plugin/marketplace.json declares git-subdir source with
path: "./plugin" pointing at this repo.
874 / 874 tests pass.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
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 (2)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe PR adds Codex plugin support: six lifecycle hooks, a marketplace registration file, a plugin manifest version bump, validation tests, and README updates documenting Codex CLI plugin-platform usage. ChangesCodex Plugin Integration for agentmemory
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes
🚥 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 docstrings
🧪 Generate unit tests (beta)
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: 2
🧹 Nitpick comments (1)
.codex-plugin/marketplace.json (1)
13-13: ⚡ Quick winPin
source.refto an immutable tag/commit for reproducible installs.Using
mainon Line [13] can make plugin installs drift over time. Prefer a release tag (or commit SHA).Proposed change
- "ref": "main" + "ref": "v0.9.10"🤖 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 @.codex-plugin/marketplace.json at line 13, The manifest currently pins source.ref to the mutable branch "main" in .codex-plugin/marketplace.json; change the "ref" value used by the plugin's source (the source.ref / "ref" key) to a fixed release tag or commit SHA (e.g., vX.Y.Z or a full commit hash) so installs are reproducible and won't drift over time, and update any documentation or release workflow that previously relied on "main" to reference the chosen immutable tag or SHA.
🤖 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 `@plugin/.codex-plugin/plugin.json`:
- Line 4: Update the "description" field in plugin.json to reflect the actual
registered hook count (replace "12 hooks" with "6 hooks" or remove the numeric
reference) so the manifest text matches the registered hooks; edit the value of
the "description" key in plugin.json to say "6 hooks, 51 MCP tools, 4 skills,
real-time viewer." (target the "description" property in plugin.json).
In `@test/codex-plugin.test.ts`:
- Around line 66-71: The test in test/codex-plugin.test.ts currently asserts
five lifecycle events on the events array (SessionStart, UserPromptSubmit,
PreToolUse, PostToolUse, Stop) but omits the required "PreCompact" event; update
the assertions that check the events collection (the existing
expect(events).toContain(...) lines) to also include
expect(events).toContain("PreCompact") so the test enforces the full six-hook
contract and will fail if PreCompact is removed.
---
Nitpick comments:
In @.codex-plugin/marketplace.json:
- Line 13: The manifest currently pins source.ref to the mutable branch "main"
in .codex-plugin/marketplace.json; change the "ref" value used by the plugin's
source (the source.ref / "ref" key) to a fixed release tag or commit SHA (e.g.,
vX.Y.Z or a full commit hash) so installs are reproducible and won't drift over
time, and update any documentation or release workflow that previously relied on
"main" to reference the chosen immutable tag or SHA.
🪄 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: a4d6ad5d-9c72-468c-a654-b32f17a0a884
📒 Files selected for processing (5)
.codex-plugin/marketplace.jsonREADME.mdplugin/.codex-plugin/plugin.jsonplugin/hooks/hooks.codex.jsontest/codex-plugin.test.ts
Two reviewer findings addressed:
1. plugin/.codex-plugin/plugin.json's description claimed "12 hooks"
but Codex only registers 6 (the Codex hook input schemas don't
define SubagentStart, SubagentStop, SessionEnd, Notification,
TaskCompleted, PostToolUseFailure). Updated the description to
"6 hooks, 51 MCP tools, 4 skills, real-time viewer." so the
marketplace listing matches the registered surface.
2. test/codex-plugin.test.ts asserted five lifecycle events
(SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop)
but omitted PreCompact, leaving a regression hole: dropping
PreCompact from hooks.codex.json would still pass the test
because the allowlist loop only blocks UNKNOWN events. Added
expect(events).toContain("PreCompact") so the suite enforces
the full six-hook contract.
Skipped (with reason):
3. marketplace.json source.ref currently "main" — reviewer asked
for a fixed tag/SHA. Skipping because pinning to a tag forces
updating marketplace.json on every release; "main" matches our
convention where releases tag from main HEAD and pre-release
work is on feature branches. Users wanting an immutable cut
can pass --ref vX.Y.Z to `codex plugin marketplace add` per
Codex docs.
Validation: 6/6 codex tests pass; 874/874 full suite unchanged.
… website star button (#317) Three landed PRs since v0.9.10: - #311 — Codex plugin support (manifest + marketplace + Codex-shaped hooks subset, sharing the same scripts as the Claude Code plugin via CLAUDE_PLUGIN_ROOT OOTB-compat injection on Codex's hook engine) - #310 — OpenClaw plugins.slots.memory now actually claimed via api.registerMemoryCapability({ promptBuilder }); older builds without the capability API still load via the existing hook-only path - #316 — Star on GitHub button in the website hero CTA row, live stargazer count via api.github.com, 30-minute localStorage cache, graceful degrade on API failure Bumping 0.9.10 -> 0.9.11 across the 8 standard files: - package.json - packages/mcp/package.json - plugin/.claude-plugin/plugin.json - plugin/.codex-plugin/plugin.json - src/version.ts - src/types.ts (ExportData.version literal) - src/functions/export-import.ts (supportedVersions) - test/export-import.test.ts (round-trip expectation) - CHANGELOG.md (new 0.9.11 entry) 877 / 877 tests pass. Build clean.
`detectProvider()` correctly gates OpenAI auto-detection on OPENAI_API_KEY_FOR_LLM !== "false", but `detectLlmProviderKind()` did not — so users who set OPENAI_API_KEY only for embeddings (via the existing OPENAI_BASE_URL + OPENAI_EMBEDDING_MODEL flow from rohitg00#186) would see /agentmemory/config/flags report `provider: llm` even though detectProvider() routed them to the noop provider. Also clarify in the README that OPENAI_REASONING_EFFORT is honored only by reasoning models (o1, o3, gpt-*-reasoning) and providers that mirror that schema (Ollama Cloud thinking models). Standard chat models reject the field with 400. Verified: - OPENAI_API_KEY=sk-... + OPENAI_API_KEY_FOR_LLM=false now returns "noop" from detectLlmProviderKind (was "llm" before the fix). - OPENAI_API_KEY=sk-... alone still returns "llm" (intended default). - npm run build clean. Note: 10 pre-existing test failures on test/mcp-standalone.test.ts are a stale-branch artefact — this branch is 10 commits behind main and is missing the MCP shim fixes that landed via rohitg00#311 / rohitg00#327. Recommend rebasing on main (or "Update branch" via the GitHub UI) before merge.
`detectProvider()` correctly gates OpenAI auto-detection on OPENAI_API_KEY_FOR_LLM !== "false", but `detectLlmProviderKind()` did not — so users who set OPENAI_API_KEY only for embeddings (via the existing OPENAI_BASE_URL + OPENAI_EMBEDDING_MODEL flow from rohitg00#186) would see /agentmemory/config/flags report `provider: llm` even though detectProvider() routed them to the noop provider. Also clarify in the README that OPENAI_REASONING_EFFORT is honored only by reasoning models (o1, o3, gpt-*-reasoning) and providers that mirror that schema (Ollama Cloud thinking models). Standard chat models reject the field with 400. Verified: - OPENAI_API_KEY=sk-... + OPENAI_API_KEY_FOR_LLM=false now returns "noop" from detectLlmProviderKind (was "llm" before the fix). - OPENAI_API_KEY=sk-... alone still returns "llm" (intended default). - npm run build clean. Note: 10 pre-existing test failures on test/mcp-standalone.test.ts are a stale-branch artefact — this branch is 10 commits behind main and is missing the MCP shim fixes that landed via rohitg00#311 / rohitg00#327. Recommend rebasing on main (or "Update branch" via the GitHub UI) before merge.
* feat: add OpenAI-compatible LLM provider - Add OpenAIProvider using raw fetch (no SDK dependency) - Supports any /v1/chat/completions endpoint: OpenAI, DeepSeek, SiliconFlow, Azure OpenAI, vLLM, LM Studio, Ollama - Auto-detects OPENAI_API_KEY with OPENAI_API_KEY_FOR_LLM opt-out - Add OPENAI_REASONING_EFFORT passthrough for thinking models (e.g. Ollama Cloud kimi-k2.6) to ensure content is populated - Update README with OpenAI provider table, env vars, and reasoning config * fix(config): honor OPENAI_API_KEY_FOR_LLM=false in detectLlmProviderKind `detectProvider()` correctly gates OpenAI auto-detection on OPENAI_API_KEY_FOR_LLM !== "false", but `detectLlmProviderKind()` did not — so users who set OPENAI_API_KEY only for embeddings (via the existing OPENAI_BASE_URL + OPENAI_EMBEDDING_MODEL flow from #186) would see /agentmemory/config/flags report `provider: llm` even though detectProvider() routed them to the noop provider. Also clarify in the README that OPENAI_REASONING_EFFORT is honored only by reasoning models (o1, o3, gpt-*-reasoning) and providers that mirror that schema (Ollama Cloud thinking models). Standard chat models reject the field with 400. Verified: - OPENAI_API_KEY=sk-... + OPENAI_API_KEY_FOR_LLM=false now returns "noop" from detectLlmProviderKind (was "llm" before the fix). - OPENAI_API_KEY=sk-... alone still returns "llm" (intended default). - npm run build clean. Note: 10 pre-existing test failures on test/mcp-standalone.test.ts are a stale-branch artefact — this branch is 10 commits behind main and is missing the MCP shim fixes that landed via #311 / #327. Recommend rebasing on main (or "Update branch" via the GitHub UI) before merge. * feat(providers): openai — fetch timeout, Azure auto-detect, OPENAI_API_KEY scope hint Three follow-ups against the v2 PR so reviewers can see what's left before merge: 1. Outbound fetch timeout. The other raw-fetch providers (anthropic / gemini / openrouter / minimax) all lack one too — that's a same-pattern repo-wide concern tracked as a follow-up issue. This PR fixes the bound on the new surface only: AbortController + setTimeout, default 60s, overridable via OPENAI_TIMEOUT_MS. Abort messages explain how to raise the bound. 2. Azure OpenAI auto-detection. Azure is in the README's supported list but the code only emitted the standard OpenAI shape. Now detects `.openai.azure.com` hostnames at construction time and: - swaps `Authorization: Bearer` for `api-key: <KEY>` - drops the `/v1` path prefix (deployment is baked into base URL) - appends `api-version=<version>` query param (env-overridable) Default api-version is `2024-08-01-preview` per Azure docs. Existing users of the standard OpenAI shape are unaffected — the detection is purely hostname-driven. 3. README clarity on `OPENAI_API_KEY` shared use. Embeddings (#186) and this PR's LLM both auto-activate from the same key, which surprises users who only meant one or the other. Added an explicit callout above the LLM section pointing at the `OPENAI_API_KEY_FOR_LLM=false` opt-out. Also documents the new timeout + Azure base-URL shape inline. Build clean. Tests 954/954 (10 pre-existing mcp-standalone failures on main are not in this branch's snapshot). --------- Co-authored-by: Rohit Ghumare <ghumare64@gmail.com>
Why
OpenAI Codex now has a plugin platform (developers.openai.com/codex/plugins). Same shape as Anthropic Claude Code plugins:
.codex-plugin/plugin.jsonmanifest, optional.mcp.json,hooks/hooks.json, and askills/directory.Verified against the openai/codex source (not docs):
codex-rs/hooks/src/engine/discovery.rs— Codex's hook engine explicitly injectsCLAUDE_PLUGIN_ROOTinto hook subprocesses for OOTB compat with existing Claude Code plugins:codex-rs/hooks/schema/generated/session-start.command.input.schema.json— wire-format input uses the same field names as Claude Code (session_id,cwd,hook_event_name,source,transcript_path,model,permission_mode). Our existingplugin/scripts/session-start.mjsalready readsdata.session_idanddata.cwd.Net result: our existing
plugin/directory already works as a Codex plugin with two small additions.Changes
plugin/.codex-plugin/plugin.json(new)Codex manifest pointing at the shared
./.mcp.json,./skills/, and a Codex-specific./hooks/hooks.codex.json. Same name + version as the Claude Code manifest (kebab-caseagentmemory).plugin/hooks/hooks.codex.json(new)Codex-compatible hook subset. Drops
SubagentStart,SubagentStop,SessionEnd,Notification,TaskCompleted,PostToolUseFailure(Claude-Code-only — Codex's input schemas don't define them). KeepsSessionStart,UserPromptSubmit,PreToolUse,PostToolUse,PreCompact,Stop. Adds Codex-specificstatusMessagedecorations onSessionStart+UserPromptSubmit. Script commands still reference${CLAUDE_PLUGIN_ROOT}because Codex's engine injects it (cited above)..codex-plugin/marketplace.json(new, at repo root)git-subdirsource pointing at./pluginsocodex plugin marketplace add rohitg00/agentmemoryworks the same wayclaude plugin marketplace adddoes. Mirrors the existing.claude-plugin/marketplace.jsonbut in Codex's marketplace schema (name+interface.displayName+plugins[].source.{source, url, path, ref}+plugins[].policy).README.mdcodex mcp addpath) from Codex CLI (full plugin) (new marketplace install).codex plugin marketplace add+codex plugin install), the list of registered surfaces, and the env-var-injection note citing the Codex source line.test/codex-plugin.test.ts(new — 6 cases).codex-plugin/plugin.jsonpresent with kebab-case name and required references.package.json(future bumps won't drift the Codex side).hooks.codex.jsoncontains only events Codex supports — adding an unsupported event fails the test.${CLAUDE_PLUGIN_ROOT}/scripts/*command references an existing script (catches typos before users hit them)..codex-plugin/marketplace.jsondeclaresgit-subdirsource withpath: "./plugin".Install (post-merge)
Registers
@agentmemory/mcpMCP server + 6 lifecycle hooks + 4 skills (/recall,/remember,/session-history,/forget).Test plan
npm test— 874 / 874 (868 baseline + 6 new tests).npm run build— tsdown clean.codex plugin marketplace add rohitg00/agentmemory+codex plugin install agentmemoryshould pick up the manifest and register MCP + hooks + skills.SessionStartandagentmemorywrites a session row athttp://localhost:3113.Summary by CodeRabbit
New Features
Documentation
Tests
Chores