duet-cli 0.2.8__tar.gz → 0.2.10__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: duet-cli
3
- Version: 0.2.8
3
+ Version: 0.2.10
4
4
  Summary: Two CLI agents in conversation. One Python file. Stdlib only.
5
5
  Author: Volkan Altan
6
6
  License-Expression: MIT
@@ -47,7 +47,9 @@ Plain `/duet` runs Claude Code's real `/review`, then loops Codex and Claude in
47
47
  a worktree until they converge. Pass any upstream command as the kickoff:
48
48
  `/duet 'npm test 2>&1' --turns 4`. The plugin shells out to the `duet` CLI, so
49
49
  install that first (see below) and make sure `command -v duet` passes in Claude
50
- Code's shell. Full guide:
50
+ Code's shell. Custom topology flags such as `--no-worktree` and
51
+ `--allow-worktree-fallback` replace the plugin defaults without emitting
52
+ conflicting CLI flags. Full guide:
51
53
  [docs/CLAUDE_CODE_PLUGIN.md](https://github.com/volkan/duet/blob/main/docs/CLAUDE_CODE_PLUGIN.md).
52
54
  If Claude Code disambiguates plugin commands with namespaces, `/duet:duet` is
53
55
  the same command.
@@ -108,8 +110,10 @@ Then invoke `/duet` in the OpenCode TUI (or `opencode run --command duet "..."`
108
110
  non-interactively). Like the other plugins it shells out to the `duet` CLI, so
109
111
  install that first and make sure `command -v duet` passes in OpenCode's shell.
110
112
  The command runs on OpenCode's `build` agent; plain `/duet` runs the same
111
- `claude -p /review` kickoff, and `/duet 'npm test 2>&1' --turns 4` seeds from
112
- any command. Full guide:
113
+ `claude -p /review --model sonnet` kickoff, and
114
+ `/duet 'npm test 2>&1' --turns 4` seeds from any command. Custom worktree
115
+ overrides are constructed conditionally, matching the Claude and Codex entry
116
+ points. Full guide:
113
117
  [docs/OPENCODE_PLUGIN.md](https://github.com/volkan/duet/blob/main/docs/OPENCODE_PLUGIN.md).
114
118
  (duet can also drive OpenCode as a backend — `--partner opencode:coder` — so
115
119
  OpenCode can be one of the two looped agents too.)
@@ -155,9 +159,28 @@ duet --task "Review the latest commit; fix only what the reviewer requests." \
155
159
  `/review`, a test run, or any command:
156
160
 
157
161
  ```bash
158
- duet --task-from-cmd 'claude -p /review' \
159
- --lead claude:reviewer --partner codex:coder \
160
- --worktree --recap --cwd ~/workspace/project --turns 6
162
+ duet --recipe review --cwd ~/workspace/project
163
+ ```
164
+
165
+ The review recipe uses recap mode, `claude:reviewer` + `codex:coder`, six
166
+ turns, `claude -p /review --model sonnet`, and strict worktree isolation.
167
+ Claude agents use the stable `sonnet` alias unless an explicit slot model
168
+ overrides it. The recipe also sets
169
+ `--on-turn-timeout continue`, so when the coder turn times out the reviewer
170
+ still gets the timeout block plus the worktree diff to review instead of the
171
+ run dying reviewless. Explicit flags override recipe values.
172
+
173
+ **Deterministic automation** — discover the run without parsing terminal prose,
174
+ then poll the curated status schema:
175
+
176
+ ```bash
177
+ control_dir=$(mktemp -d)
178
+ duet --recipe review --run-info-file "$control_dir/run.json" &
179
+ duet_pid=$!
180
+ while [ ! -s "$control_dir/run.json" ]; do sleep 0.1; done
181
+ run_dir=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["run_dir"])' "$control_dir/run.json")
182
+ duet --status "$run_dir" --json
183
+ wait "$duet_pid"
161
184
  ```
162
185
 
163
186
  **Deep planner, fast coder** — Claude plans at high effort while Codex coder
@@ -202,18 +225,31 @@ other.
202
225
  To converge, an agent must include an `LGTM rationale:` explaining why the work
203
226
  is done, followed by the sentinel `<<<LGTM>>>` on its own line — a bare
204
227
  sentinel is ignored, and **both** agents must agree in back-to-back turns. The
205
- loop also stops on `--turns`, a per-turn timeout, or Ctrl-C. After a normal
228
+ loop also stops on `--turns`, a per-turn timeout, or Ctrl-C. With
229
+ `--on-turn-timeout continue` (the review recipe's default) a single turn
230
+ timeout is handed to the partner instead of ending the run; two consecutive
231
+ timeouts still stop. Without `--timeout`, the per-turn budget scales with the
232
+ reasoning level (900s → 1800s at `xhigh`/`max`). After a normal
206
233
  stop, duet opens a `force>` prompt so you can push another round.
207
234
 
208
235
  Every run writes a directory with `transcript.md`, `state.json`, per-turn
209
236
  stderr logs, and the `wt/` worktree when `--worktree` is on. Inspect a run with
210
- `duet --status <run-id>`, list runs with `duet --list`, and start a fresh run
237
+ `duet --status <run-id> --json` (or omit `--json` for the human view), list runs
238
+ with `duet --list`, and start a fresh run
211
239
  from saved state with `duet --continue <run> --task "next thing"`.
212
240
 
213
241
  - **Backends:** `claude`, `codex`, `gemini`, `copilot`, `opencode`
214
242
  - **Roles:** `planner`, `coder`, `reviewer`, `triage-reviewer`, or a custom one
215
243
  - **Reasoning:** `--reasoning minimal|low|medium|high|xhigh|max`
216
244
 
245
+ ## Limits / future
246
+
247
+ Timeout continuation applies only to automatic loop turns. Seed extraction
248
+ and forced turns still stop on timeout. A final-turn timeout also stops because
249
+ no partner turn remains, and two consecutive timeouts stop the run. Poll
250
+ `duet --status <run-id> --json` to watch the current budget instead of assuming
251
+ a deep-reasoning turn is stuck.
252
+
217
253
  ## Documentation
218
254
 
219
255
  [docs/USAGE.md](https://github.com/volkan/duet/blob/main/docs/USAGE.md) is the
@@ -26,7 +26,9 @@ Plain `/duet` runs Claude Code's real `/review`, then loops Codex and Claude in
26
26
  a worktree until they converge. Pass any upstream command as the kickoff:
27
27
  `/duet 'npm test 2>&1' --turns 4`. The plugin shells out to the `duet` CLI, so
28
28
  install that first (see below) and make sure `command -v duet` passes in Claude
29
- Code's shell. Full guide:
29
+ Code's shell. Custom topology flags such as `--no-worktree` and
30
+ `--allow-worktree-fallback` replace the plugin defaults without emitting
31
+ conflicting CLI flags. Full guide:
30
32
  [docs/CLAUDE_CODE_PLUGIN.md](https://github.com/volkan/duet/blob/main/docs/CLAUDE_CODE_PLUGIN.md).
31
33
  If Claude Code disambiguates plugin commands with namespaces, `/duet:duet` is
32
34
  the same command.
@@ -87,8 +89,10 @@ Then invoke `/duet` in the OpenCode TUI (or `opencode run --command duet "..."`
87
89
  non-interactively). Like the other plugins it shells out to the `duet` CLI, so
88
90
  install that first and make sure `command -v duet` passes in OpenCode's shell.
89
91
  The command runs on OpenCode's `build` agent; plain `/duet` runs the same
90
- `claude -p /review` kickoff, and `/duet 'npm test 2>&1' --turns 4` seeds from
91
- any command. Full guide:
92
+ `claude -p /review --model sonnet` kickoff, and
93
+ `/duet 'npm test 2>&1' --turns 4` seeds from any command. Custom worktree
94
+ overrides are constructed conditionally, matching the Claude and Codex entry
95
+ points. Full guide:
92
96
  [docs/OPENCODE_PLUGIN.md](https://github.com/volkan/duet/blob/main/docs/OPENCODE_PLUGIN.md).
93
97
  (duet can also drive OpenCode as a backend — `--partner opencode:coder` — so
94
98
  OpenCode can be one of the two looped agents too.)
@@ -134,9 +138,28 @@ duet --task "Review the latest commit; fix only what the reviewer requests." \
134
138
  `/review`, a test run, or any command:
135
139
 
136
140
  ```bash
137
- duet --task-from-cmd 'claude -p /review' \
138
- --lead claude:reviewer --partner codex:coder \
139
- --worktree --recap --cwd ~/workspace/project --turns 6
141
+ duet --recipe review --cwd ~/workspace/project
142
+ ```
143
+
144
+ The review recipe uses recap mode, `claude:reviewer` + `codex:coder`, six
145
+ turns, `claude -p /review --model sonnet`, and strict worktree isolation.
146
+ Claude agents use the stable `sonnet` alias unless an explicit slot model
147
+ overrides it. The recipe also sets
148
+ `--on-turn-timeout continue`, so when the coder turn times out the reviewer
149
+ still gets the timeout block plus the worktree diff to review instead of the
150
+ run dying reviewless. Explicit flags override recipe values.
151
+
152
+ **Deterministic automation** — discover the run without parsing terminal prose,
153
+ then poll the curated status schema:
154
+
155
+ ```bash
156
+ control_dir=$(mktemp -d)
157
+ duet --recipe review --run-info-file "$control_dir/run.json" &
158
+ duet_pid=$!
159
+ while [ ! -s "$control_dir/run.json" ]; do sleep 0.1; done
160
+ run_dir=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["run_dir"])' "$control_dir/run.json")
161
+ duet --status "$run_dir" --json
162
+ wait "$duet_pid"
140
163
  ```
141
164
 
142
165
  **Deep planner, fast coder** — Claude plans at high effort while Codex coder
@@ -181,18 +204,31 @@ other.
181
204
  To converge, an agent must include an `LGTM rationale:` explaining why the work
182
205
  is done, followed by the sentinel `<<<LGTM>>>` on its own line — a bare
183
206
  sentinel is ignored, and **both** agents must agree in back-to-back turns. The
184
- loop also stops on `--turns`, a per-turn timeout, or Ctrl-C. After a normal
207
+ loop also stops on `--turns`, a per-turn timeout, or Ctrl-C. With
208
+ `--on-turn-timeout continue` (the review recipe's default) a single turn
209
+ timeout is handed to the partner instead of ending the run; two consecutive
210
+ timeouts still stop. Without `--timeout`, the per-turn budget scales with the
211
+ reasoning level (900s → 1800s at `xhigh`/`max`). After a normal
185
212
  stop, duet opens a `force>` prompt so you can push another round.
186
213
 
187
214
  Every run writes a directory with `transcript.md`, `state.json`, per-turn
188
215
  stderr logs, and the `wt/` worktree when `--worktree` is on. Inspect a run with
189
- `duet --status <run-id>`, list runs with `duet --list`, and start a fresh run
216
+ `duet --status <run-id> --json` (or omit `--json` for the human view), list runs
217
+ with `duet --list`, and start a fresh run
190
218
  from saved state with `duet --continue <run> --task "next thing"`.
191
219
 
192
220
  - **Backends:** `claude`, `codex`, `gemini`, `copilot`, `opencode`
193
221
  - **Roles:** `planner`, `coder`, `reviewer`, `triage-reviewer`, or a custom one
194
222
  - **Reasoning:** `--reasoning minimal|low|medium|high|xhigh|max`
195
223
 
224
+ ## Limits / future
225
+
226
+ Timeout continuation applies only to automatic loop turns. Seed extraction
227
+ and forced turns still stop on timeout. A final-turn timeout also stops because
228
+ no partner turn remains, and two consecutive timeouts stop the run. Poll
229
+ `duet --status <run-id> --json` to watch the current budget instead of assuming
230
+ a deep-reasoning turn is stuck.
231
+
196
232
  ## Documentation
197
233
 
198
234
  [docs/USAGE.md](https://github.com/volkan/duet/blob/main/docs/USAGE.md) is the