duet-cli 0.1.0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,160 @@
1
+ Metadata-Version: 2.4
2
+ Name: duet-cli
3
+ Version: 0.2.0
4
+ Summary: Two CLI agents in conversation. One Python file. Stdlib only.
5
+ Author: Volkan Altan
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/volkan/duet
8
+ Project-URL: Repository, https://github.com/volkan/duet
9
+ Keywords: agents,cli,claude,codex,llm,orchestration,pair-programming
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Software Development
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Provides-Extra: yaml
19
+ Requires-Dist: pyyaml; extra == "yaml"
20
+ Dynamic: license-file
21
+
22
+ # duet
23
+
24
+ **Two CLI agents in conversation. One Python file. Stdlib only.**
25
+
26
+ `duet` runs two command-line coding agents in alternating turns until they
27
+ agree. By default that is Claude and Codex; Gemini and Copilot are also
28
+ supported, and you can pair two agents from the same backend. One agent plans
29
+ or reviews while the other implements; each keeps its own session memory across
30
+ turns, and every run leaves a transcript you can inspect.
31
+
32
+ ## Use it three ways
33
+
34
+ ### 1. Inside Claude Code — `/duet`
35
+
36
+ The fastest path if you already live in Claude Code.
37
+
38
+ ```text
39
+ /plugin marketplace add volkan/duet
40
+ /plugin install duet@volkan-duet
41
+ /duet
42
+ ```
43
+
44
+ Plain `/duet` runs Claude Code's real `/review`, then loops Codex and Claude in
45
+ a worktree until they converge. Pass any upstream command as the kickoff:
46
+ `/duet 'npm test 2>&1' --turns 4`. The plugin shells out to the `duet` CLI, so
47
+ install that first (see below) and make sure `command -v duet` passes in Claude
48
+ Code's shell. Full guide:
49
+ [docs/CLAUDE_CODE_PLUGIN.md](https://github.com/volkan/duet/blob/main/docs/CLAUDE_CODE_PLUGIN.md).
50
+
51
+ ### 2. Inside Codex — `$duet`
52
+
53
+ ```text
54
+ codex plugin marketplace add volkan/duet
55
+ codex plugin add duet@volkan-duet
56
+ ```
57
+
58
+ Start a new Codex thread and invoke `$duet`, or just ask Codex to use duet in
59
+ plain language. Full guide:
60
+ [docs/CODEX_PLUGIN.md](https://github.com/volkan/duet/blob/main/docs/CODEX_PLUGIN.md).
61
+
62
+ ### 3. From the terminal — `duet`
63
+
64
+ ```bash
65
+ pipx install duet-cli # the command it installs is `duet`
66
+ duet --task "Fix the failing test" --cwd ~/code/myrepo
67
+ ```
68
+
69
+ The PyPI package is `duet-cli` (bare `duet` on PyPI is Google's async library),
70
+ so `pipx`/`uvx` isolation is recommended. Add `'duet-cli[yaml]'` if you want
71
+ `--config foo.yaml`. One-shot, no install:
72
+ `uvx --from duet-cli duet --task "..."`.
73
+
74
+ ## Examples
75
+
76
+ Each command teaches one capability. The partner agent speaks first.
77
+
78
+ **Review loop** — Codex reviews at max effort, Claude applies only the fixes
79
+ Codex asks for, in an isolated worktree:
80
+
81
+ ```bash
82
+ duet --task "Review the latest commit; fix only what the reviewer requests." \
83
+ --lead claude:coder --partner codex:reviewer \
84
+ --reasoning max --worktree --worktree-for lead --turns 6
85
+ ```
86
+
87
+ **Seed from another tool's output** — drive the loop from Claude Code's real
88
+ `/review`, a test run, or any command:
89
+
90
+ ```bash
91
+ duet --task-from-cmd 'claude -p /review' \
92
+ --lead claude:reviewer --partner codex:coder \
93
+ --worktree --recap --cwd ~/workspace/project --turns 6
94
+ ```
95
+
96
+ **Deep planner, fast coder** — Claude plans at high effort while Codex coder
97
+ turns drop to low for latency:
98
+
99
+ ```bash
100
+ duet --reasoning high --codex-fast \
101
+ --task "Fix the issue" --cwd ~/workspace/project
102
+ ```
103
+
104
+ **Verify gate** — a convergence proposal only counts if `make test` exits 0;
105
+ any failure feeds back into the next turn:
106
+
107
+ ```bash
108
+ duet --task "Fix the issue" \
109
+ --lead claude:coder --partner codex:reviewer \
110
+ --verify-cmd 'make test' --worktree --worktree-for lead
111
+ ```
112
+
113
+ **Resume a plan** — plan with Codex in its own session, then hand the session
114
+ id to duet; Codex implements with the plan in context while Claude reviews
115
+ (`--resume-claude <id>` does the inverse):
116
+
117
+ ```bash
118
+ duet --resume-codex <codex-session-id> --worktree --reasoning max \
119
+ --task "Implement the plan from your Codex planning session."
120
+ ```
121
+
122
+ Reusable configs ship under `examples/` — `pr-review.yaml` (deep review of
123
+ `HEAD`) and `codex-test-fix.yaml` (Codex planner diagnoses failing checks, Codex
124
+ coder fixes them). Run one with `duet --config examples/pr-review.yaml`.
125
+
126
+ ## How it works
127
+
128
+ Each agent keeps its own conversation memory across turns (Claude via
129
+ `--resume`, Codex via `codex exec resume`, Gemini and Copilot via their JSON
130
+ session ids). On each turn duet sends one agent's latest reply to the other.
131
+
132
+ To converge, an agent must include an `LGTM rationale:` explaining why the work
133
+ is done, followed by the sentinel `<<<LGTM>>>` on its own line — a bare
134
+ sentinel is ignored, and **both** agents must agree in back-to-back turns. The
135
+ loop also stops on `--turns`, a per-turn timeout, or Ctrl-C. After a normal
136
+ stop, duet opens a `force>` prompt so you can push another round.
137
+
138
+ Every run writes a directory with `transcript.md`, `state.json`, per-turn
139
+ stderr logs, and the `wt/` worktree when `--worktree` is on. Inspect a run with
140
+ `duet --status <run-id>`, list runs with `duet --list`, and start a fresh run
141
+ from saved state with `duet --continue <run> --task "next thing"`.
142
+
143
+ - **Backends:** `claude`, `codex`, `gemini`, `copilot`
144
+ - **Roles:** `planner`, `coder`, `reviewer`, `triage-reviewer`, or a custom one
145
+ - **Reasoning:** `--reasoning minimal|low|medium|high|xhigh|max`
146
+
147
+ ## Documentation
148
+
149
+ [docs/USAGE.md](https://github.com/volkan/duet/blob/main/docs/USAGE.md) is the
150
+ full reference: every flag, reasoning levels, session memory, output layout,
151
+ `--status` / `--continue`, the force prompt, Codex sandbox and network rules,
152
+ and worktree mode.
153
+
154
+ ## Contributing
155
+
156
+ Contributor guidance is in
157
+ [CLAUDE.md](https://github.com/volkan/duet/blob/main/CLAUDE.md); Codex entry
158
+ notes are in [AGENTS.md](https://github.com/volkan/duet/blob/main/AGENTS.md).
159
+ CI runs on every PR and is advisory until marked required — see
160
+ [.github/BRANCH_PROTECTION.md](https://github.com/volkan/duet/blob/main/.github/BRANCH_PROTECTION.md).
@@ -0,0 +1,139 @@
1
+ # duet
2
+
3
+ **Two CLI agents in conversation. One Python file. Stdlib only.**
4
+
5
+ `duet` runs two command-line coding agents in alternating turns until they
6
+ agree. By default that is Claude and Codex; Gemini and Copilot are also
7
+ supported, and you can pair two agents from the same backend. One agent plans
8
+ or reviews while the other implements; each keeps its own session memory across
9
+ turns, and every run leaves a transcript you can inspect.
10
+
11
+ ## Use it three ways
12
+
13
+ ### 1. Inside Claude Code — `/duet`
14
+
15
+ The fastest path if you already live in Claude Code.
16
+
17
+ ```text
18
+ /plugin marketplace add volkan/duet
19
+ /plugin install duet@volkan-duet
20
+ /duet
21
+ ```
22
+
23
+ Plain `/duet` runs Claude Code's real `/review`, then loops Codex and Claude in
24
+ a worktree until they converge. Pass any upstream command as the kickoff:
25
+ `/duet 'npm test 2>&1' --turns 4`. The plugin shells out to the `duet` CLI, so
26
+ install that first (see below) and make sure `command -v duet` passes in Claude
27
+ Code's shell. Full guide:
28
+ [docs/CLAUDE_CODE_PLUGIN.md](https://github.com/volkan/duet/blob/main/docs/CLAUDE_CODE_PLUGIN.md).
29
+
30
+ ### 2. Inside Codex — `$duet`
31
+
32
+ ```text
33
+ codex plugin marketplace add volkan/duet
34
+ codex plugin add duet@volkan-duet
35
+ ```
36
+
37
+ Start a new Codex thread and invoke `$duet`, or just ask Codex to use duet in
38
+ plain language. Full guide:
39
+ [docs/CODEX_PLUGIN.md](https://github.com/volkan/duet/blob/main/docs/CODEX_PLUGIN.md).
40
+
41
+ ### 3. From the terminal — `duet`
42
+
43
+ ```bash
44
+ pipx install duet-cli # the command it installs is `duet`
45
+ duet --task "Fix the failing test" --cwd ~/code/myrepo
46
+ ```
47
+
48
+ The PyPI package is `duet-cli` (bare `duet` on PyPI is Google's async library),
49
+ so `pipx`/`uvx` isolation is recommended. Add `'duet-cli[yaml]'` if you want
50
+ `--config foo.yaml`. One-shot, no install:
51
+ `uvx --from duet-cli duet --task "..."`.
52
+
53
+ ## Examples
54
+
55
+ Each command teaches one capability. The partner agent speaks first.
56
+
57
+ **Review loop** — Codex reviews at max effort, Claude applies only the fixes
58
+ Codex asks for, in an isolated worktree:
59
+
60
+ ```bash
61
+ duet --task "Review the latest commit; fix only what the reviewer requests." \
62
+ --lead claude:coder --partner codex:reviewer \
63
+ --reasoning max --worktree --worktree-for lead --turns 6
64
+ ```
65
+
66
+ **Seed from another tool's output** — drive the loop from Claude Code's real
67
+ `/review`, a test run, or any command:
68
+
69
+ ```bash
70
+ duet --task-from-cmd 'claude -p /review' \
71
+ --lead claude:reviewer --partner codex:coder \
72
+ --worktree --recap --cwd ~/workspace/project --turns 6
73
+ ```
74
+
75
+ **Deep planner, fast coder** — Claude plans at high effort while Codex coder
76
+ turns drop to low for latency:
77
+
78
+ ```bash
79
+ duet --reasoning high --codex-fast \
80
+ --task "Fix the issue" --cwd ~/workspace/project
81
+ ```
82
+
83
+ **Verify gate** — a convergence proposal only counts if `make test` exits 0;
84
+ any failure feeds back into the next turn:
85
+
86
+ ```bash
87
+ duet --task "Fix the issue" \
88
+ --lead claude:coder --partner codex:reviewer \
89
+ --verify-cmd 'make test' --worktree --worktree-for lead
90
+ ```
91
+
92
+ **Resume a plan** — plan with Codex in its own session, then hand the session
93
+ id to duet; Codex implements with the plan in context while Claude reviews
94
+ (`--resume-claude <id>` does the inverse):
95
+
96
+ ```bash
97
+ duet --resume-codex <codex-session-id> --worktree --reasoning max \
98
+ --task "Implement the plan from your Codex planning session."
99
+ ```
100
+
101
+ Reusable configs ship under `examples/` — `pr-review.yaml` (deep review of
102
+ `HEAD`) and `codex-test-fix.yaml` (Codex planner diagnoses failing checks, Codex
103
+ coder fixes them). Run one with `duet --config examples/pr-review.yaml`.
104
+
105
+ ## How it works
106
+
107
+ Each agent keeps its own conversation memory across turns (Claude via
108
+ `--resume`, Codex via `codex exec resume`, Gemini and Copilot via their JSON
109
+ session ids). On each turn duet sends one agent's latest reply to the other.
110
+
111
+ To converge, an agent must include an `LGTM rationale:` explaining why the work
112
+ is done, followed by the sentinel `<<<LGTM>>>` on its own line — a bare
113
+ sentinel is ignored, and **both** agents must agree in back-to-back turns. The
114
+ loop also stops on `--turns`, a per-turn timeout, or Ctrl-C. After a normal
115
+ stop, duet opens a `force>` prompt so you can push another round.
116
+
117
+ Every run writes a directory with `transcript.md`, `state.json`, per-turn
118
+ stderr logs, and the `wt/` worktree when `--worktree` is on. Inspect a run with
119
+ `duet --status <run-id>`, list runs with `duet --list`, and start a fresh run
120
+ from saved state with `duet --continue <run> --task "next thing"`.
121
+
122
+ - **Backends:** `claude`, `codex`, `gemini`, `copilot`
123
+ - **Roles:** `planner`, `coder`, `reviewer`, `triage-reviewer`, or a custom one
124
+ - **Reasoning:** `--reasoning minimal|low|medium|high|xhigh|max`
125
+
126
+ ## Documentation
127
+
128
+ [docs/USAGE.md](https://github.com/volkan/duet/blob/main/docs/USAGE.md) is the
129
+ full reference: every flag, reasoning levels, session memory, output layout,
130
+ `--status` / `--continue`, the force prompt, Codex sandbox and network rules,
131
+ and worktree mode.
132
+
133
+ ## Contributing
134
+
135
+ Contributor guidance is in
136
+ [CLAUDE.md](https://github.com/volkan/duet/blob/main/CLAUDE.md); Codex entry
137
+ notes are in [AGENTS.md](https://github.com/volkan/duet/blob/main/AGENTS.md).
138
+ CI runs on every PR and is advisory until marked required — see
139
+ [.github/BRANCH_PROTECTION.md](https://github.com/volkan/duet/blob/main/.github/BRANCH_PROTECTION.md).