Skip to content

feat: Codex CLI plugin as a 4th delivery format - #46

Merged
jsirish merged 2 commits into
mainfrom
chore/codex-plugin-manifest
Aug 23, 2026
Merged

feat: Codex CLI plugin as a 4th delivery format#46
jsirish merged 2 commits into
mainfrom
chore/codex-plugin-manifest

Conversation

@jsirish

@jsirish jsirish commented Aug 23, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds .codex-plugin/plugin.json + .agents/plugins/marketplace.json at repo root so codex plugin marketplace add dynamic/throughline installs natively, alongside the existing Claude Code plugin and OpenCode plugin.
  • New plugin-root hooks.json mirrors hooks/hooks.json, but with ./hooks/<script>.sh commands instead of ${CLAUDE_PLUGIN_ROOT}/hooks/<script>.sh - Codex has no CLAUDE_PLUGIN_ROOT equivalent, and the existing hooks/_lib.sh fallback (${CLAUDE_PLUGIN_ROOT:-$DIR/..}) already handles that, so no script changes were needed.
  • license: MIT added to all 4 SKILL.md frontmatters (matches .claude-plugin/plugin.json; clears the only gh skill publish --dry-run warning).
  • Found and fixed a real pre-existing bug: hooks/session-precompact.sh was missing its executable bit (unlike its four siblings) - this silently broke the hook on Claude Code too, not just the new Codex path.

Test plan

  • python3 validate_plugin.py (Codex's own validator) passes
  • codex plugin marketplace add / plugin list / plugin add throughline@throughline - full round-trip against this branch, confirmed a real copy landed in the plugin cache including hooks/ with executable bits intact
  • All 5 hooks smoke-tested directly against the installed plugin cache with CLAUDE_PLUGIN_ROOT unset - piped synthetic Claude-Code-shaped JSON at each and confirmed correct buffer output: prompt line, tool-call line, compaction-boundary marker, session-ended marker, and the version-tagged onboard context block all rendered correctly
  • gh skill publish --dry-run - clean, zero warnings
  • /local-ci - 167/167 shell tests pass, shellcheck clean

Filed a follow-up issue for docs/promo: #45

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01J73antfNfrGEBa5fHHcAew

Repo-root .codex-plugin/plugin.json and .agents/plugins/marketplace.json
install the same shell-hook capture pipeline Claude Code uses - no
TypeScript port needed, since Codex's plugin-root hooks.json turns out
to be schema-identical to Claude Code's (confirmed against the bundled
figma@openai-curated plugin). Install: `codex plugin marketplace add
dynamic/throughline` -> `codex plugin add throughline@throughline`.

All 5 hooks verified end-to-end against a real installed plugin cache
with CLAUDE_PLUGIN_ROOT unset: piped synthetic Claude-Code-shaped JSON
at each script directly (session-prompt, session-capture,
session-precompact, session-flush, session-onboard) and confirmed the
buffer file got the right redacted/timestamped lines, the compaction
and session-ended markers landed, and onboard's version-tagged context
block rendered correctly - the _lib.sh sourcing fallback
(${CLAUDE_PLUGIN_ROOT:-$DIR/..}) needed zero changes.

Along the way: hooks/session-precompact.sh was missing its executable
bit (unlike its four siblings) - a real, pre-existing bug that broke
this hook on Claude Code too, since exec'ing a non-executable file's
path fails at the OS level before the script's own logic runs. Fixed.

Also added `license: MIT` to all 4 SKILL.md frontmatters (matches
.claude-plugin/plugin.json; gh skill publish --dry-run now passes clean).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J73antfNfrGEBa5fHHcAew
/review-pr surfaced a real problem with the original approach: I'd only
verified the hook SCRIPTS work correctly with CLAUDE_PLUGIN_ROOT unset
(ran each directly with synthetic JSON), not that Codex actually FIRES
them - the reviewer independently tried and could not get any hook to
fire under real `codex exec` either. There's also a plausible
double-registration risk: Codex's hook discovery warns when it finds
both a file and a directory representation at the same plugin-root
layer, which this repo's hooks.json + hooks/ (Claude Code's own
convention) would trigger - and session-capture.sh has no idempotency
guard, so a double-registration would silently double-log every action.

