feat: Codex CLI plugin support (manifest, agent generation, skills)#395
Conversation
Add first-class Codex CLI plugin support alongside existing Claude Code plugin system: - .codex-plugin/plugin.json manifest with mcpServers reference - generate_codex_agent_toml() in plugin.py with sandbox_mode mapping - factory install --runner codex writes TOML to ~/.codex/agents/ - .agents/skills/ directory mirroring skills/ for Codex convention - AGENTS.md at repo root as cross-tool instruction file - docs/codex-mcp.md documenting MCP setup for Codex users - scripts/sync_agents.py generates both Markdown and TOML formats - 22 new tests covering TOML generation, sandbox modes, and install Closes #392 Signed-off-by: Luke Inglis <lukeinglis21@yahoo.com>
Add .agents/**, .codex-plugin/**, AGENTS.md, and scripts/** to the Modifiable scope so the Reviewer no longer flags these legitimate new files as scope guard violations. Signed-off-by: Luke Inglis <lukeinglis21@yahoo.com>
- Use TOML literal strings (''') for developer_instructions to eliminate
backslash escape processing entirely
- Add fail-closed ValueError in _sandbox_mode for roles not in either
frozenset, with test coverage
- Escape backslashes before quotes in description field to prevent
TOML string injection
Signed-off-by: Luke Inglis <lukeinglis21@yahoo.com>
- Replace invalid TOML ''' concatenation with lossy '' substitution - Strip newlines/tabs from TOML description to ensure single-line values - Fix .codex-plugin skills path to point to ../.agents/skills/ Signed-off-by: Luke Inglis <linglis@redhat.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Luke Inglis <lukeinglis21@yahoo.com>
Signed-off-by: Luke Inglis <lukeinglis21@yahoo.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #395 +/- ##
==========================================
+ Coverage 87.31% 87.38% +0.07%
==========================================
Files 61 61
Lines 9339 9396 +57
==========================================
+ Hits 8154 8211 +57
Misses 1185 1185 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
xukai92
left a comment
There was a problem hiding this comment.
Review: Align with the Claude Code plugin pipeline
The core code (TOML generation, sandbox mapping, install command, tests) is well-executed — nice work. But the PR diverges from how the Claude Code plugin pipeline works in several structural ways. The goal should be: same pattern, different format.
1. Generated TOML files should NOT be on main — use the plugin branch
The Claude pipeline generates agents/*.md via CI and pushes them to the plugin branch. They never land on main. This PR checks 9 generated TOML files (~4800 lines) directly into main under codex-agents/.
Fix: Remove codex-agents/ from this PR. Update .github/workflows/plugin.yml to also git add -f codex-agents/ alongside agents/ when pushing to the plugin branch. The sync script already generates both formats — CI just needs to include both in the push.
# In the "Push to plugin branch" step:
git add -f agents/ codex-agents/2. Skills duplication — .agents/skills/ is a full copy of skills/
The 5 skill files under .agents/skills/ are copies of the existing skills/ directory. There's no mechanism to keep them in sync — they'll drift.
Fix: Either:
- (Preferred) Symlink
.agents/skills→skillsso Codex discovers them at its conventional path, or - Have CI copy
skills/→.agents/skills/on thepluginbranch, same as agent files
Don't maintain two copies of the same files on main.
3. AGENTS.md has a factual error and will drift from CLAUDE.md
Line 54 lists "Refiner" as an agent role — there is no Refiner in agents.yml. The 9 roles are: researcher, strategist, builder, reviewer, evaluator, archivist, distiller, failure_analyst, ceo.
More broadly, AGENTS.md is a hand-written subset of CLAUDE.md with no generation mechanism. It will go stale.
Fix: Either:
- Generate AGENTS.md from CLAUDE.md in CI (strip architecture details, keep build/test/lint/style), or
- Symlink
AGENTS.md→CLAUDE.md(both tools read the same format), or - At minimum, fix the "Refiner" typo and add a comment noting it should be kept in sync with CLAUDE.md
4. .codex-plugin/plugin.json — skills path points to .agents/skills/ which depends on #2
The manifest has "skills": "../.agents/skills/". This only works if .agents/skills/ exists and is kept in sync. If you go with the symlink approach for #2 this resolves itself; if you go with CI-only, then .codex-plugin/ also belongs on the plugin branch.
For reference, the Claude plugin manifest (.claude-plugin/plugin.json) has no "skills" key — Claude Code discovers skills from the skills/ directory by convention.
5. check_codex_agents_in_sync(None) silently returns []
The Markdown version check_agents_in_sync(None) falls back to a default _PLUGIN_AGENTS_DIR. The Codex version returns [] (always passes) when agents_dir is None. This is fine at the script level since sync_agents.py always passes an explicit dir, but the function API is asymmetric. Consider giving it a default _CODEX_AGENTS_DIR too, or documenting why it differs.
Summary
The Python code (plugin.py, cli.py, tests) is solid. The structural issues are about aligning with the existing pipeline:
- Generated files →
pluginbranch, notmain - Skills → single source of truth (symlink or CI copy)
- AGENTS.md → fix "Refiner", add sync mechanism
- Update CI workflow to include Codex artifacts in the
pluginbranch push
After these changes, sync_agents.py generates both formats, CI publishes both to plugin, and factory install --runner codex pulls from the same source — clean parity.
- Remove codex-agents/ from main, generate on plugin branch via CI - Remove .agents/skills/ copies, generate via CI instead of duplicating - Fix AGENTS.md: replace Refiner with Failure Analyst, add sync comment - Update plugin.json skills path to ./skills/ - Add default _CODEX_PLUGIN_AGENTS_DIR for check_codex_agents_in_sync Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Luke Inglis <lukeinglis21@yahoo.com>
|
@xukai92 Thanks for the thorough review — all 5 items addressed in d92f458:
|
xukai92
left a comment
There was a problem hiding this comment.
All 5 items from the previous review are addressed. The pipeline is now aligned:
- Generated files (
codex-agents/,.agents/skills/) stay offmain, published topluginbranch via CI - Skills path in
.codex-plugin/plugin.jsoncorrected to../skills/ - AGENTS.md fixed ("Refiner" → "Failure Analyst") with sync reminder comment
check_codex_agents_in_syncnow has a default dir fallback matching the Claude version- CI workflow updated to copy skills and push both formats
One nit (non-blocking): _WORKSPACE_WRITE_ROLES in plugin.py still contains "refiner" which isn't a real role in agents.yml. It's harmless (never matched by load_agent_config()), but worth removing to avoid confusion — the same Refiner ghost that was in AGENTS.md.
LGTM otherwise.
The refiner role is not defined in agents.yml. Remove it from _WORKSPACE_WRITE_ROLES to keep the role sets consistent. Signed-off-by: Luke Inglis <linglis@redhat.com> Signed-off-by: Luke Inglis <lukeinglis21@yahoo.com>
|
@xukai92 Good catch. Removed Thanks for the review! |
Summary
Closes #392
.codex-plugin/plugin.jsonmanifest with MCP server referencefactory/agents/plugin.pywith TOML agent generation (generate_codex_agent_toml())--runner codexflag tofactory install(writes to~/.codex/agents/).agents/skills/directory with 5 Codex skill definitionsAGENTS.md(cross-tool instruction file)docs/codex-mcp.md(MCP setup documentation for Codex users)scripts/sync_agents.pyto generate both Markdown + TOML formatsReview notes
''') to avoid escape injectionValueErroron unknown roles)../.agents/skills/Test plan
uv run pytest tests/test_plugin_agents.py -vpasses (46 tests)factory install --runner codexwrites TOML files to~/.codex/agents/factory install --runner claudestill works (backwards compatible)🤖 Generated with Claude Code