From bed3e582ac0e7d07d86a32e8023c129693e2fd43 Mon Sep 17 00:00:00 2001 From: lil-bsz <269894707+lil-bsz@users.noreply.github.com> Date: Mon, 21 Sep 2026 17:50:05 +0200 Subject: [PATCH] feat(codex): repo marketplace so Codex users can install the plugin before the directory lists it Codex reads a plugin catalogue from .agents/plugins/marketplace.json in any GitHub repo (`codex plugin marketplace add tester-army/cli`), and the ChatGPT app shows the same file as a source in its Plugins tab. This gives Codex users the one-command install Claude Code users already have through .claude-plugin/marketplace.json, without waiting for the OpenAI Plugins Directory review. Tested with codex-cli 0.153.4: marketplace add, plugin list shows testerarmy@testerarmy-agent-skills, plugin add installs 1.0.0 and registers the hosted MCP server at https://tester.army/mcp, plugin remove cleans up. - .agents/plugins/marketplace.json: one plugin, source ./ (the repo root carries .codex-plugin/plugin.json), category Developer Tools, sign-in on install; marketplace name matches the Claude one. - scripts/check-plugin-manifests.sh + validate-plugin.yml: the new file is parsed and must name the same plugin, point at ./ and share the Claude marketplace name. - README: Codex install commands next to the Claude Code ones. Refs Linear GTM-82. Co-Authored-By: Claude Fable 5.1 --- .agents/plugins/marketplace.json | 20 ++++++++++++++++++++ .github/workflows/validate-plugin.yml | 1 + README.md | 13 ++++++++++++- scripts/check-plugin-manifests.sh | 11 +++++++++-- 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 .agents/plugins/marketplace.json diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json new file mode 100644 index 0000000..a1f852e --- /dev/null +++ b/.agents/plugins/marketplace.json @@ -0,0 +1,20 @@ +{ + "name": "testerarmy-agent-skills", + "interface": { + "displayName": "TesterArmy" + }, + "plugins": [ + { + "name": "testerarmy", + "source": { + "source": "local", + "path": "./" + }, + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_INSTALL" + }, + "category": "Developer Tools" + } + ] +} diff --git a/.github/workflows/validate-plugin.yml b/.github/workflows/validate-plugin.yml index d1ef3ee..9395cf7 100644 --- a/.github/workflows/validate-plugin.yml +++ b/.github/workflows/validate-plugin.yml @@ -9,6 +9,7 @@ on: - ".claude-plugin/**" - ".codex-plugin/**" - ".cursor-plugin/**" + - ".agents/plugins/**" - "assets/**" - "server.json" - "scripts/check-plugin-manifests.sh" diff --git a/README.md b/README.md index 1746f4e..47960d5 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,18 @@ Cursor: open Customize and search for `testerarmy`, or click Add to Cursor on th } ``` -This repo is also a Claude Code plugin that installs the MCP server and the `testerarmy-cli` skill together: run `/plugin marketplace add tester-army/cli`, then `/plugin install testerarmy@testerarmy-agent-skills`. +This repo is also a plugin that installs the MCP server and the `testerarmy-cli` skill together. + +Claude Code: run `/plugin marketplace add tester-army/cli`, then `/plugin install testerarmy@testerarmy-agent-skills`. + +Codex: the repo is a plugin marketplace too, so until TesterArmy appears in the Plugins Directory you can add it from here: + +```bash +codex plugin marketplace add tester-army/cli +codex plugin add testerarmy@testerarmy-agent-skills +``` + +The plugin registers the hosted server for you; sign in once with `codex mcp login testerarmy`, or accept the sign-in prompt the ChatGPT app shows at install. In the ChatGPT desktop app, open this repository in Codex and the marketplace appears as a source in the Plugins tab. Full reference for the server and its tools: https://docs.tester.army/cli/mcp diff --git a/scripts/check-plugin-manifests.sh b/scripts/check-plugin-manifests.sh index debc67e..841ccda 100755 --- a/scripts/check-plugin-manifests.sh +++ b/scripts/check-plugin-manifests.sh @@ -1,12 +1,13 @@ #!/usr/bin/env bash -# Keeps the plugin manifests and the MCP Registry manifest (server.json) in step. Run locally or in CI. +# Keeps the plugin manifests, the Codex repo marketplace and the MCP Registry manifest (server.json) in step. Run locally or in CI. set -euo pipefail cd "$(dirname "$0")/.." -files=(.claude-plugin/plugin.json .claude-plugin/marketplace.json .codex-plugin/plugin.json .cursor-plugin/plugin.json plugin.json .mcp.json mcp.json server.json) +files=(.claude-plugin/plugin.json .claude-plugin/marketplace.json .codex-plugin/plugin.json .cursor-plugin/plugin.json plugin.json .mcp.json mcp.json server.json .agents/plugins/marketplace.json) for f in "${files[@]}"; do jq -e . "$f" >/dev/null || { echo "invalid JSON: $f"; exit 1; }; done # name, version and description must match across every manifest and the marketplace entry +ref_name=$(jq -r .name plugin.json) for key in name version description; do ref=$(jq -r ".$key" plugin.json) for f in .claude-plugin/plugin.json .codex-plugin/plugin.json .cursor-plugin/plugin.json; do @@ -32,6 +33,12 @@ u2=$(jq -r '.mcpServers.testerarmy.url' mcp.json) [ "$(jq -r .version server.json)" = "$(jq -r .version plugin.json)" ] || { echo "version differs in server.json (bump it with the plugin manifests)"; exit 1; } [ "$(jq -r '.remotes[0].url' server.json)" = "$u1" ] || { echo "server.json remotes[0].url differs from the MCP files"; exit 1; } +# the Codex repo marketplace (.agents/plugins/marketplace.json, read by `codex plugin marketplace add tester-army/cli` +# and by the ChatGPT app) must point at this plugin under the same name as the Claude marketplace +[ "$(jq -r '.plugins[0].name' .agents/plugins/marketplace.json)" = "$ref_name" ] || { echo "Codex marketplace plugin name differs from plugin.json"; exit 1; } +[ "$(jq -r '.plugins[0].source.path' .agents/plugins/marketplace.json)" = "./" ] || { echo "Codex marketplace must reference the repo root (./)"; exit 1; } +[ "$(jq -r .name .agents/plugins/marketplace.json)" = "$(jq -r .name .claude-plugin/marketplace.json)" ] || { echo "Codex and Claude marketplace names differ"; exit 1; } + # referenced logo must exist for p in "$(jq -r .logo .cursor-plugin/plugin.json)" "$(jq -r .interface.logo .codex-plugin/plugin.json)"; do [ -f "${p#./}" ] || { echo "missing logo file: $p"; exit 1; }