ralph-review 0.1.6 → 0.1.8

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
@@ -136,6 +136,9 @@ brew install kenryu42/tap/ralph-review
136
136
 
137
137
  # npm (install or update)
138
138
  npm install -g ralph-review
139
+
140
+ # Or let ralph-review detect the install method and update itself
141
+ rr update
139
142
  ```
140
143
 
141
144
  ---
@@ -159,6 +162,7 @@ rrr
159
162
 
160
163
  | Command | Description |
161
164
  |---------|-------------|
165
+ | `rr` | Interactive Mode |
162
166
  | `rr init` | Configure reviewer, fixer, and simplifier agents (auto-detects installed CLIs) |
163
167
  | `rr run` | Start review cycle in a tmux session |
164
168
  | `rr run --base main` | Review changes against a base branch |
@@ -169,14 +173,18 @@ rrr
169
173
  | `rr config show` | Print full configuration |
170
174
  | `rr config set KEY VAL` | Update a config value (e.g. `rr config set maxIterations 8`) |
171
175
  | `rr list` | List active review sessions |
172
- | `rr status` | Show current review status |
173
176
  | `rr stop` | Stop running review session (`--all` to stop all) |
174
177
  | `rr log` | View review logs (`-n 5` for last 5, `--json` for JSON output) |
175
178
  | `rr dashboard` | Open review dashboard in browser |
176
179
  | `rr doctor` | Run environment and configuration diagnostics (`--fix` to auto-resolve) |
180
+ | `rr update` | Check for and install a newer `ralph-review` version |
177
181
 
178
182
  The `rrr` command is a shorthand alias for `rr run` -- all flags work the same.
179
183
 
184
+ For update checks without installing, run `rr update --check`. If install-source detection is
185
+ ambiguous, force the package manager with `rr update --manager npm` or
186
+ `rr update --manager brew`.
187
+
180
188
  ---
181
189
 
182
190
  ## Supported Coding Agents
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-review",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Orchestrating coding agents for code review, verification and fixing via the ralph loop.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/cli-core.ts CHANGED
@@ -81,18 +81,18 @@ export const COMMANDS: CommandDef[] = [
81
81
  description: "Disable finish sound for this run (override config)",
82
82
  },
83
83
  {
84
- name: "watch",
84
+ name: "interactive",
85
85
  type: "boolean",
86
- description: "Open Session Panel after starting the run (override config)",
86
+ description: "Launch Interactive Mode after starting the run (override config)",
87
87
  },
88
88
  {
89
- name: "no-watch",
89
+ name: "no-interactive",
90
90
  type: "boolean",
91
- description: "Start run without opening Session Panel (override config)",
91
+ description: "Start run without launching Interactive Mode (override config)",
92
92
  },
93
93
  SIMPLIFIER_OPTION,
94
94
  ],
95
- examples: ["rr run", "rr run --base main", "rr run --no-watch"],
95
+ examples: ["rr run", "rr run --base main", "rr run --no-interactive"],
96
96
  },
97
97
  {
98
98
  name: "list",
@@ -104,6 +104,7 @@ export const COMMANDS: CommandDef[] = [
104
104
  name: "status",
105
105
  description: "Show review status",
106
106
  examples: ["rr status"],
107
+ hidden: true,
107
108
  },
108
109
  {
109
110
  name: "stop",
@@ -150,6 +151,29 @@ export const COMMANDS: CommandDef[] = [
150
151
  ],
151
152
  examples: ["rr doctor", "rr doctor --fix"],
152
153
  },
154
+ {
155
+ name: "update",
156
+ description: "Check for and install a newer ralph-review version",
157
+ options: [
158
+ {
159
+ name: "check",
160
+ type: "boolean",
161
+ description: "Check for an update without installing it",
162
+ },
163
+ {
164
+ name: "manager",
165
+ type: "string",
166
+ placeholder: "npm|brew",
167
+ description: "Override install-source detection",
168
+ },
169
+ ],
170
+ examples: [
171
+ "rr update",
172
+ "rr update --check",
173
+ "rr update --manager npm",
174
+ "rr update --manager brew",
175
+ ],
176
+ },
153
177
  {
154
178
  name: "_run-foreground",
155
179
  description: "Internal: run review cycle in tmux foreground",
package/src/cli.ts CHANGED
@@ -11,6 +11,7 @@ import { runLog } from "./commands/log";
11
11
  import { runForeground, startReview } from "./commands/run";
12
12
  import { runStatus } from "./commands/status";
13
13
  import { runStop } from "./commands/stop";
14
+ import { runUpdate } from "./commands/update";
14
15
  import { CliError, type CommandDef, parseCommand } from "./lib/cli-parser";
15
16
 
16
17
  export {
@@ -41,6 +42,8 @@ export interface CliDeps {
41
42
  runDashboard: typeof runDashboard;
42
43
  runDoctor: typeof runDoctor;
43
44
  runList: typeof runList;
45
+ runUpdate: typeof runUpdate;
46
+ isInteractiveTerminal: () => boolean;
44
47
  log: (message: string) => void;
45
48
  logError: (message: string) => void;
46
49
  logMessage: (message: string) => void;
@@ -51,6 +54,8 @@ const CONSOLE_LOG = console.log.bind(console) as (message: string) => void;
51
54
  const CLACK_ERROR = p.log.error.bind(p.log) as (message: string) => void;
52
55
  const CLACK_MESSAGE = p.log.message.bind(p.log) as (message: string) => void;
53
56
  const PROCESS_EXIT = process.exit.bind(process) as (code: number) => void;
57
+ const IS_INTERACTIVE_TERMINAL = (): boolean =>
58
+ process.stdin.isTTY === true && process.stdout.isTTY === true;
54
59
 
55
60
  const DEFAULT_CLI_DEPS: CliDeps = {
56
61
  parseArgs,
@@ -69,6 +74,8 @@ const DEFAULT_CLI_DEPS: CliDeps = {
69
74
  runDashboard,
70
75
  runDoctor,
71
76
  runList,
77
+ runUpdate,
78
+ isInteractiveTerminal: IS_INTERACTIVE_TERMINAL,
72
79
  log: CONSOLE_LOG,
73
80
  logError: CLACK_ERROR,
74
81
  logMessage: CLACK_MESSAGE,
@@ -79,6 +86,11 @@ function buildCliDeps(overrides: Partial<CliDeps>): CliDeps {
79
86
  return { ...DEFAULT_CLI_DEPS, ...overrides };
80
87
  }
81
88
 
89
+ function reportCliError(cliDeps: CliDeps, error: unknown): void {
90
+ cliDeps.logError(`Error: ${error}`);
91
+ cliDeps.exit(1);
92
+ }
93
+
82
94
  export async function runCli(
83
95
  args: string[] = process.argv.slice(2),
84
96
  deps: Partial<CliDeps> = {}
@@ -91,11 +103,25 @@ export async function runCli(
91
103
  return;
92
104
  }
93
105
 
94
- if (!command) {
106
+ if (showHelp && !command) {
95
107
  cliDeps.log(cliDeps.printUsage());
96
108
  return;
97
109
  }
98
110
 
111
+ if (!command) {
112
+ if (commandArgs.length > 0 || !cliDeps.isInteractiveTerminal()) {
113
+ cliDeps.log(cliDeps.printUsage());
114
+ return;
115
+ }
116
+
117
+ try {
118
+ await cliDeps.runStatus();
119
+ } catch (error) {
120
+ reportCliError(cliDeps, error);
121
+ }
122
+ return;
123
+ }
124
+
99
125
  if (showHelp) {
100
126
  const commandHelp = cliDeps.printCommandHelp(command);
101
127
  if (commandHelp) {
@@ -165,6 +191,10 @@ export async function runCli(
165
191
  await cliDeps.runDoctor(commandArgs);
166
192
  break;
167
193
 
194
+ case "update":
195
+ await cliDeps.runUpdate(commandArgs);
196
+ break;
197
+
168
198
  case "list":
169
199
  await cliDeps.runList();
170
200
  break;
@@ -176,8 +206,7 @@ export async function runCli(
176
206
  return;
177
207
  }
178
208
  } catch (error) {
179
- cliDeps.logError(`Error: ${error}`);
180
- cliDeps.exit(1);
209
+ reportCliError(cliDeps, error);
181
210
  }
182
211
  }
183
212
 
@@ -4,7 +4,9 @@ import {
4
4
  configExists,
5
5
  ensureConfigDir,
6
6
  loadConfig,
7
+ loadConfigWithDiagnostics,
7
8
  parseConfig,
9
+ parseConfigWithDiagnostics,
8
10
  saveConfig,
9
11
  } from "@/lib/config";
10
12
  import {
@@ -41,7 +43,9 @@ export type ConfigCommandDeps = {
41
43
  configExists: typeof configExists;
42
44
  ensureConfigDir: typeof ensureConfigDir;
43
45
  loadConfig: typeof loadConfig;
46
+ loadConfigWithDiagnostics: typeof loadConfigWithDiagnostics;
44
47
  parseConfig: typeof parseConfig;
48
+ parseConfigWithDiagnostics: typeof parseConfigWithDiagnostics;
45
49
  saveConfig: typeof saveConfig;
46
50
  spawn: ConfigCommandSpawner;
47
51
  env: Record<string, string | undefined>;
@@ -68,7 +72,7 @@ const CONFIG_KEYS = [
68
72
  "defaultReview.type",
69
73
  "defaultReview.branch",
70
74
  "run.simplifier",
71
- "run.watch",
75
+ "run.interactive",
72
76
  "retry.maxRetries",
73
77
  "retry.baseDelayMs",
74
78
  "retry.maxDelayMs",
@@ -251,7 +255,7 @@ export function parseConfigValue(key: ConfigKey, rawValue: string): ConfigValue
251
255
  return rawValue;
252
256
 
253
257
  case "run.simplifier":
254
- case "run.watch":
258
+ case "run.interactive":
255
259
  if (rawValue !== "true" && rawValue !== "false") {
256
260
  throw new Error(`Value for "${key}" must be "true" or "false".`);
257
261
  }
@@ -306,8 +310,8 @@ export function getConfigValue(config: Config, key: ConfigKey): unknown {
306
310
  return config.defaultReview.type === "base" ? config.defaultReview.branch : undefined;
307
311
  case "run.simplifier":
308
312
  return config.run?.simplifier;
309
- case "run.watch":
310
- return config.run?.watch;
313
+ case "run.interactive":
314
+ return config.run?.interactive;
311
315
  case "retry.maxRetries":
312
316
  return config.retry?.maxRetries;
313
317
  case "retry.baseDelayMs":
@@ -490,13 +494,13 @@ export function setConfigValue(config: Config, key: ConfigKey, value: ConfigValu
490
494
  if (typeof value !== "boolean") {
491
495
  throw new Error(`Value for "${key}" must be "true" or "false".`);
492
496
  }
493
- next.run = { simplifier: value, watch: next.run?.watch ?? true };
497
+ next.run = { simplifier: value, interactive: next.run?.interactive ?? true };
494
498
  return next;
495
- case "run.watch":
499
+ case "run.interactive":
496
500
  if (typeof value !== "boolean") {
497
501
  throw new Error(`Value for "${key}" must be "true" or "false".`);
498
502
  }
499
- next.run = { simplifier: next.run?.simplifier ?? false, watch: value };
503
+ next.run = { simplifier: next.run?.simplifier ?? false, interactive: value };
500
504
  return next;
501
505
  case "retry.maxRetries":
502
506
  next.retry = next.retry ? { ...next.retry } : { ...DEFAULT_RETRY_CONFIG };
@@ -591,26 +595,55 @@ export function validateConfigInvariants(config: Config): string[] {
591
595
  if (config.run && typeof config.run.simplifier !== "boolean") {
592
596
  errors.push("run.simplifier must be a boolean.");
593
597
  }
594
- if (config.run && typeof config.run.watch !== "boolean") {
595
- errors.push("run.watch must be a boolean.");
598
+ if (config.run && typeof config.run.interactive !== "boolean") {
599
+ errors.push("run.interactive must be a boolean.");
596
600
  }
597
601
 
598
602
  return errors;
599
603
  }
600
604
 
605
+ function formatConfigValidationMessage(header: string, errors: string[], footer?: string): string {
606
+ const uniqueErrors = [...new Set(errors)];
607
+ const lines = [header];
608
+ for (const error of uniqueErrors) {
609
+ lines.push(`- ${error}`);
610
+ }
611
+ if (footer) {
612
+ lines.push(footer);
613
+ }
614
+ return lines.join("\n");
615
+ }
616
+
617
+ function collectConfigValidationErrors(config: Config | null, errors: string[]): string[] {
618
+ const combined = [...errors];
619
+ if (config) {
620
+ combined.push(...validateConfigInvariants(config));
621
+ }
622
+ return [...new Set(combined)];
623
+ }
624
+
601
625
  async function loadExistingConfig(deps: ConfigCommandDeps): Promise<Config> {
602
626
  if (!(await deps.configExists())) {
603
627
  throw new Error('Configuration not found. Run "rr init" first.');
604
628
  }
605
629
 
606
- const config = await deps.loadConfig();
607
- if (!config) {
630
+ const loaded = await deps.loadConfigWithDiagnostics();
631
+ if (!loaded.exists) {
632
+ throw new Error('Configuration not found. Run "rr init" first.');
633
+ }
634
+
635
+ const errors = collectConfigValidationErrors(loaded.config, loaded.errors);
636
+ if (!loaded.config || errors.length > 0) {
608
637
  throw new Error(
609
- `Configuration exists but is invalid: ${deps.configPath}. Run "rr init" or fix the file manually.`
638
+ formatConfigValidationMessage(
639
+ `Invalid configuration: ${deps.configPath}`,
640
+ errors.length > 0 ? errors : ["Configuration format is invalid."],
641
+ 'Run "rr init" to regenerate the file, or fix it manually.'
642
+ )
610
643
  );
611
644
  }
612
645
 
613
- return config;
646
+ return loaded.config;
614
647
  }
615
648
 
616
649
  async function runShow(args: string[], deps: ConfigCommandDeps): Promise<void> {
@@ -650,17 +683,18 @@ async function runSet(args: string[], deps: ConfigCommandDeps): Promise<void> {
650
683
  const current = await loadExistingConfig(deps);
651
684
  const updated = setConfigValue(current, key, parsedValue);
652
685
 
653
- const invariantErrors = validateConfigInvariants(updated);
654
- if (invariantErrors.length > 0) {
655
- throw new Error(invariantErrors.join("\n"));
656
- }
657
-
658
- const normalized = deps.parseConfig(updated as unknown);
659
- if (!normalized) {
660
- throw new Error("Updated configuration is invalid.");
686
+ const normalized = deps.parseConfigWithDiagnostics(updated as unknown);
687
+ const validationErrors = collectConfigValidationErrors(normalized.config, normalized.errors);
688
+ if (!normalized.config || validationErrors.length > 0) {
689
+ throw new Error(
690
+ formatConfigValidationMessage(
691
+ "Updated configuration is invalid.",
692
+ validationErrors.length > 0 ? validationErrors : ["Configuration format is invalid."]
693
+ )
694
+ );
661
695
  }
662
696
 
663
- await deps.saveConfig(normalized);
697
+ await deps.saveConfig(normalized.config);
664
698
  deps.log.success(`Updated "${key}" to ${formatValue(parsedValue)}.`);
665
699
  }
666
700
 
@@ -695,15 +729,20 @@ async function runEdit(args: string[], deps: ConfigCommandDeps): Promise<void> {
695
729
  return;
696
730
  }
697
731
 
698
- const config = await deps.loadConfig();
699
- if (!config) {
732
+ const loaded = await deps.loadConfigWithDiagnostics();
733
+ const errors = collectConfigValidationErrors(loaded.config, loaded.errors);
734
+ if (!loaded.config || errors.length > 0) {
700
735
  deps.log.warn(
701
- `Configuration exists but is invalid: ${deps.configPath}. Run "rr init" or fix it manually.`
736
+ formatConfigValidationMessage(
737
+ `Invalid configuration: ${deps.configPath}`,
738
+ errors.length > 0 ? errors : ["Configuration format is invalid."],
739
+ 'Run "rr init" to regenerate the file, or fix it manually.'
740
+ )
702
741
  );
703
742
  return;
704
743
  }
705
744
 
706
- await deps.saveConfig(config);
745
+ await deps.saveConfig(loaded.config);
707
746
  }
708
747
 
709
748
  const DEFAULT_CONFIG_COMMAND_DEPS: ConfigCommandDeps = {
@@ -711,7 +750,9 @@ const DEFAULT_CONFIG_COMMAND_DEPS: ConfigCommandDeps = {
711
750
  configExists,
712
751
  ensureConfigDir,
713
752
  loadConfig,
753
+ loadConfigWithDiagnostics,
714
754
  parseConfig,
755
+ parseConfigWithDiagnostics,
715
756
  saveConfig,
716
757
  spawn: Bun.spawn as unknown as ConfigCommandSpawner,
717
758
  env: process.env as Record<string, string | undefined>,
@@ -731,7 +772,7 @@ function resolveConfigCommandDeps(overrides?: Partial<ConfigCommandDeps>): Confi
731
772
  return DEFAULT_CONFIG_COMMAND_DEPS;
732
773
  }
733
774
 
734
- return {
775
+ const deps: ConfigCommandDeps = {
735
776
  ...DEFAULT_CONFIG_COMMAND_DEPS,
736
777
  ...overrides,
737
778
  log: {
@@ -739,6 +780,30 @@ function resolveConfigCommandDeps(overrides?: Partial<ConfigCommandDeps>): Confi
739
780
  ...overrides.log,
740
781
  },
741
782
  };
783
+
784
+ const loadConfigOverride = overrides.loadConfig;
785
+ if (loadConfigOverride && !overrides.loadConfigWithDiagnostics) {
786
+ deps.loadConfigWithDiagnostics = async (path = deps.configPath) => {
787
+ const config = (await loadConfigOverride(path)) ?? null;
788
+ return {
789
+ exists: config !== null,
790
+ config,
791
+ errors: config ? [] : ["Configuration format is invalid."],
792
+ };
793
+ };
794
+ }
795
+
796
+ if (overrides.parseConfig && !overrides.parseConfigWithDiagnostics) {
797
+ deps.parseConfigWithDiagnostics = (value) => {
798
+ const config = overrides.parseConfig?.(value) ?? null;
799
+ return {
800
+ config,
801
+ errors: config ? [] : ["Configuration format is invalid."],
802
+ };
803
+ };
804
+ }
805
+
806
+ return deps;
742
807
  }
743
808
 
744
809
  export function createRunConfig(overrides?: Partial<ConfigCommandDeps>) {
@@ -53,7 +53,7 @@ interface InitInput {
53
53
  defaultReviewType: "uncommitted" | "base";
54
54
  defaultReviewBranch?: string;
55
55
  runSimplifierByDefault: boolean;
56
- runWatchByDefault: boolean;
56
+ runInteractiveByDefault: boolean;
57
57
  soundNotificationsEnabled: boolean;
58
58
  }
59
59
 
@@ -319,7 +319,7 @@ export function buildConfig(input: InitInput): Config {
319
319
  ),
320
320
  run: {
321
321
  simplifier: input.runSimplifierByDefault,
322
- watch: input.runWatchByDefault,
322
+ interactive: input.runInteractiveByDefault,
323
323
  },
324
324
  maxIterations: input.maxIterations,
325
325
  iterationTimeout: input.iterationTimeoutMinutes * 60 * 1000,
@@ -537,7 +537,7 @@ function formatConfigDisplay(config: Config): string {
537
537
  ` Iteration timeout: ${config.iterationTimeout / 1000 / 60} minutes`,
538
538
  ` Default review: ${defaultReviewDisplay}`,
539
539
  ` Run simplifier: ${config.run?.simplifier ? "enabled" : "disabled"}`,
540
- ` Run watch panel: ${(config.run?.watch ?? true) ? "enabled" : "disabled"}`,
540
+ ` Interactive Mode: ${(config.run?.interactive ?? true) ? "enabled" : "disabled"}`,
541
541
  ` Sound notify: ${config.notifications.sound.enabled ? "enabled" : "disabled"}`,
542
542
  ].join("\n");
543
543
  }
@@ -757,7 +757,7 @@ export async function buildAutoInitInput(
757
757
  iterationTimeoutMinutes,
758
758
  defaultReviewType: "uncommitted",
759
759
  runSimplifierByDefault: false,
760
- runWatchByDefault: true,
760
+ runInteractiveByDefault: true,
761
761
  soundNotificationsEnabled: true,
762
762
  },
763
763
  skippedAgents,
@@ -919,14 +919,17 @@ async function promptForCustomInitInput(
919
919
  defaultReviewType: defaultReviewType as "uncommitted" | "base",
920
920
  defaultReviewBranch: defaultReviewBranch as string | undefined,
921
921
  runSimplifierByDefault: runSimplifierByDefault as boolean,
922
- runWatchByDefault: DEFAULT_CONFIG.run?.watch ?? true,
922
+ runInteractiveByDefault: DEFAULT_CONFIG.run?.interactive ?? true,
923
923
  soundNotificationsEnabled: DEFAULT_CONFIG.notifications?.sound.enabled ?? true,
924
924
  } satisfies InitInput;
925
925
  }
926
926
 
927
- async function promptForRunWatch(runtime: InitRuntime, defaultValue: boolean): Promise<boolean> {
927
+ async function promptForRunInteractive(
928
+ runtime: InitRuntime,
929
+ defaultValue: boolean
930
+ ): Promise<boolean> {
928
931
  const shouldEnable = await runtime.prompt.confirm({
929
- message: "Open Session Panel automatically after 'rr run'?",
932
+ message: "Launch Interactive Mode automatically after 'rr run'?",
930
933
  initialValue: defaultValue,
931
934
  });
932
935
  handleCancel(runtime, shouldEnable);
@@ -1050,12 +1053,15 @@ export async function runInitWithRuntime(
1050
1053
  setupMode === "auto"
1051
1054
  ? {
1052
1055
  ...resolvedInput,
1053
- runWatchByDefault: true,
1056
+ runInteractiveByDefault: true,
1054
1057
  soundNotificationsEnabled: true,
1055
1058
  }
1056
1059
  : {
1057
1060
  ...resolvedInput,
1058
- runWatchByDefault: await promptForRunWatch(runtime, resolvedInput.runWatchByDefault),
1061
+ runInteractiveByDefault: await promptForRunInteractive(
1062
+ runtime,
1063
+ resolvedInput.runInteractiveByDefault
1064
+ ),
1059
1065
  soundNotificationsEnabled: await promptForSoundNotifications(
1060
1066
  runtime,
1061
1067
  resolvedInput.soundNotificationsEnabled
@@ -33,8 +33,8 @@ export interface RunOptions {
33
33
  commit?: string;
34
34
  custom?: string;
35
35
  simplifier?: boolean;
36
- watch?: boolean;
37
- "no-watch"?: boolean;
36
+ interactive?: boolean;
37
+ "no-interactive"?: boolean;
38
38
  sound?: boolean;
39
39
  "no-sound"?: boolean;
40
40
  }
@@ -82,20 +82,20 @@ export function resolveRunSimplifierEnabled(options: RunOptions, config: Config
82
82
  return options.simplifier === true || config?.run?.simplifier === true;
83
83
  }
84
84
 
85
- export function resolveRunWatchEnabled(options: RunOptions, config: Config | null): boolean {
86
- if (options.watch && options["no-watch"]) {
87
- throw new Error("Cannot use --watch and --no-watch together");
85
+ export function resolveRunInteractiveEnabled(options: RunOptions, config: Config | null): boolean {
86
+ if (options.interactive && options["no-interactive"]) {
87
+ throw new Error("Cannot use --interactive and --no-interactive together");
88
88
  }
89
89
 
90
- if (options.watch) {
90
+ if (options.interactive) {
91
91
  return true;
92
92
  }
93
93
 
94
- if (options["no-watch"]) {
94
+ if (options["no-interactive"]) {
95
95
  return false;
96
96
  }
97
97
 
98
- return config?.run?.watch ?? true;
98
+ return config?.run?.interactive ?? true;
99
99
  }
100
100
 
101
101
  export function formatRunAgentsNote(config: Config, reviewOptions: ReviewOptions): string {
@@ -377,7 +377,7 @@ async function runInBackground(
377
377
  runtime.prompt.log.success(`Review started in background session: ${sessionName}`);
378
378
  const reviewOptions: ReviewOptions = { baseBranch, commitSha, customInstructions, simplifier };
379
379
  runtime.prompt.note(formatRunAgentsNote(config, reviewOptions), "Agents");
380
- runtime.prompt.note("rr status - Check status\n" + "rr stop - Stop the review", "Commands");
380
+ runtime.prompt.note("rr - Check status\n" + "rr stop - Stop the review", "Commands");
381
381
  } catch (error) {
382
382
  await runtime.lockfile.removeLockfile(undefined, projectPath, { expectedSessionId: sessionId });
383
383
  runtime.prompt.log.error(`Failed to start background session: ${error}`);
@@ -385,9 +385,9 @@ async function runInBackground(
385
385
  }
386
386
  }
387
387
 
388
- function logWatchReconnectHint(runtime: RunRuntime): void {
389
- runtime.prompt.log.message("Session Panel closed.");
390
- runtime.prompt.log.message("Re-open panel: rr status");
388
+ function logInteractiveReconnectHint(runtime: RunRuntime): void {
389
+ runtime.prompt.log.message("Interactive Mode closed.");
390
+ runtime.prompt.log.message("Launch Interactive Mode: rr");
391
391
  runtime.prompt.log.message("Stop session: rr stop");
392
392
  }
393
393
 
@@ -692,17 +692,17 @@ export async function startReview(
692
692
  }
693
693
 
694
694
  const runSimplifier = resolveRunSimplifierEnabled(options, config);
695
- let runWatch: boolean;
695
+ let runInteractive: boolean;
696
696
  try {
697
- runWatch = resolveRunWatchEnabled(options, config);
697
+ runInteractive = resolveRunInteractiveEnabled(options, config);
698
698
  } catch (error) {
699
699
  runtime.prompt.log.error(`${error}`);
700
700
  runtime.process.exit(1);
701
701
  return;
702
702
  }
703
- if (runWatch && !runtime.process.stdoutIsTTY) {
704
- runtime.prompt.log.warn("Watch mode is disabled because stdout is not a TTY.");
705
- runWatch = false;
703
+ if (runInteractive && !runtime.process.stdoutIsTTY) {
704
+ runtime.prompt.log.warn("Interactive Mode is disabled because stdout is not a TTY.");
705
+ runInteractive = false;
706
706
  }
707
707
 
708
708
  // Check if inside tmux - warn about nesting
@@ -722,7 +722,7 @@ export async function startReview(
722
722
  soundOverride
723
723
  );
724
724
 
725
- if (!runWatch) {
725
+ if (!runInteractive) {
726
726
  return;
727
727
  }
728
728
 
@@ -731,8 +731,8 @@ export async function startReview(
731
731
  const branch = await runtime.getGitBranch(projectPath);
732
732
  await runtime.openSessionPanel(projectPath, branch ?? undefined);
733
733
  } catch (error) {
734
- runtime.prompt.log.warn(`Could not open Session Panel: ${error}`);
734
+ runtime.prompt.log.warn(`Could not launch Interactive Mode: ${error}`);
735
735
  }
736
736
 
737
- logWatchReconnectHint(runtime);
737
+ logInteractiveReconnectHint(runtime);
738
738
  }
@@ -118,7 +118,7 @@ async function stopCurrentSession(): Promise<void> {
118
118
  if (allSessions.length > 0) {
119
119
  p.log.message(`\nThere are ${allSessions.length} other session(s) running.`);
120
120
  p.log.message(
121
- 'Use "rr stop --all" to stop all running review sessions, or "rr status" to see details.'
121
+ 'Use "rr stop --all" to stop all running review sessions, or "rr" to see details.'
122
122
  );
123
123
  }
124
124
  return;