Skip to content

feat: install the Codex plugin through the codex CLI - #51

Open
camjac251 wants to merge 2 commits into
tolibear:mainfrom
camjac251:feat/codex-native-plugin-add
Open

feat: install the Codex plugin through the codex CLI#51
camjac251 wants to merge 2 commits into
tolibear:mainfrom
camjac251:feat/codex-native-plugin-add

Conversation

@camjac251

Copy link
Copy Markdown

Stacked on #50. The first commit here is that PR; review only the second, or merge #50 first and this will reduce to one commit.

Summary

The installer hand-rolled Codex's plugin store: copy the bundled tree into plugins/cache/<marketplace>/<plugin>/<version>, then write the [plugins] config entry. That re-implements internals Codex already owns, and it skipped steps Codex performs itself.

Install now calls the CLI:

codex plugin marketplace add tolibear/goalbuddy
codex plugin add goalbuddy@goalbuddy

The bundled-copy path stays as a fallback for a missing codex CLI or a failed install, which also keeps the install working offline. The report records which model ran via install_model.

What the hand-rolled copy was missing

Step Codex performs on install Effect of skipping it
migrate_plugin_commands plugins/goalbuddy/commands/goalbuddy.md produced nothing in Codex. It is harness-neutral (reads goal-execution.md, states the loop invariants), so migrating it gives Codex users an execution entry point, which matters because native /goal is gated
Stage into a tempdir, then rename, with rollback A failure mid-copy could leave a half-written cache
remove_old_plugin_versions Covered by #50; the native path now gets it for free
Symlink handling Codex's installer skips symlinks; a recursive copy recreates them. No effect today (the tree has none), but the two would drift

Why the published marketplace rather than the npm package

A local directory is a valid marketplace source, and pointing at the npm package would have guaranteed the installed content matched the version being run. This uses tolibear/goalbuddy anyway, because the entry is written into the user's config.toml and it should be portable and match what the docs tell people to run. A path under an npx cache is machine-specific and disappears when that cache is cleared.

The consequence is that a Codex install tracks the marketplace's default branch, the same way the Claude Code plugin does. That is one distribution model rather than two.

Notes

  • Subagents still install as loose ~/.codex/agents/*.toml. Codex plugins cannot bundle them: neither manifest format has an agents field, and agent roles are read only from config-layer agents/ directories.
  • enablePluginConfig() now runs only when the plugin is not already enabled, so the native path does not get its config.toml rewritten by our formatter.

Test plan

  • npm run check passes (113 internal tests).
  • New coverage: the native path is used when the CLI can install, reporting install_model: "codex-cli" and the published marketplace source; the bundled copy is used when it cannot, with a warning, still producing a loadable cache, config, and agents.
  • The test double now simulates a real codex plugin add, so the native path is the default in tests and the fallback is exercised explicitly. That flushed out two pruning tests from fix: prune stale Codex plugin version directories on install #50 that had started passing through the native path where Codex prunes and our code never runs; they are now pointed at the fallback, the only place that code applies.

Install removed only the version directory it was about to write, leaving any
sibling from an earlier install in place. Codex resolves the active plugin by
scanning that directory and taking the highest version it finds, so a directory
left behind by a newer install keeps being served after a downgrade: install
0.5.0, downgrade to 0.4.3, and Codex still loads 0.5.0.

Install now prunes stale sibling version directories, which is what Codex's own
installer does after it stages a new version. Pruning runs after the new version
is copied into place so a failed copy cannot empty the cache, and it skips names
that are not valid version segments, since Codex would never activate those.
The installer hand-rolled Codex's plugin store: copy the bundled tree into
plugins/cache/<marketplace>/<plugin>/<version>, then write the [plugins] config
entry. That re-implements internals Codex already owns, and it skipped steps
Codex performs itself. Most visibly it never ran the commands migration, so the
plugin's commands/ directory produced nothing in Codex; it also copied
non-atomically, so a failure could leave a half-written cache.

Install now calls `codex plugin add` against the published marketplace, the same
source the documentation and the in-app instructions name, so the entry written
into the user's config.toml stays portable.

The bundled-copy path remains as a fallback for when the codex CLI is missing or
cannot install, which also keeps the install working offline, and the report
records which model was used. Subagents still install as loose config files
because Codex plugins cannot bundle them.
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