Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
17 changes: 17 additions & 0 deletions plugins/claudex/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
14 changes: 14 additions & 0 deletions plugins/claudex/README.md
Original file line number Diff line number Diff line change
@@ -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
```
110 changes: 110 additions & 0 deletions plugins/claudex/commands/claudex.md
Original file line number Diff line number Diff line change
@@ -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 <that-sha>`).
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 <absolute path to the temp file>, 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 <noreply@anthropic.com>
Co-Authored-By: Codex <noreply@openai.com>
```

## 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 `<git-dir>/claudex/stats.jsonl` (resolve `<git-dir>` with
`git rev-parse --git-dir`; create the `claudex/` directory if needed):

```json
{"ts":"<UTC ISO-8601>","cmd":"loop","rounds":<completed review rounds>,"codex_findings":<total>,"fixed":<n>,"rejected":<n>,"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.
110 changes: 110 additions & 0 deletions plugins/claudex/commands/debate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
description: The debate — Claude and Codex argue a design decision from opposite corners, you arbitrate
argument-hint: <the decision to debate, e.g. "Postgres vs SQLite for this app" or "should this service be split?">
---

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 <absolute temp file path>. 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 <absolute temp file path>. 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 — <option>**: two rivals who tried to win and converged
anyway is the strongest signal this process produces.
- Otherwise declare **SPLIT DECISION** and end with "You arbitrate." —
do not break the tie in the ruling; your vote is already on the record
in Claude's corner.
7. Close with exactly this line:

`argued with love by ClauDex 🧡🖤`

8. **Ledger (feeds `/claudex:stats`).** Only if inside a git repo (debates
don't require one): however the run ended — signed or interrupted
(preflight refusals and empty motions excluded) — append one JSON line
to `<git-dir>/claudex/stats.jsonl` (via `git rev-parse --git-dir`;
create the `claudex/` directory if needed):

```json
{"ts":"<UTC ISO-8601>","cmd":"debate","ruling":"CONSENSUS|SPLIT","outcome":"signed|interrupted"}
```

Best-effort and silent on failure; it must never affect the debate.
92 changes: 92 additions & 0 deletions plugins/claudex/commands/demo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
description: A two-minute guided duet — plants bugs in a throwaway repo and lets Claude and Codex argue about them
---

You are running the **ClauDex demo** — a safe, self-contained first experience
of the duet. You will plant bugs, let both models review them independently,
and reveal who caught what. Everything happens in a throwaway directory;
the user's own files are never touched.

**Sign-off contract:** this is a real review, so the normal rules apply — end
with `reviewed with love by ClauDex 🧡🖤` ONLY if Codex successfully delivered
its review; if the Codex call fails (after one retry), end unsigned with the
interruption message.

## Preflight — it takes two to ClauDex

Run `codex --version` and check auth (`codex login status` or equivalent).
If either fails, STOP and reply with exactly:

> **It takes two to ClauDex.** 🧡 Claude is here — 🖤 Codex is not, so there is
> no duet to demo. Fix it in two lines, then come back:
> ```
> npm i -g @openai/codex
> codex login
> ```

(No git preflight — the demo brings its own repo.)

## The demo

1. **Set the stage.** Create a throwaway workspace and repo:
`DEMO=$(mktemp -d "${TMPDIR:-/tmp}/claudex-demo.XXXXXX") && git -C "$DEMO" init -q`
2. **Plant the bugs.** Write exactly this to `$DEMO/discount.js`:

```js
// discount.js — apply coupon discounts to a shopping cart
function applyDiscount(cart, coupon) {
let total = 0;
for (let i = 0; i <= cart.length; i++) {
total += cart[i].price * cart[i].qty;
}

if (coupon.type == "percent") {
total = total - (total * coupon.value) / 100;
} else {
total = total - coupon.value;
}

cart.forEach((item) => (item.discounted = true));

return "$" + total.toFixed(2);
}

module.exports = { applyDiscount };
```

For your own reveal later, the planted issues are: (a) off-by-one
`i <= cart.length` — guaranteed crash; (b) no validation of
`coupon.value` — negative totals, >100% discounts; (c) loose `==`
comparison; (d) the function silently mutates the caller's cart;
(e) floating-point money math. Do NOT tell either reviewer this list.
3. **Tell the user what's happening** in two sentences: bugs are planted —
some obvious, some subtle, one a pure judgment call — and the two models
will now review the same file *independently*.
4. **Claude's review (yours).** Review `discount.js` and write down your
findings BEFORE consulting Codex.
5. **Codex's review.** With a hard timeout of ~10 minutes:

```
codex exec --sandbox read-only "You are reviewing a teammate's new file before merge. Read the file at $DEMO/discount.js and find real bugs, risky design choices, and missing edge cases. Be specific — cite lines."
```

If it fails or times out, retry ONCE; if that fails too, clean up the
demo directory and STOP unsigned: "The duet was interrupted — Codex never
completed its review. Try `/claudex:demo` again in a little while (rate
limits usually clear within the hour)."
6. **The Verdict table.** Merge both reviews:
- 🤝 **Both flagged**
- 🧡 **Only Claude flagged**
- 🖤 **Only Codex flagged**
7. **The reveal.** Show the planted-bug scoreboard: for each of (a)–(e),
which models caught it — and highlight anything either model found that
you didn't plant. Spell out the lesson in one line: agreement is signal,
disagreement is where a human looks.
8. **Clean up.** Remove the throwaway directory (`rm -rf "$DEMO"` — it is a
directory you created under the system temp path this run; never remove
anything else).
9. **Point at real life:** "That was a toy. Run `/claudex:verdict` on your
actual uncommitted changes, or `/claudex <task>` to build with the
reviewer in the loop." Then close with:

`reviewed with love by ClauDex 🧡🖤`
25 changes: 25 additions & 0 deletions plugins/claudex/commands/setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
description: Verify ClauDex prerequisites — Codex CLI, authentication, and git
---

Check each prerequisite and report it as ✅ or ❌ with the exact fix command:

1. **Codex CLI installed** — `codex --version`
(fix: `npm i -g @openai/codex`)
2. **Codex authenticated** — `codex login status` or the equivalent for the
installed version (fix: `codex login`)
3. **Inside a git repo** — `git rev-parse --is-inside-work-tree`. Distinguish
the two failure modes: git not installed (fix: `xcode-select --install` on
macOS, `apt install git`/`winget install Git.Git` elsewhere) vs. not a
repository (fix: `git init` — ClauDex reviews diffs, so it needs one)
4. **Optional:** the official Codex plugin for `/codex:*` commands
(`/plugin marketplace add openai/codex-plugin-cc`, then `/plugin install codex@openai-codex`)

When everything passes, reply:
"ClauDex is ready. Claude writes, Codex reviews, you ship. 🧡🖤
First time? Run `/claudex:demo` — two minutes, zero risk: watch the two
models argue over planted bugs before you point them at real code."

If the Codex CLI or its login is missing, end with:
"**It takes two to ClauDex.** 🧡 Claude is here — 🖤 Codex is not. Run the fix
commands above, then `/claudex:setup` again for the duet."
Loading