Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

duet

You pay for Claude and ChatGPT. On any given question you ask one of them.

licence MIT bash dependencies none agents 2

Terminal replay: duet asks Claude Code and Codex about UUIDv4 primary keys, then reports that Claude overgeneralized its claim about secondary indexes

duet asks both — independently, neither seeing the other — then reports where they disagree.
Not a merged consensus answer. The disagreements are the product.


That run is real, and it is the whole pitch: Claude got something wrong, confidently, and nothing inside a single-agent session would have flagged it.

 Read the full comparison from that run 

Agreed

Both say UUIDv4's random B-tree insertion can hurt sustained 5k/s once the index exceeds memory, and that UUIDv7 or an ordered numeric key is the practical alternative.

Disagreements

Claude presents the impact as visible "within days"; Codex says it ranges from negligible to material. 5k/s alone does not determine the outcome — row size, index count, RAM, storage, fillfactor and checkpoints do. Settle it with a production-shaped v4-vs-v7 load test measuring p95 insert latency, WAL bytes and index size.

Claude says the issue "hits every secondary index and any FK columns." Codex limits the claim to the UUID PK index. Claude overgeneralizes: only indexes whose inserted key distribution is random UUID-like have this exact locality problem.

Where this lands

Neither answer is factually wrong overall. The unresolved decision is whether your workload's measured write cost justifies an ID migration.

Both raw answers are in example.md.

How it works

A question fans out to Claude Code and Codex in parallel, blind to each other. Both run read-only. A comparison pass reads both answers and produces a report led by the disagreements.

That diagram is the entire architecture. One bash script, no config file, no daemon, no state, nothing sent anywhere except the two vendors you already trust with these prompts.

Why bother

A model's confident wrong answer looks exactly like its confident right answer. Two models from different labs, answering blind, produce uncorrelated errors — so a disagreement is a signal that something is genuinely unsettled, and it points at the specific claim worth checking.

Worth running when being wrong is expensive: architecture decisions, migration plans, security reasoning, "is this actually safe to deploy". Not worth running on the other 95% of your prompts.

Install

Needs Claude Code and Codex installed and logged in. Any plan — duet drives the CLIs you already have, so there are no API keys and no metered billing.

git clone https://github.com/Chirudeva-Reddy/duet && cd duet
install -m 755 duet ~/.local/bin/duet   # or anywhere on your PATH
duet --selftest
$ duet --selftest
OK        claude answered, and could not write to disk
OK        codex answered, and could not write to disk
duet is ready.
 What --selftest actually proves 

It does not check that the sandbox flags still exist. It gives each agent a scratch directory and tells it to write a file there by any means available — file write, shell redirection, anything — then asserts that nothing landed on disk.

That tests the guarantee rather than the flag name. A sandbox flag that is removed, renamed, or quietly weakened all fail the same way:

$ duet --selftest
BREACH    codex wrote to disk while sandboxed read-only:
            /var/folders/…/canary.txt
          Do not point duet at anything you care about until this is fixed.
duet is NOT ready — fix the above.

It costs two agent turns, so run it after an install or a CLI upgrade, not habitually.

Verified against

Claude Code 2.1.251
Codex CLI 0.149.1
Shell macOS system bash 3.2, and newer

Use

duet "your question"                   # ask both, get the diff
duet -C ~/src/api "review the session handling on this branch for auth bypass"
cat rfc.md | duet                      # pipe a plan in
duet -n "..."                          # skip the comparison, just print both answers

Both agents run read-only. Pointed at a repo with -C they read your real files and run git log / git diff — they just cannot edit anything. That is the advantage over pasting the same question into two browser tabs.

flag
-C DIR working root for both agents (default .)
-s claude|codex who writes the comparison (default codex)
-t SECONDS per-agent timeout (default 600)
-o FILE report path (default duet-<timestamp>.md)
-n skip the comparison pass
--selftest check both CLIs answer, and that neither can write to disk

Env: DUET_SYNTH, DUET_TIMEOUT.

What it costs

No API keys, no per-token billing — but it is not free. It spends the monthly usage limits you are already paying for, and faster than a chat message does.

One duet run is three agent turns:

default (-s codex) flipped (-s claude)
Claude 1 turn 2 turns
Codex 2 turns 1 turn
  • These are agentic turns, not chat messages. With -C on a large repo, each agent may read many files before answering. That costs materially more of your limit than typing the same question into the app.
  • Codex writes the comparison by default because the Claude $20 plan has the tighter limit of the two. If your limits run the other way, -s claude.
  • Called from a Claude Code session (below), the surrounding session is additional Claude usage on top of the table.
  • Do not automate it. No git hooks, no CI, no loops. Three turns per question adds up fast, and questions that only needed one answer get one answer for free.

Run it on decisions. That is where three turns is obviously cheaper than being wrong.

 Use it as a /duet slash command in Claude Code 

Drop this in ~/.claude/commands/duet.md and /duet <question> works in any project:

---
description: Cross-check a question against both Claude Code and Codex, then report where they disagree
argument-hint: [-C dir] <question to cross-check>
allowed-tools: Bash
---

The user wants an independent second opinion on: **$ARGUMENTS**

1. Run `duet -C . -t 240 -o "/tmp/duet-$(date +%s).md" "<question, as one quoted argument>"`
   with the Bash tool, timeout 540000ms. Keep `-t 240` — higher values can outlast the
   Bash tool's own timeout. Takes 1–3 minutes; run it in the foreground.
2. Report back: the disagreements first, then what one agent caught alone, then one line on
   what they agreed, then the report path.
3. Do not adjudicate the disagreement unless asked. You are Claude, and one of the two answers
   is Claude's — if you weigh in, say so rather than presenting it as a neutral tiebreak.

That last rule matters. The agent relaying the report is one of the two panelists.

Design notes

Deliberately not included: auto-triggering on "important" prompts, a third agent, voting or scoring, session history. You invoke it by hand on the questions that earn it.

Two panelists, no tiebreaker — on purpose. duet tells you that two capable models split on a claim and what would settle it. Deciding stays yours. A third panelist would mostly let you launder a 2–1 vote into an answer, and a majority vote among models trained on largely the same internet is not the independent check it looks like.

Swapping a panelist is a different question from adding one, and swaps are welcome — see below.

Editable diagram source: docs/architecture.excalidraw — open it at excalidraw.com.

Contributing

Issues and PRs welcome. Useful directions:

  • more CLIs as alternative panelists — Gemini CLI, Cursor, opencode. Substitution, not addition: duet stays two voices, but which two should be yours to choose.
  • sharper comparison prompts — the current one is a first draft
  • --json output for scripting

MIT. See LICENSE.

About

Ask Claude Code and Codex the same question independently, then report where they disagree. One bash script, no API keys.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages