pi-review-loop 0.1.1 → 0.2.0

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.
package/README.md CHANGED
@@ -4,12 +4,10 @@
4
4
 
5
5
  # Pi Review Loop
6
6
 
7
- Automated code review loop for pi. Repeatedly prompts the agent to review its own work until it confirms no issues remain.
7
+ Automated code review loop for [Pi coding agent](https://buildwithpi.ai/). Repeatedly prompts the agent to review its own work until it confirms no issues remain.
8
8
 
9
9
  ```
10
- > implement the plan
11
-
12
- [agent implements...]
10
+ > /review-start
13
11
 
14
12
  Review mode (1/7) ← status appears in footer
15
13
 
@@ -24,13 +22,9 @@ Review mode (2/7)
24
22
  Review mode ended: no issues found ← auto-exits
25
23
  ```
26
24
 
27
- ## Why
28
-
29
- Agents make mistakes. They miss edge cases, introduce typos, forget error handling. Asking them to review their own code catches a surprising number of issues, but you have to remember to ask, and then ask again if they found something.
25
+ Agents make mistakes. They miss edge cases, introduce typos, forget error handling. Asking them to review their own code catches a surprising number of issues, but you have to remember to ask, and then ask again if they found something. This automates that:
30
26
 
31
- Reviewer Loop automates this:
32
-
33
- **Auto-Trigger** - Detects phrases like "implement the plan" or the `/double-check` template. No need to manually activate.
27
+ **Auto-Trigger** - Optionally detects phrases like "implement the plan" or the `/double-check` template. Disabled by default; enable with `/review-auto on` or in settings.
34
28
 
35
29
  **Persistent Loop** - After each response, sends a review prompt. If the agent found and fixed issues, it loops again. Only exits when the agent genuinely finds nothing.
36
30
 
@@ -42,9 +36,9 @@ Reviewer Loop automates this:
42
36
 
43
37
  The loop shines in two scenarios:
44
38
 
45
- **Before implementing** — You've got a plan doc and want to sanity-check it against the actual codebase. Run `/double-check-plan` and let the agent compare the plan to what exists. It'll catch things like outdated assumptions, conflicting patterns, or unnecessary complexity. The funny thing is, it rarely finds everything on the first pass. Second pass catches different issues. Third pass, more still. That's the whole point of the loop.
39
+ **Before implementing** — You've got a plan doc and want to sanity-check it against the actual codebase. Run `/review-start` and let the agent compare the plan to what exists. It'll catch things like outdated assumptions, conflicting patterns, or unnecessary complexity. The funny thing is, it rarely finds everything on the first pass. Second pass catches different issues. Third pass, more still. That's the whole point of the loop.
46
40
 
47
- **After implementing** — You just finished building a feature and want to catch bugs before calling it done. Run `/double-check` and the agent reviews its own work with fresh eyes. Typos, missed edge cases, forgotten error handling — it finds stuff you'd miss staring at the same code. Again, multiple passes tend to surface different issues each time.
41
+ **After implementing** — You just finished building a feature and want to catch bugs before calling it done. Run `/review-start` and the agent reviews its own work with fresh eyes. Typos, missed edge cases, forgotten error handling — it finds stuff you'd miss staring at the same code. Again, multiple passes tend to surface different issues each time.
48
42
 
49
43
  The pattern is the same: keep reviewing until there's genuinely nothing left to find. The loop handles the "ask again" part automatically. You'll see `Review mode (2/7)` in the footer so you know it's working and how many passes it's done.
50
44
 
@@ -80,9 +74,13 @@ The package includes two prompt templates that are automatically installed to `~
80
74
  | `double-check-plan.md` | `/double-check-plan` | Review implementation plan against codebase |
81
75
 
82
76
  These prompts are designed to work with the review loop:
83
- - They include the "fresh eyes" phrase that auto-triggers the loop
84
77
  - They instruct the agent to respond with "No issues found." when done (triggering exit)
85
78
  - They tell the agent to end with "Fixed [N] issue(s). Ready for another review." when issues are fixed (continuing the loop)
79
+ - They include the "fresh eyes" phrase that triggers the loop when `autoTrigger` is enabled
80
+
81
+ **Recommended workflow:** Use `/review-start` to activate review mode, which sends the review prompt automatically. Alternatively, enable auto-trigger (`/review-auto on`) and the `/double-check` template will activate the loop.
82
+
83
+ You can customize or replace these prompts, change trigger patterns, or use your own entirely. See [Configuration](#configuration). The agent can also start/stop the loop on demand via the `review_loop` tool. See [Tool API](#tool-api).
86
84
 
87
85
  **Manual installation** (if cloning instead of npm):
88
86
 
@@ -92,25 +90,41 @@ cp ~/.pi/agent/extensions/pi-review-loop/prompts/*.md ~/.pi/agent/prompts/
92
90
 
93
91
  ## Quick Start
94
92
 
95
- ### Automatic Activation
93
+ ### Manual Activation
96
94
 
97
- Just use trigger phrases naturally:
95
+ ```
96
+ /review-start
97
+ ```
98
+
99
+ Activates review mode and immediately sends the review prompt.
100
+
101
+ ### Automatic Activation (Optional)
102
+
103
+ Auto-trigger is disabled by default. Enable it for the current session:
98
104
 
99
105
  ```
100
- > implement the plan
101
- > implement the spec
102
- > let's implement this plan
106
+ /review-auto on
103
107
  ```
104
108
 
105
- Or use the `/double-check` prompt template.
109
+ Or permanently in `~/.pi/agent/settings.json`:
106
110
 
107
- ### Manual Activation
111
+ ```json
112
+ {
113
+ "reviewerLoop": {
114
+ "autoTrigger": true
115
+ }
116
+ }
117
+ ```
118
+
119
+ With auto-trigger enabled, trigger phrases activate review mode:
108
120
 
109
121
  ```
110
- /review-start
122
+ > implement the plan
123
+ > implement the spec
124
+ > let's implement this plan
111
125
  ```
112
126
 
113
- Activates review mode and immediately sends the review prompt.
127
+ Or use the `/double-check` prompt template.
114
128
 
115
129
  ### Check Status
116
130
 
@@ -144,6 +158,7 @@ Configure in `~/.pi/agent/settings.json`. Works out of the box, but everything i
144
158
  {
145
159
  "reviewerLoop": {
146
160
  "maxIterations": 7,
161
+ "autoTrigger": true,
147
162
  "reviewPrompt": "template:double-check",
148
163
  "triggerPatterns": {
149
164
  "mode": "extend",
@@ -166,8 +181,9 @@ Configure in `~/.pi/agent/settings.json`. Works out of the box, but everything i
166
181
  | Option | Description |
167
182
  |--------|-------------|
168
183
  | `maxIterations` | Max review prompts before auto-exit (default: 7) |
184
+ | `autoTrigger` | Enable keyword-based auto-trigger (default: false) |
169
185
  | `reviewPrompt` | The prompt to send each iteration |
170
- | `triggerPatterns` | What activates review mode |
186
+ | `triggerPatterns` | What activates review mode (requires autoTrigger: true) |
171
187
  | `exitPatterns` | What indicates "review complete" |
172
188
  | `issuesFixedPatterns` | What indicates issues were fixed (prevents false exits) |
173
189
 
@@ -228,7 +244,7 @@ The loop exits when:
228
244
 
229
245
  1. **Exit phrase without fixes** - Agent says "no issues" and didn't fix anything
230
246
  2. **Max iterations** - Safety limit reached (default: 7)
231
- 3. **User interrupts** - You type something that isn't a trigger
247
+ 3. **User interrupts** - You type something (only trigger phrases are ignored, and only when auto-trigger is on)
232
248
  4. **Manual exit** - `/review-exit` command
233
249
  5. **Abort** - Press ESC or agent response is empty
234
250
 
@@ -239,11 +255,12 @@ The loop exits when:
239
255
  | `/review-start` | Activate and send review prompt immediately |
240
256
  | `/review-exit` | Exit review mode |
241
257
  | `/review-max <n>` | Set max iterations (session only) |
258
+ | `/review-auto [on\|off]` | Toggle auto-trigger from keywords (session only) |
242
259
  | `/review-status` | Show current state |
243
260
 
244
261
  ## Tool API
245
262
 
246
- The `review_loop` tool lets the agent programmatically control review mode:
263
+ The `review_loop` tool lets the agent control review mode directly:
247
264
 
248
265
  ```typescript
249
266
  // Check status (default)
@@ -260,6 +277,10 @@ review_loop({ stop: true })
260
277
 
261
278
  // Just update max iterations
262
279
  review_loop({ maxIterations: 10 })
280
+
281
+ // Enable/disable auto-trigger
282
+ review_loop({ autoTrigger: true })
283
+ review_loop({ autoTrigger: false })
263
284
  ```
264
285
 
265
286
  **Returns:**
@@ -268,6 +289,7 @@ review_loop({ maxIterations: 10 })
268
289
  "active": true,
269
290
  "currentIteration": 2,
270
291
  "maxIterations": 7,
292
+ "autoTrigger": false,
271
293
  "message": "Review mode active: iteration 2/7"
272
294
  }
273
295
  ```
@@ -279,7 +301,7 @@ review_loop({ maxIterations: 10 })
279
301
  ```
280
302
  input event
281
303
 
282
- matches trigger? → enter review mode
304
+ autoTrigger on + matches trigger? → enter review mode
283
305
 
284
306
  agent responds
285
307
 
@@ -294,14 +316,14 @@ otherwise → exit (max reached)
294
316
 
295
317
  **Events used:**
296
318
  - `session_start` - Reload settings
297
- - `input` - Detect triggers, handle interrupts
298
- - `before_agent_start` - Check expanded prompts for triggers
319
+ - `input` - Detect triggers (if autoTrigger enabled), handle interrupts
320
+ - `before_agent_start` - Check expanded prompts for triggers (if autoTrigger enabled)
299
321
  - `agent_end` - Analyze response, decide to loop or exit
300
322
 
301
323
  ## Limitations
302
324
 
303
325
  - **User templates only** - `template:name` loads from `~/.pi/agent/prompts/`, not project templates
304
- - **Session-scoped /review-max** - Doesn't persist across sessions
326
+ - **Session-scoped settings** - `/review-max` and `/review-auto` don't persist across sessions (use settings.json for persistence)
305
327
  - **Pattern failures are silent** - Invalid regex patterns are skipped without error
306
328
 
307
329
  ## File Structure
@@ -325,8 +347,6 @@ pi-review-loop/
325
347
 
326
348
  ## Credits
327
349
 
328
- Inspired by and built on ideas from:
329
-
330
- - **[Ralph Wiggum Loop](https://ghuntley.com/ralph/)** by [@GeoffreyHuntley](https://x.com/GeoffreyHuntley) - Loosely based on the "Ralph" loop
350
+ - **[Ralph Wiggum Loop](https://ghuntley.com/ralph/)** by [@GeoffreyHuntley](https://x.com/GeoffreyHuntley)
331
351
  - **["Fresh eyes" review prompt](https://x.com/doodlestein/status/1956228999945806049)** by [@doodlestein](https://x.com/doodlestein)
332
- - **[pi](https://github.com/badlogic/pi-mono/)** by [@badlogicgames](https://x.com/badlogicgames) — The agent framework powering all of this
352
+ - **[pi](https://github.com/badlogic/pi-mono/)** by [@badlogicgames](https://x.com/badlogicgames)
package/index.ts CHANGED
@@ -39,7 +39,7 @@ export default function (pi: ExtensionAPI) {
39
39
  pi.on("input", async (event, ctx) => {
40
40
  if (!ctx.hasUI) return { action: "continue" as const };
41
41
 
42
- const isTrigger = settings.triggerPatterns.some((p) => p.test(event.text));
42
+ const isTrigger = settings.autoTrigger && settings.triggerPatterns.some((p) => p.test(event.text));
43
43
 
44
44
  if (reviewModeActive && event.source === "interactive" && !isTrigger) {
45
45
  exitReviewMode(ctx, "user interrupted");
@@ -56,6 +56,7 @@ export default function (pi: ExtensionAPI) {
56
56
  pi.on("before_agent_start", async (event, ctx) => {
57
57
  if (!ctx.hasUI) return;
58
58
  if (reviewModeActive) return;
59
+ if (!settings.autoTrigger) return;
59
60
 
60
61
  const isTrigger = settings.triggerPatterns.some((p) => p.test(event.prompt));
61
62
  if (isTrigger) {
@@ -153,17 +154,38 @@ export default function (pi: ExtensionAPI) {
153
154
  );
154
155
  } else {
155
156
  ctx.ui.notify(
156
- `Review mode inactive (max: ${settings.maxIterations})`,
157
+ `Review mode inactive (max: ${settings.maxIterations}, auto-trigger: ${settings.autoTrigger ? "on" : "off"})`,
157
158
  "info"
158
159
  );
159
160
  }
160
161
  },
161
162
  });
162
163
 
164
+ pi.registerCommand("review-auto", {
165
+ description: "Toggle auto-trigger from keywords (off by default)",
166
+ handler: async (args, ctx) => {
167
+ const arg = args.trim().toLowerCase();
168
+ if (arg === "on" || arg === "true" || arg === "1") {
169
+ settings.autoTrigger = true;
170
+ } else if (arg === "off" || arg === "false" || arg === "0") {
171
+ settings.autoTrigger = false;
172
+ } else if (arg === "") {
173
+ settings.autoTrigger = !settings.autoTrigger;
174
+ } else {
175
+ ctx.ui.notify("Usage: /review-auto [on|off]", "error");
176
+ return;
177
+ }
178
+ ctx.ui.notify(
179
+ `Auto-trigger ${settings.autoTrigger ? "enabled" : "disabled"}`,
180
+ "info"
181
+ );
182
+ },
183
+ });
184
+
163
185
  pi.registerTool({
164
186
  name: "review_loop",
165
187
  description:
166
- "Control the automated code review loop. Start/stop review mode or check status. When started, the loop repeatedly prompts for code review until 'No issues found' or max iterations reached.",
188
+ "Control the automated code review loop. Start/stop review mode, toggle auto-trigger, or check status. When started, the loop repeatedly prompts for code review until 'No issues found' or max iterations reached.",
167
189
  parameters: Type.Object({
168
190
  start: Type.Optional(
169
191
  Type.Boolean({
@@ -175,6 +197,11 @@ export default function (pi: ExtensionAPI) {
175
197
  description: "Stop review mode",
176
198
  })
177
199
  ),
200
+ autoTrigger: Type.Optional(
201
+ Type.Boolean({
202
+ description: "Enable/disable auto-trigger from keywords (disabled by default)",
203
+ })
204
+ ),
178
205
  maxIterations: Type.Optional(
179
206
  Type.Number({
180
207
  description: "Set max iterations (can be combined with start)",
@@ -189,6 +216,15 @@ export default function (pi: ExtensionAPI) {
189
216
  settings.maxIterations = params.maxIterations;
190
217
  }
191
218
 
219
+ // Update autoTrigger if provided
220
+ if (typeof params.autoTrigger === "boolean") {
221
+ settings.autoTrigger = params.autoTrigger;
222
+ ctx.ui.notify(
223
+ `Auto-trigger ${settings.autoTrigger ? "enabled" : "disabled"}`,
224
+ "info"
225
+ );
226
+ }
227
+
192
228
  // Mode: start > stop > status
193
229
  if (params.start) {
194
230
  if (reviewModeActive) {
@@ -200,6 +236,7 @@ export default function (pi: ExtensionAPI) {
200
236
  active: true,
201
237
  currentIteration,
202
238
  maxIterations: settings.maxIterations,
239
+ autoTrigger: settings.autoTrigger,
203
240
  message: "Review mode is already active",
204
241
  }),
205
242
  },
@@ -218,6 +255,7 @@ export default function (pi: ExtensionAPI) {
218
255
  active: true,
219
256
  currentIteration,
220
257
  maxIterations: settings.maxIterations,
258
+ autoTrigger: settings.autoTrigger,
221
259
  message: "Review mode started. Review prompt sent.",
222
260
  }),
223
261
  },
@@ -235,6 +273,7 @@ export default function (pi: ExtensionAPI) {
235
273
  active: false,
236
274
  currentIteration: 0,
237
275
  maxIterations: settings.maxIterations,
276
+ autoTrigger: settings.autoTrigger,
238
277
  message: "Review mode is not active",
239
278
  }),
240
279
  },
@@ -252,6 +291,7 @@ export default function (pi: ExtensionAPI) {
252
291
  active: false,
253
292
  currentIteration: 0,
254
293
  maxIterations: settings.maxIterations,
294
+ autoTrigger: settings.autoTrigger,
255
295
  message: "Review mode stopped",
256
296
  }),
257
297
  },
@@ -268,6 +308,7 @@ export default function (pi: ExtensionAPI) {
268
308
  active: reviewModeActive,
269
309
  currentIteration,
270
310
  maxIterations: settings.maxIterations,
311
+ autoTrigger: settings.autoTrigger,
271
312
  message: reviewModeActive
272
313
  ? `Review mode active: iteration ${currentIteration}/${settings.maxIterations}`
273
314
  : "Review mode inactive",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-review-loop",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Automated code review loop extension for pi coding agent",
5
5
  "scripts": {
6
6
  "postinstall": "node scripts/install.js",
package/settings.ts CHANGED
@@ -60,6 +60,7 @@ export interface ReviewPromptConfig {
60
60
  export interface ReviewerLoopSettingsRaw {
61
61
  maxIterations?: number;
62
62
  reviewPrompt?: string;
63
+ autoTrigger?: boolean;
63
64
  triggerPatterns?: PatternConfig;
64
65
  exitPatterns?: PatternConfig;
65
66
  issuesFixedPatterns?: PatternConfig;
@@ -68,6 +69,7 @@ export interface ReviewerLoopSettingsRaw {
68
69
  export interface ReviewerLoopSettings {
69
70
  maxIterations: number;
70
71
  reviewPromptConfig: ReviewPromptConfig;
72
+ autoTrigger: boolean;
71
73
  triggerPatterns: RegExp[];
72
74
  exitPatterns: RegExp[];
73
75
  issuesFixedPatterns: RegExp[];
@@ -201,6 +203,7 @@ export function loadSettings(): ReviewerLoopSettings {
201
203
  ? raw.maxIterations
202
204
  : DEFAULT_MAX_ITERATIONS,
203
205
  reviewPromptConfig: parseReviewPromptConfig(raw.reviewPrompt),
206
+ autoTrigger: raw.autoTrigger === true,
204
207
  triggerPatterns: loadPatterns(raw.triggerPatterns, DEFAULT_TRIGGER_PATTERNS),
205
208
  exitPatterns: loadPatterns(raw.exitPatterns, DEFAULT_EXIT_PATTERNS),
206
209
  issuesFixedPatterns: loadPatterns(