One claimed fix turned out to be wrong too: the reviewer's "critical"
finding said plugin.json needs a `hooks` field pointing at hooks.json.
Tested directly - Codex's own validate_plugin.py (0.149.0) rejects a
`hooks` key outright, contradicting the reference doc that suggested it
(which also separately states hooks are unsupported - the doc is
internally contradictory and shouldn't be trusted over a live test).

Applying the same discipline from the sibling assistant-skills PR (drop
what can't be verified rather than ship a guess with a plausible
corruption risk): removed hooks.json. Codex delivery is now skills-only
- the 4 skills (handoff/onboard/consolidate/consolidate-memory) install
and load correctly (re-verified end-to-end after this change), automatic
capture is not wired. Filed #47 with both reviewers' findings for when
this can actually be tested against a firing hook.

README/CHANGELOG corrected to state what's actually verified instead of
what was assumed to work.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J73antfNfrGEBa5fHHcAew
@jsirish

jsirish commented Aug 23, 2026

Copy link
Copy Markdown
Member Author

/review-pr summary

Ran code-reviewer against the diff. Genuinely important findings this time - one led to a real scope change.

The critical finding, tested and confirmed wrong: the reviewer flagged that plugin.json needed a "hooks": "./hooks.json" field, citing Codex's own reference doc. I tested it directly: validate_plugin.py (Codex 0.149.0) rejects a hooks key outright - the reference doc actually contradicts itself on this (shows it in one example, then separately says it's unsupported). Live test beats a self-contradictory doc.

The two findings that mattered, both real:

  1. I'd only verified the hook scripts work correctly outside CLAUDE_PLUGIN_ROOT (ran each directly with synthetic JSON) - not that Codex actually fires them. The reviewer independently tried under real codex exec and couldn't get a hook to fire either, in either direction. So hook execution under Codex is genuinely unverified, not "verified end-to-end" like the original CHANGELOG claimed.
  2. A plausible double-registration risk: Codex's hook discovery warns when it finds both a file and a directory representation at the same plugin-root layer - which the file layout in this PR (root hooks.json + the pre-existing hooks/ dir) would trigger. session-capture.sh has no idempotency guard, so a double-registration would silently double-log every captured action.

Fix (26eb42b): removed hooks.json from this PR. Codex delivery is now skills-only - the 4 skills install and load correctly (re-verified end-to-end after the change: marketplace add → plugin add → skill load, all confirmed). Filed #47 with both reviewers' findings for when hook firing can actually be tested live, rather than shipping a guess with a plausible corruption risk. README and CHANGELOG corrected to say what's actually verified.

Confirmed correct, no changes needed: .codex-plugin/plugin.json internal consistency with .claude-plugin/plugin.json, .agents/plugins/marketplace.json's shape and source path, the chmod +x fix on session-precompact.sh (clean, complete, survives the install copy), and the "4th delivery format" framing.

🤖 Generated with Claude Code

@jsirish
jsirish merged commit 4ee00f3 into main Aug 23, 2026
2 checks passed
@jsirish
jsirish deleted the chore/codex-plugin-manifest branch August 23, 2026 16:12
jsirish added a commit that referenced this pull request Aug 25, 2026
…gation

Extends CI (.github/workflows/ci.yml) and local-ci (.local-ci.json) manifest
validation to cover .codex-plugin/plugin.json and .agents/plugins/marketplace.json,
which shipped with zero validation since PR #46. Adds a version-agreement check
between the two independently hand-maintained plugin.json version strings.

Closes issue #47 (Codex automatic-capture hooks) with a full empirical
investigation via a live probe hook under real `codex exec`. Decision: not
wiring hooks - discovery is solved and double-registration is ruled out for
the recommended pattern, but hooks require an interactive trust grant with no
verified non-interactive path, so wiring it now would look automatic while
silently not firing for most real usage. Skills-only framing stands, now
backed by evidence instead of an inconclusive prior attempt.

/review-pr found no blocking issues; fixed one sub-threshold divergence
between the local-ci and CI forms of the version-agreement check (missing-file
edge case) and filed #49 for a pre-existing, unrelated local-ci/CI parity gap
it surfaced.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant