Skip to main content

Two CLI agents in conversation. One Python file. Stdlib only.

Project description

duet

Two CLI agents in conversation. One Python file. Stdlib only.

duet runs two command-line coding agents in alternating turns until they agree. By default that is Claude and Codex; Gemini and Copilot are also supported, and you can pair two agents from the same backend. One agent plans or reviews while the other implements; each keeps its own session memory across turns, and every run leaves a transcript you can inspect.

Use it three ways

1. Inside Claude Code — /duet

The fastest path if you already live in Claude Code.

/plugin marketplace add volkan/duet
/plugin install duet@volkan-duet
/duet

Plain /duet runs Claude Code's real /review, then loops Codex and Claude in a worktree until they converge. Pass any upstream command as the kickoff: /duet 'npm test 2>&1' --turns 4. The plugin shells out to the duet CLI, so install that first (see below) and make sure command -v duet passes in Claude Code's shell. Full guide: docs/CLAUDE_CODE_PLUGIN.md. If Claude Code disambiguates plugin commands with namespaces, /duet:duet is the same command.

Autonomous handoff example:

Claude Code handoff using duet

While the handoff runs, Claude Code shows the shell in auto mode and exposes the exact duet command under shell details:

Claude Code auto mode shell status

Claude Code shell details running duet

Copy-ready version:

/loop /goal Create a temporary todo.md from the plan above and the remaining
tasks in todo_codex.md.

1. Use /duet:duet with max reasoning to confirm the plan.
2. After the plan is confirmed, implement it.
3. Once the first implementation is done, use /duet:duet with max reasoning
   for code review.
4. Use /duet:duet with max reasoning to review the second plan, then implement
   it.
5. When the process is complete and all checks are green, merge the approved
   changes.

P.S. I will not be around, so handle decisions without me. If you need another
opinion, use /duet:duet to discuss it with Codex.

2. Inside Codex — $duet

codex plugin marketplace add volkan/duet
codex plugin add duet@volkan-duet

Start a new Codex thread and invoke $duet, or just ask Codex to use duet in plain language. Like the Claude Code plugin, the skill shells out to the duet CLI, so install that first (see below) and make sure command -v duet passes in Codex's shell. Full guide: docs/CODEX_PLUGIN.md.

3. From the terminal — duet

pipx install duet-cli        # recommended; the command it installs is `duet`
duet --task "Fix the failing test" --cwd ~/code/myrepo

pipx is the recommended install. Two other persistent options put duet on PATH the same way:

uv tool install duet-cli
python3 -m pip install --user duet-cli

The PyPI package is duet-cli (bare duet on PyPI is Google's async library). Add the [yaml] extra for --config foo.yaml support — pipx install 'duet-cli[yaml]', uv tool install 'duet-cli[yaml]', or python3 -m pip install --user 'duet-cli[yaml]'. One-shot, no install: uvx --from duet-cli duet --task "..." — note this is ephemeral and does not put duet on PATH, so the /duet and $duet plugins need a persistent install (pipx install duet-cli, uv tool install duet-cli, python3 -m pip install --user duet-cli, or make install) instead.

Examples

Each command teaches one capability. The partner agent speaks first.

Review loop — Codex reviews at max effort, Claude applies only the fixes Codex asks for, in an isolated worktree:

duet --task "Review the latest commit; fix only what the reviewer requests." \
    --lead claude:coder --partner codex:reviewer \
    --reasoning max --worktree --worktree-for lead --turns 6

Seed from another tool's output — drive the loop from Claude Code's real /review, a test run, or any command:

duet --task-from-cmd 'claude -p /review' \
    --lead claude:reviewer --partner codex:coder \
    --worktree --recap --cwd ~/workspace/project --turns 6

Deep planner, fast coder — Claude plans at high effort while Codex coder turns drop to low for latency:

duet --reasoning high --codex-fast \
    --task "Fix the issue" --cwd ~/workspace/project

Verify gate — a convergence proposal only counts if make test exits 0; any failure feeds back into the next turn:

duet --task "Fix the issue" \
    --lead claude:coder --partner codex:reviewer \
    --verify-cmd 'make test' --worktree --worktree-for lead

Resume a plan — plan with Codex in its own session, then hand the session id to duet; Codex implements with the plan in context while Claude reviews (--resume-claude <id> does the inverse):

duet --resume-codex <codex-session-id> --worktree --reasoning max \
    --task "Implement the plan from your Codex planning session."

Reusable configs ship under examples/pr-review.yaml (deep review of HEAD) and codex-test-fix.yaml (Codex planner diagnoses failing checks, Codex coder fixes them). Run one with duet --config examples/pr-review.yaml.

How it works

Each agent keeps its own conversation memory across turns (Claude via --resume, Codex via codex exec resume, Gemini and Copilot via their JSON session ids). On each turn duet sends one agent's latest reply to the other.

To converge, an agent must include an LGTM rationale: explaining why the work is done, followed by the sentinel <<<LGTM>>> on its own line — a bare sentinel is ignored, and both agents must agree in back-to-back turns. The loop also stops on --turns, a per-turn timeout, or Ctrl-C. After a normal stop, duet opens a force> prompt so you can push another round.

Every run writes a directory with transcript.md, state.json, per-turn stderr logs, and the wt/ worktree when --worktree is on. Inspect a run with duet --status <run-id>, list runs with duet --list, and start a fresh run from saved state with duet --continue <run> --task "next thing".

  • Backends: claude, codex, gemini, copilot
  • Roles: planner, coder, reviewer, triage-reviewer, or a custom one
  • Reasoning: --reasoning minimal|low|medium|high|xhigh|max

Documentation

docs/USAGE.md is the full reference: every flag, reasoning levels, session memory, output layout, --status / --continue, the force prompt, Codex sandbox and network rules, and worktree mode.

Contributing

Contributor guidance is in CLAUDE.md; Codex entry notes are in AGENTS.md. CI runs on every PR and is advisory until marked required — see .github/BRANCH_PROTECTION.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

duet_cli-0.2.5.tar.gz (58.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

duet_cli-0.2.5-py3-none-any.whl (46.4 kB view details)

Uploaded Python 3

File details

Details for the file duet_cli-0.2.5.tar.gz.

File metadata

  • Download URL: duet_cli-0.2.5.tar.gz
  • Upload date:
  • Size: 58.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for duet_cli-0.2.5.tar.gz
Algorithm Hash digest
SHA256 03b665da094a92a5ba025fcac2e4d708a9b9632dbb9fe0e5bb86c92813df2ddb
MD5 a2ddd40fd724e87c693464ab53d33cad
BLAKE2b-256 3d8a69cdf3f5dfa80bae6b71f1da1afcc8d9f1dffebec5aedfee0a3f62c79bd6

See more details on using hashes here.

Provenance

The following attestation bundles were made for duet_cli-0.2.5.tar.gz:

Publisher: release.yml on volkan/duet

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file duet_cli-0.2.5-py3-none-any.whl.

File metadata

  • Download URL: duet_cli-0.2.5-py3-none-any.whl
  • Upload date:
  • Size: 46.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for duet_cli-0.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 7117b6c01fe0751ef4b0d46221ca035ec8bfb7dd98abf8dd0bd3696a77907cfa
MD5 00eb7d552865f827a9aa4e6fdb1b9d5c
BLAKE2b-256 bfd51ec305fc0de7edb346557831ca7234dd56123e7a4fbadbb720c9c51c378b

See more details on using hashes here.

Provenance

The following attestation bundles were made for duet_cli-0.2.5-py3-none-any.whl:

Publisher: release.yml on volkan/duet

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page