Add startup progress indicators#71720
Conversation
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
Greptile SummaryThis PR adds startup progress spinners for the CLI bootstrap phase and the Crestodian startup/overview-loading flows, and adds
Confidence Score: 4/5Mostly safe, but the newly introduced "Loading Crestodian overview…" spinner is silently dead in the primary CLI code path. One P1 finding: the
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/crestodian/crestodian.ts
Line: 54-62
Comment:
**"Loading Crestodian overview…" spinner always suppressed**
When `runCrestodian` is called from `run-main.ts` with a `--message` argument, `createCliProgress` in `run-main.ts` has already incremented `activeProgress` to 1 for the "Starting Crestodian…" spinner before `runCrestodian` is entered. `createCliProgress` returns `noopReporter` when `activeProgress > 0`, so this `withProgress` call is silently suppressed for every CLI invocation via the message path — the overview spinner never appears.
`onReady` (which decrements `activeProgress` by calling `progress.done()`) is only invoked on line 81 in the TUI path, not here, so `activeProgress` is still 1 when this `withProgress` call is made. The fix is to call `opts.onReady?.()` before `loadCrestodianOverview()` so the outer spinner is stopped first, or restructure `run-main.ts` to not hold an active progress across all of `runCrestodian`.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: scripts/install.sh
Line: 449-474
Comment:
**`showed_progress` check is unreachable dead code**
`showed_progress` is set to `true` in every branch that continues past the `if/else` block: the spinner failure path sets it before falling through, and the `else` path sets it unconditionally before running the command. The `if [[ "$showed_progress" == "false" ]]` guard further down can never be entered; the `ui_info` call it wraps is dead code. The `showed_progress` variable and its guard can be removed.
How can I resolve this? If you propose a fix, please make it concise.Reviews (2): Last reviewed commit: "Show progress for installer download pha..." | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
Adds startup progress indicators during CLI bootstrap and Crestodian startup/overview loading, using the shared CLI progress helper to avoid polluting JSON and non-TTY output.
Changes:
- Wrap Crestodian overview load and interactive startup in
withProgress. - Wrap the main CLI bootstrap path in
withProgress. - Mock and assert
withProgressusage in Crestodian unit tests.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/crestodian/crestodian.ts | Adds progress wrappers around overview loading and interactive startup. |
| src/crestodian/crestodian.test.ts | Mocks withProgress and asserts progress labels are requested. |
| src/cli/run-main.ts | Adds a bootstrap progress wrapper around routing/import/registration/parse flow. |
| await withProgress( | ||
| { | ||
| label: "Loading OpenClaw CLI…", | ||
| indeterminate: true, | ||
| delayMs: 120, | ||
| fallback: "none", | ||
| }, |
There was a problem hiding this comment.
fallback: "none" disables the spinner/line fallback in TTY mode (only OSC progress may show, if supported). That conflicts with the PR goal of showing a startup spinner; consider omitting fallback (default spinner) or setting fallback: "spinner" and/or enabled based on --json to keep JSON output quiet without disabling the indicator entirely.
| try { | ||
| await program.parseAsync(parseArgv); | ||
| } catch (error) { | ||
| if (!(error instanceof CommanderError)) { | ||
| throw error; | ||
| } | ||
| process.exitCode = error.exitCode; |
There was a problem hiding this comment.
withProgress(...) currently wraps program.parseAsync(parseArgv), which executes the selected command. Because createCliProgress uses a global activeProgress guard, this outer progress scope will suppress any nested progress spinners used by commands for the entire runtime (and can leave the “Loading OpenClaw CLI…” state active during real work). Suggestion: limit the withProgress scope to just the slow bootstrap/import/registration steps, then call program.parseAsync after the progress has been finalized.
| { | ||
| label: "Loading Crestodian overview…", | ||
| indeterminate: true, | ||
| delayMs: 120, | ||
| fallback: "none", | ||
| }, |
There was a problem hiding this comment.
fallback: "none" disables the spinner/line fallback in TTY mode (only OSC progress may show). If the intention is to show a visible startup indicator, consider using the default fallback (omit fallback) or explicitly fallback: "spinner" so the overview load actually displays a spinner in typical terminals.
| const runInteractiveTui = | ||
| opts.runInteractiveTui ?? (await import("./tui-backend.js")).runCrestodianTui; | ||
| await runInteractiveTui(opts, runtime); | ||
| await withProgress( | ||
| { | ||
| label: "Starting Crestodian…", | ||
| indeterminate: true, | ||
| delayMs: 120, | ||
| fallback: "none", | ||
| }, | ||
| async () => await runInteractiveTui(opts, runtime), | ||
| ); |
There was a problem hiding this comment.
The progress wrapper for the interactive path starts after the dynamic import("./tui-backend.js"), so it won’t cover the slow module-load portion. Also, wrapping runInteractiveTui(opts, runtime) keeps the progress scope active for the entire TUI session (until the user exits), which can interfere with terminal UI and suppress any nested withProgress usage due to the global activeProgress guard. Consider scoping progress to just the startup phase (e.g., the dynamic import + initial overview load) and finishing it before entering the long-running runTui loop.
|
Added follow-up coverage for the fresh-install path (curl ... | bash):\n\n- install.sh now prints immediate startup feedback before any gum bootstrap network work.\n- quiet steps now always emit a visible step label when spinner mode is unavailable (for example, shell-function-backed steps).\n- NodeSource setup-script downloads now run as explicit quiet steps, so users see progress text instead of apparent hangs.\n\nThis keeps long operations from appearing stalled in the installer flow. |
fabianwilliams
left a comment
There was a problem hiding this comment.
Worthwhile UX win — the silent multi-second startup gap is real, and createCliProgress with indeterminate spinner + done() cleanup is the right shape. onReady callback to stop the spinner from inside Crestodian keeps the lifecycle explicit. install.sh changes (adding ui_info ahead of NodeSource downloads, wrapping the bootstrap step) are also a good move — the gum bootstrap itself was the silent part. LGTM.
| const overview = await withProgress( | ||
| { | ||
| label: "Loading Crestodian overview…", | ||
| indeterminate: true, | ||
| delayMs: 0, | ||
| fallback: "none", | ||
| }, | ||
| async () => await loadCrestodianOverview(), | ||
| ); |
There was a problem hiding this comment.
"Loading Crestodian overview…" spinner always suppressed
When runCrestodian is called from run-main.ts with a --message argument, createCliProgress in run-main.ts has already incremented activeProgress to 1 for the "Starting Crestodian…" spinner before runCrestodian is entered. createCliProgress returns noopReporter when activeProgress > 0, so this withProgress call is silently suppressed for every CLI invocation via the message path — the overview spinner never appears.
onReady (which decrements activeProgress by calling progress.done()) is only invoked on line 81 in the TUI path, not here, so activeProgress is still 1 when this withProgress call is made. The fix is to call opts.onReady?.() before loadCrestodianOverview() so the outer spinner is stopped first, or restructure run-main.ts to not hold an active progress across all of runCrestodian.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/crestodian/crestodian.ts
Line: 54-62
Comment:
**"Loading Crestodian overview…" spinner always suppressed**
When `runCrestodian` is called from `run-main.ts` with a `--message` argument, `createCliProgress` in `run-main.ts` has already incremented `activeProgress` to 1 for the "Starting Crestodian…" spinner before `runCrestodian` is entered. `createCliProgress` returns `noopReporter` when `activeProgress > 0`, so this `withProgress` call is silently suppressed for every CLI invocation via the message path — the overview spinner never appears.
`onReady` (which decrements `activeProgress` by calling `progress.done()`) is only invoked on line 81 in the TUI path, not here, so `activeProgress` is still 1 when this `withProgress` call is made. The fix is to call `opts.onReady?.()` before `loadCrestodianOverview()` so the outer spinner is stopped first, or restructure `run-main.ts` to not hold an active progress across all of `runCrestodian`.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8803b2ed73
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| label: "Loading OpenClaw CLI…", | ||
| indeterminate: true, | ||
| delayMs: 0, | ||
| fallback: "none", |
There was a problem hiding this comment.
Enable spinner fallback for CLI bootstrap progress
The new bootstrap progress reporter is created with fallback: "none", which means createCliProgress will not render a spinner or line unless OSC progress is available. In TTY environments where supportsOscProgress(...) returns false, users now see no startup indicator during slow CLI initialization, so the new feedback path is effectively disabled for that terminal class.
Useful? React with 👍 / 👎.
| label: "Loading Crestodian overview…", | ||
| indeterminate: true, | ||
| delayMs: 0, | ||
| fallback: "none", |
There was a problem hiding this comment.
Use visible fallback for Crestodian overview progress
The overview-loading progress in runCrestodian also sets fallback: "none", so on TTYs without OSC progress support there is no visible indicator while loadCrestodianOverview() runs. That creates a silent wait in the exact one-shot flow this change is trying to make more responsive.
Useful? React with 👍 / 👎.
* Add startup progress indicators * Narrow startup progress scope * Revert startup spinner delay to immediate feedback * Improve install.sh progress feedback for quiet steps * Show progress for installer download phases
* Add startup progress indicators * Narrow startup progress scope * Revert startup spinner delay to immediate feedback * Improve install.sh progress feedback for quiet steps * Show progress for installer download phases
* Add startup progress indicators * Narrow startup progress scope * Revert startup spinner delay to immediate feedback * Improve install.sh progress feedback for quiet steps * Show progress for installer download phases
* Add startup progress indicators * Narrow startup progress scope * Revert startup spinner delay to immediate feedback * Improve install.sh progress feedback for quiet steps * Show progress for installer download phases
* Add startup progress indicators * Narrow startup progress scope * Revert startup spinner delay to immediate feedback * Improve install.sh progress feedback for quiet steps * Show progress for installer download phases
* Add startup progress indicators * Narrow startup progress scope * Revert startup spinner delay to immediate feedback * Improve install.sh progress feedback for quiet steps * Show progress for installer download phases
* Add startup progress indicators * Narrow startup progress scope * Revert startup spinner delay to immediate feedback * Improve install.sh progress feedback for quiet steps * Show progress for installer download phases
Show an indeterminate spinner during slow CLI bootstrap and while Crestodian loads its overview, with immediate feedback (no hardcoded 2s delay threshold).
The startup progress now stops before command execution and before the interactive TUI session begins, so nested progress is not suppressed.
Validation: