From f378c23ce0d9ed55fae3fc308991864421f1d071 Mon Sep 17 00:00:00 2001 From: Hamza Ali Shahjahan <191920295+hamza-ali-shahjahan@users.noreply.github.com> Date: Mon, 13 Jul 2026 23:11:44 +0500 Subject: [PATCH] =?UTF-8?q?Add=20claudex=20=E2=80=94=20cross-model=20pair?= =?UTF-8?q?=20programming=20(Claude=20writes,=20Codex=20reviews)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + plugins/claudex/.claude-plugin/plugin.json | 17 +++ plugins/claudex/README.md | 14 +++ plugins/claudex/commands/claudex.md | 110 ++++++++++++++++++ plugins/claudex/commands/debate.md | 110 ++++++++++++++++++ plugins/claudex/commands/demo.md | 92 +++++++++++++++ plugins/claudex/commands/setup.md | 25 ++++ plugins/claudex/commands/stats.md | 32 +++++ plugins/claudex/commands/verdict.md | 77 ++++++++++++ .../skills/claudex-second-opinion/SKILL.md | 43 +++++++ 10 files changed, 521 insertions(+) create mode 100644 plugins/claudex/.claude-plugin/plugin.json create mode 100644 plugins/claudex/README.md create mode 100644 plugins/claudex/commands/claudex.md create mode 100644 plugins/claudex/commands/debate.md create mode 100644 plugins/claudex/commands/demo.md create mode 100644 plugins/claudex/commands/setup.md create mode 100644 plugins/claudex/commands/stats.md create mode 100644 plugins/claudex/commands/verdict.md create mode 100644 plugins/claudex/skills/claudex-second-opinion/SKILL.md diff --git a/README.md b/README.md index e4de615..cbe869f 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ Install or disable them dynamically with the `/plugin` command β€” enabling you ### Code Quality Testing - [api-tester](./plugins/api-tester) - [bug-detective](./plugins/bug-detective) +- [claudex](./plugins/claudex) - [code-review](./plugins/code-review) - [code-review-assistant](./plugins/code-review-assistant) - [code-reviewer](./plugins/code-reviewer) diff --git a/plugins/claudex/.claude-plugin/plugin.json b/plugins/claudex/.claude-plugin/plugin.json new file mode 100644 index 0000000..3454ad3 --- /dev/null +++ b/plugins/claudex/.claude-plugin/plugin.json @@ -0,0 +1,17 @@ +{ + "name": "claudex", + "version": "0.6.0", + "description": "Claude writes. Codex reviews. You ship. Cross-model pair programming inside Claude Code.", + "author": { + "name": "Hamza Ali" + }, + "homepage": "https://github.com/hamza-ali-shahjahan/claudex", + "keywords": [ + "claude-code", + "codex", + "code-review", + "pair-programming", + "cross-model", + "claudex" + ] +} diff --git a/plugins/claudex/README.md b/plugins/claudex/README.md new file mode 100644 index 0000000..523d39e --- /dev/null +++ b/plugins/claudex/README.md @@ -0,0 +1,14 @@ +# ClauDex πŸ§‘πŸ–€ + +**Claude writes. Codex reviews. You ship.** + +Cross-model pair programming: `/claudex` runs a writeβ†’review loop where Claude implements and OpenAI Codex reviews the diff (read-only) until both agree; `/claudex:verdict` has both models review the same diff independently and surfaces where they disagree (🀝 both / 🧑 only Claude / πŸ–€ only Codex); `/claudex:debate` has them argue a design decision while you arbitrate; `/claudex:demo` is a two-minute guided first run over planted bugs. + +Requires the Codex CLI (`npm i -g @openai/codex` + `codex login`) β€” every command refuses to run a one-model duet. + +Canonical repo, docs, and latest version: **https://github.com/hamza-ali-shahjahan/claudex** + +``` +/plugin marketplace add hamza-ali-shahjahan/claudex +/plugin install claudex@claudex +``` diff --git a/plugins/claudex/commands/claudex.md b/plugins/claudex/commands/claudex.md new file mode 100644 index 0000000..72f0b8e --- /dev/null +++ b/plugins/claudex/commands/claudex.md @@ -0,0 +1,110 @@ +--- +description: Claude writes, Codex reviews, iterate until both agree β€” then ship with love +argument-hint: [task to build β€” or leave empty to run the loop on current uncommitted changes] +--- + +You are running **ClauDex** β€” a cross-model pair-programming loop between Claude Code (you, the writer) and OpenAI Codex (the reviewer). + +**The sign-off contract, before anything else:** the line +`built with love by ClauDex πŸ§‘πŸ–€` may appear ONLY at the end of a run in which +Codex successfully completed at least one review AND no blocking findings +remain β€” and when a run earns it, signing is REQUIRED (an earned, unsigned +run breaks the contract just like an unearned, signed one). Every other +outcome β€” refusal, interruption, empty diff, deadlock β€” ends UNSIGNED. +There is no path to the sign-off that skips Codex. + +## Preflight β€” it takes two to ClauDex + +Both halves must be present before ANY work starts. Claude Code is you β€” that +half is here by definition. Now verify the other half: + +1. Run `codex --version`. If the binary is missing, STOP immediately β€” do not + implement anything, do not review anything β€” and reply with exactly: + + > **It takes two to ClauDex.** 🧑 Claude is here β€” πŸ–€ Codex is not, so this + > would be *built with love by Claude alone*, and that's not the deal. + > Fix it in two lines, then come back for the duet: + > ``` + > npm i -g @openai/codex + > codex login + > ``` + +2. If the binary exists, verify authentication (`codex login status` or the + equivalent for the installed version). If not logged in, STOP the same way, + with the same message minus the install line β€” just `codex login`. +3. Run `git rev-parse --is-inside-work-tree`. If it doesn't print `true`, + STOP unsigned: ClauDex reviews diffs, so it needs a git repository + (`git init` if this project should become one). + +## The loop + +4. **Build.** If "$ARGUMENTS" is non-empty, implement it. If it is empty, + treat the current uncommitted changes as the work under review. +5. **Collect the change set.** Combine `git diff`, `git diff --staged`, and + every untracked file (list them with `git status --porcelain`, then append + each new file's path and content). **Sanity-check the scope:** if the + change set looks tiny relative to the work just done, check `git log` for + auto-generated commits (`[auto-checkpoint]`, `WIP`, hook-made commits) β€” + some setups commit continuously, silently draining the diff. In that case + diff against the last *human* commit instead (`git diff `). + If the change set is genuinely empty, STOP unsigned: "Nothing to review β€” + the tree is clean." +6. **Codex review β€” safe transport, never inline the diff in the shell.** + Write the change set to a temporary file (e.g. `$TMPDIR/claudex-review.patch`) + so no diff content passes through shell quoting, then invoke: + + ``` + codex exec --sandbox read-only "You are reviewing a teammate's change before merge. Read the diff at , then find real bugs, risky design choices, and missing edge cases. Be specific β€” cite files and lines. Do not restate the diff." + ``` + + Run it with a hard timeout of ~10 minutes β€” Codex reviews normally finish + in a few, but calls can hang on rate limits (especially right after a + previous heavy run). Delete the temp file afterwards. **If `codex exec` + exits non-zero, times out, or its output contains no recognizable review: + retry ONCE. If the retry also fails, STOP unsigned** and report: "The duet + was interrupted β€” Codex never completed its review, so nothing was + cross-checked and there is no πŸ§‘πŸ–€ today." Include the error, and mention + that rate limits usually clear within the hour. +7. **Triage.** For every Codex finding, decide: real β†’ fix it now; wrong β†’ + record a one-line reason. Never silently drop a finding. +8. **Iterate.** After fixing, run the Codex review again (same transport, + same timeout and failure rule) β€” but keep re-reviews cheap and focused: + send only the diff of the fixes plus a numbered list of the prior + findings, and ask for a one-line verdict per finding (RESOLVED / PARTIAL / + NOT ADDRESSED) plus any NEW blocking issue. Repeat until Codex reports no + blocking findings, up to 3 rounds. If a finding is still contested after + round 3, STOP unsigned: present both positions and end with "Deadlocked + after 3 rounds β€” the duet needs a referee. Unsigned until you decide." + +## Shipping (only reachable through consensus) + +9. Summarize for the user: what was built, what Codex caught, what you fixed, + and what you rejected (with reasons). +10. End your reply with exactly this line: + + `built with love by ClauDex πŸ§‘πŸ–€` + +11. Only if the user asks you to commit, use this trailer in the commit + message: + + ``` + built with love by ClauDex + + Co-Authored-By: Claude + Co-Authored-By: Codex + ``` + +## Ledger (feeds `/claudex:stats`) + +However the run ended β€” signed, deadlocked, interrupted, or +nothing-to-review (preflight refusals excluded: they did no work) β€” append +one JSON line to `/claudex/stats.jsonl` (resolve `` with +`git rev-parse --git-dir`; create the `claudex/` directory if needed): + +```json +{"ts":"","cmd":"loop","rounds":,"codex_findings":,"fixed":,"rejected":,"outcome":"signed|deadlock|interrupted|nothing-to-review"} +``` + +Living under the git dir, the ledger can never be committed. It is +best-effort: if the write fails, skip it silently β€” the ledger must never +affect the run's result or delay the user. diff --git a/plugins/claudex/commands/debate.md b/plugins/claudex/commands/debate.md new file mode 100644 index 0000000..4d83764 --- /dev/null +++ b/plugins/claudex/commands/debate.md @@ -0,0 +1,110 @@ +--- +description: The debate β€” Claude and Codex argue a design decision from opposite corners, you arbitrate +argument-hint: +--- + +You are running **ClauDex debate** β€” a structured argument between Claude Code +(you, 🧑) and OpenAI Codex (πŸ–€) over a real design decision. Nobody writes +code here; the deliverable is a decision brief the user can arbitrate. + +**Sign-off contract:** the closing line `argued with love by ClauDex πŸ§‘πŸ–€` +appears ONLY when Codex delivered both its opening position and its rebuttal β€” +and it is REQUIRED then (an earned, unsigned run breaks the contract just like +an unearned, signed one). Refusal, interruption, or an empty motion all end +UNSIGNED. The verb is "argued" β€” this command builds nothing and reviews no +diff; only the `/claudex` loop signs "built", only reviews sign "reviewed". + +## Preflight β€” it takes two to ClauDex + +1. Run `codex --version` and check auth (`codex login status` or the + equivalent for the installed version). If either fails, STOP before any + framing or arguing and reply with exactly: + + > **It takes two to ClauDex.** 🧑 Claude is here β€” πŸ–€ Codex is not, and a + > one-model debate is just a monologue. Fix it in two lines, then come + > back for the argument: + > ``` + > npm i -g @openai/codex + > codex login + > ``` + +2. **The motion.** "$ARGUMENTS" must state a decision. If it is empty, STOP + unsigned and ask for one, with two examples of a good motion β€” a decision + with real options ("Postgres vs SQLite for this app"), not a topic + ("databases"). + +(No git preflight β€” a debate needs a question, not a diff. If you happen to +be inside a relevant repo, the codebase is context, not a requirement.) + +## The debate + +1. **Frame the motion.** Sharpen "$ARGUMENTS" into a decision question with + 2–3 concrete options. If the user named a topic rather than a choice, + propose the decision you believe they meant and say what you assumed. + Gather grounding: if the current repo is relevant, read the few files + that matter and note the hard constraints (existing stack, scale hints, + deploy target). Compress all of it into a short written brief β€” motion, + options, constraints. Keep it under a page; a debate is not a survey. +2. **Claude's opening (yours).** Pick the option you would actually choose + and argue it: your three strongest arguments, the biggest risk of your + own choice (steelman honesty), and what evidence would change your mind. + Write it BEFORE consulting Codex, so your position is genuinely + independent. +3. **Codex's opening β€” safe transport.** Write the brief from step 1 to a + temp file (e.g. `$TMPDIR/claudex-debate.md`) β€” the motion, options, and + constraints only, NOT your position; never inline content in the shell + command. Then, with a hard timeout of ~10 minutes: + + ``` + codex exec --sandbox read-only "You are debating a design decision against a rival model. Read the brief at . Take a definite position: which option you would choose and why β€” your three strongest arguments, the biggest risk of your own choice, and what evidence would change your mind. Argue to win, but concede what is true." + ``` + + If `codex exec` exits non-zero, times out, or returns no recognizable + position: retry ONCE. If the retry also fails, delete the temp file and + STOP unsigned: "The duet was interrupted β€” Codex never took the floor, + so there was no debate and there is no πŸ§‘πŸ–€ today." Include the error, + and note that rate limits usually clear within the hour. +4. **The clash β€” one rebuttal round each, kept cheap.** Append both openings + to the temp file, labeled, then ask Codex for a terse rebuttal (quota + discipline β€” same spirit as the loop's focused re-reviews): + + ``` + codex exec --sandbox read-only "Read the debate so far at . Rebut your rival's opening in at most five bullets: what they get wrong, what you concede, and your final recommendation in one line." + ``` + + Same timeout and one-retry rule; if the rebuttal fails after the retry, + STOP unsigned the same way β€” never present a half-argued debate as done. + Then write your own rebuttal of Codex's opening under the same rules: + five bullets max, concede what is true, final recommendation in one line. + Delete the temp file afterwards. +5. **The decision brief.** Merge the debate into: + - **The motion** β€” one line. + - 🀝 **Common ground** β€” what both models agree on; treat it as settled. + - 🧑 **Claude's corner** β€” position, plus the strongest argument that + survived rebuttal. + - πŸ–€ **Codex's corner** β€” same. + - **The crux** β€” the ONE disagreement that actually decides it, phrased + as a question only the user can answer (their budget, team, timeline, + appetite for risk). +6. **The ruling.** + - If both final recommendations landed on the same option, declare + **CONSENSUS β€”