duet-cli 0.1.0__tar.gz → 0.2.1__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,164 @@
1
+ Metadata-Version: 2.4
2
+ Name: duet-cli
3
+ Version: 0.2.1
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. Like the Claude Code plugin, the skill shells out to the `duet`
60
+ CLI, so install that first (see below) and make sure `command -v duet` passes in
61
+ Codex's shell. Full guide:
62
+ [docs/CODEX_PLUGIN.md](https://github.com/volkan/duet/blob/main/docs/CODEX_PLUGIN.md).
63
+
64
+ ### 3. From the terminal — `duet`
65
+
66
+ ```bash
67
+ pipx install duet-cli # the command it installs is `duet`
68
+ duet --task "Fix the failing test" --cwd ~/code/myrepo
69
+ ```
70
+
71
+ The PyPI package is `duet-cli` (bare `duet` on PyPI is Google's async library),
72
+ so `pipx`/`uvx` isolation is recommended. Add `'duet-cli[yaml]'` if you want
73
+ `--config foo.yaml`. One-shot, no install:
74
+ `uvx --from duet-cli duet --task "..."` — note this is ephemeral and does not put
75
+ `duet` on PATH, so the `/duet` and `$duet` plugins need a persistent install
76
+ (`pipx install duet-cli` or `make install`) instead.
77
+
78
+ ## Examples
79
+
80
+ Each command teaches one capability. The partner agent speaks first.
81
+
82
+ **Review loop** — Codex reviews at max effort, Claude applies only the fixes
83
+ Codex asks for, in an isolated worktree:
84
+
85
+ ```bash
86
+ duet --task "Review the latest commit; fix only what the reviewer requests." \
87
+ --lead claude:coder --partner codex:reviewer \
88
+ --reasoning max --worktree --worktree-for lead --turns 6
89
+ ```
90
+
91
+ **Seed from another tool's output** — drive the loop from Claude Code's real
92
+ `/review`, a test run, or any command:
93
+
94
+ ```bash
95
+ duet --task-from-cmd 'claude -p /review' \
96
+ --lead claude:reviewer --partner codex:coder \
97
+ --worktree --recap --cwd ~/workspace/project --turns 6
98
+ ```
99
+
100
+ **Deep planner, fast coder** — Claude plans at high effort while Codex coder
101
+ turns drop to low for latency:
102
+
103
+ ```bash
104
+ duet --reasoning high --codex-fast \
105
+ --task "Fix the issue" --cwd ~/workspace/project
106
+ ```
107
+
108
+ **Verify gate** — a convergence proposal only counts if `make test` exits 0;
109
+ any failure feeds back into the next turn:
110
+
111
+ ```bash
112
+ duet --task "Fix the issue" \
113
+ --lead claude:coder --partner codex:reviewer \
114
+ --verify-cmd 'make test' --worktree --worktree-for lead
115
+ ```
116
+
117
+ **Resume a plan** — plan with Codex in its own session, then hand the session
118
+ id to duet; Codex implements with the plan in context while Claude reviews
119
+ (`--resume-claude <id>` does the inverse):
120
+
121
+ ```bash
122
+ duet --resume-codex <codex-session-id> --worktree --reasoning max \
123
+ --task "Implement the plan from your Codex planning session."
124
+ ```
125
+
126
+ Reusable configs ship under `examples/` — `pr-review.yaml` (deep review of
127
+ `HEAD`) and `codex-test-fix.yaml` (Codex planner diagnoses failing checks, Codex
128
+ coder fixes them). Run one with `duet --config examples/pr-review.yaml`.
129
+
130
+ ## How it works
131
+
132
+ Each agent keeps its own conversation memory across turns (Claude via
133
+ `--resume`, Codex via `codex exec resume`, Gemini and Copilot via their JSON
134
+ session ids). On each turn duet sends one agent's latest reply to the other.
135
+
136
+ To converge, an agent must include an `LGTM rationale:` explaining why the work
137
+ is done, followed by the sentinel `<<<LGTM>>>` on its own line — a bare
138
+ sentinel is ignored, and **both** agents must agree in back-to-back turns. The
139
+ loop also stops on `--turns`, a per-turn timeout, or Ctrl-C. After a normal
140
+ stop, duet opens a `force>` prompt so you can push another round.
141
+
142
+ Every run writes a directory with `transcript.md`, `state.json`, per-turn
143
+ stderr logs, and the `wt/` worktree when `--worktree` is on. Inspect a run with
144
+ `duet --status <run-id>`, list runs with `duet --list`, and start a fresh run
145
+ from saved state with `duet --continue <run> --task "next thing"`.
146
+
147
+ - **Backends:** `claude`, `codex`, `gemini`, `copilot`
148
+ - **Roles:** `planner`, `coder`, `reviewer`, `triage-reviewer`, or a custom one
149
+ - **Reasoning:** `--reasoning minimal|low|medium|high|xhigh|max`
150
+
151
+ ## Documentation
152
+
153
+ [docs/USAGE.md](https://github.com/volkan/duet/blob/main/docs/USAGE.md) is the
154
+ full reference: every flag, reasoning levels, session memory, output layout,
155
+ `--status` / `--continue`, the force prompt, Codex sandbox and network rules,
156
+ and worktree mode.
157
+
158
+ ## Contributing
159
+
160
+ Contributor guidance is in
161
+ [CLAUDE.md](https://github.com/volkan/duet/blob/main/CLAUDE.md); Codex entry
162
+ notes are in [AGENTS.md](https://github.com/volkan/duet/blob/main/AGENTS.md).
163
+ CI runs on every PR and is advisory until marked required — see
164
+ [.github/BRANCH_PROTECTION.md](https://github.com/volkan/duet/blob/main/.github/BRANCH_PROTECTION.md).
@@ -0,0 +1,143 @@
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. Like the Claude Code plugin, the skill shells out to the `duet`
39
+ CLI, so install that first (see below) and make sure `command -v duet` passes in
40
+ Codex's shell. Full guide:
41
+ [docs/CODEX_PLUGIN.md](https://github.com/volkan/duet/blob/main/docs/CODEX_PLUGIN.md).
42
+
43
+ ### 3. From the terminal — `duet`
44
+
45
+ ```bash
46
+ pipx install duet-cli # the command it installs is `duet`
47
+ duet --task "Fix the failing test" --cwd ~/code/myrepo
48
+ ```
49
+
50
+ The PyPI package is `duet-cli` (bare `duet` on PyPI is Google's async library),
51
+ so `pipx`/`uvx` isolation is recommended. Add `'duet-cli[yaml]'` if you want
52
+ `--config foo.yaml`. One-shot, no install:
53
+ `uvx --from duet-cli duet --task "..."` — note this is ephemeral and does not put
54
+ `duet` on PATH, so the `/duet` and `$duet` plugins need a persistent install
55
+ (`pipx install duet-cli` or `make install`) instead.
56
+
57
+ ## Examples
58
+
59
+ Each command teaches one capability. The partner agent speaks first.
60
+
61
+ **Review loop** — Codex reviews at max effort, Claude applies only the fixes
62
+ Codex asks for, in an isolated worktree:
63
+
64
+ ```bash
65
+ duet --task "Review the latest commit; fix only what the reviewer requests." \
66
+ --lead claude:coder --partner codex:reviewer \
67
+ --reasoning max --worktree --worktree-for lead --turns 6
68
+ ```
69
+
70
+ **Seed from another tool's output** — drive the loop from Claude Code's real
71
+ `/review`, a test run, or any command:
72
+
73
+ ```bash
74
+ duet --task-from-cmd 'claude -p /review' \
75
+ --lead claude:reviewer --partner codex:coder \
76
+ --worktree --recap --cwd ~/workspace/project --turns 6
77
+ ```
78
+
79
+ **Deep planner, fast coder** — Claude plans at high effort while Codex coder
80
+ turns drop to low for latency:
81
+
82
+ ```bash
83
+ duet --reasoning high --codex-fast \
84
+ --task "Fix the issue" --cwd ~/workspace/project
85
+ ```
86
+
87
+ **Verify gate** — a convergence proposal only counts if `make test` exits 0;
88
+ any failure feeds back into the next turn:
89
+
90
+ ```bash
91
+ duet --task "Fix the issue" \
92
+ --lead claude:coder --partner codex:reviewer \
93
+ --verify-cmd 'make test' --worktree --worktree-for lead
94
+ ```
95
+
96
+ **Resume a plan** — plan with Codex in its own session, then hand the session
97
+ id to duet; Codex implements with the plan in context while Claude reviews
98
+ (`--resume-claude <id>` does the inverse):
99
+
100
+ ```bash
101
+ duet --resume-codex <codex-session-id> --worktree --reasoning max \
102
+ --task "Implement the plan from your Codex planning session."
103
+ ```
104
+
105
+ Reusable configs ship under `examples/` — `pr-review.yaml` (deep review of
106
+ `HEAD`) and `codex-test-fix.yaml` (Codex planner diagnoses failing checks, Codex
107
+ coder fixes them). Run one with `duet --config examples/pr-review.yaml`.
108
+
109
+ ## How it works
110
+
111
+ Each agent keeps its own conversation memory across turns (Claude via
112
+ `--resume`, Codex via `codex exec resume`, Gemini and Copilot via their JSON
113
+ session ids). On each turn duet sends one agent's latest reply to the other.
114
+
115
+ To converge, an agent must include an `LGTM rationale:` explaining why the work
116
+ is done, followed by the sentinel `<<<LGTM>>>` on its own line — a bare
117
+ sentinel is ignored, and **both** agents must agree in back-to-back turns. The
118
+ loop also stops on `--turns`, a per-turn timeout, or Ctrl-C. After a normal
119
+ stop, duet opens a `force>` prompt so you can push another round.
120
+
121
+ Every run writes a directory with `transcript.md`, `state.json`, per-turn
122
+ stderr logs, and the `wt/` worktree when `--worktree` is on. Inspect a run with
123
+ `duet --status <run-id>`, list runs with `duet --list`, and start a fresh run
124
+ from saved state with `duet --continue <run> --task "next thing"`.
125
+
126
+ - **Backends:** `claude`, `codex`, `gemini`, `copilot`
127
+ - **Roles:** `planner`, `coder`, `reviewer`, `triage-reviewer`, or a custom one
128
+ - **Reasoning:** `--reasoning minimal|low|medium|high|xhigh|max`
129
+
130
+ ## Documentation
131
+
132
+ [docs/USAGE.md](https://github.com/volkan/duet/blob/main/docs/USAGE.md) is the
133
+ full reference: every flag, reasoning levels, session memory, output layout,
134
+ `--status` / `--continue`, the force prompt, Codex sandbox and network rules,
135
+ and worktree mode.
136
+
137
+ ## Contributing
138
+
139
+ Contributor guidance is in
140
+ [CLAUDE.md](https://github.com/volkan/duet/blob/main/CLAUDE.md); Codex entry
141
+ notes are in [AGENTS.md](https://github.com/volkan/duet/blob/main/AGENTS.md).
142
+ CI runs on every PR and is advisory until marked required — see
143
+ [.github/BRANCH_PROTECTION.md](https://github.com/volkan/duet/blob/main/.github/BRANCH_PROTECTION.md).