You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(cli): make startup logo static by default, animate via BOMLY_LOGO opt-in (#371)
User feedback: help must render instantly. The ~2s startup animation now
only plays when BOMLY_LOGO is set (truthy value = random variant, variant
name pins one), and runs faster when it does (28 frames x 45ms ~= 1.3s,
down from 70ms ~= 2s). NO_COLOR / BOMLY_NO_ANIMATION / CI / BOMLY_QUIET
keep their meaning and still win over the opt-in.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: dev-docs/ARCHITECTURE.md
+5-3Lines changed: 5 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -542,12 +542,14 @@ The detect stage resolves subprojects concurrently (`resolveAll` fans out to per
542
542
- Each detector's public `ResolveGraph` rebinds `d.Logger = req.DetectorLogger(d.Logger)` on its value-receiver copy, so every private helper inherits the scoped logger with no signature churn and no shared mutable state.
543
543
- The console encoder enables `NameKey`/`EncodeName` so the subproject scope renders as a prefix. Logs remain real-time (not buffered per subproject) because `-vv` is used precisely to watch slow or hung detectors.
544
544
545
-
### Decision: startup banner frames are procedural; gating is env-var-only
545
+
### Decision: startup banner frames are procedural; animation is opt-in; gating is env-var-only
546
546
547
-
The help-path startup banner (`internal/cli/render/logo.go`) is a frame-based animation in the style of GitHub Copilot CLI's banner: the art itself changes per frame. Four variants exist — `reveal` (a boundary sweeps left to right with a scramble band), `rain` (matrix-style green code glyphs fall down the logo silhouette), `glitch` (the full logo is visible from frame one but corrupted, and the noise density decays to zero), and `slide` (rows enter alternately from the left and right edges). A random variant plays each run; `BOMLY_LOGO=<name>` pins one. All variants share the finale (finished art, tagline fading in), the frame budget (28 frames × 70ms ≈ 2s), and the cell/run-grouping renderer. Three choices worth recording:
547
+
The help-path startup banner (`internal/cli/render/logo.go`) is a frame-based animation in the style of GitHub Copilot CLI's banner: the art itself changes per frame. Four variants exist — `reveal` (a boundary sweeps left to right with a scramble band), `rain` (matrix-style green code glyphs fall down the logo silhouette), `glitch` (the full logo is visible from frame one but corrupted, and the noise density decays to zero), and `slide` (rows enter alternately from the left and right edges). All variants share the finale (finished art, tagline fading in), the frame budget (28 frames × 45ms ≈ 1.3s), and the cell/run-grouping renderer.
548
+
549
+
**The animation is opt-in; the default is the static colored logo.** The banner originally animated by default, but user feedback was consistent that a CLI — and the help command especially — must render instantly, so the default flipped to static. `BOMLY_LOGO` is the single opt-in knob: any truthy value animates a random variant, and a variant name (`reveal`, `rain`, `glitch`, `slide`) animates that variant. Three further choices worth recording:
548
550
549
551
-**Frames are generated procedurally, not stored as files.** Copilot ships ~20 hand-drawn frame files plus a position→color-role→theme mapping layer. At our scale (6×42 cells, a handful of visual roles) that indirection is over-engineering: frames are computed from the final art with a deterministic FNV-1a hash (stable across runs, so tests assert exact frame properties per variant), and styling uses lightweight run-grouped style constants — consecutive same-style cells share one escape sequence. Only variant *selection* is random; frame content is deterministic.
550
-
-**Gating is env-var-only (`NO_COLOR`, `BOMLY_NO_ANIMATION`, `CI`, `BOMLY_QUIET`), deliberately not a config key.** Cobra's `execute()` returns `flag.ErrHelp` right after flag parsing, *before* the `PersistentPreRunE` chain where `options.ResolveConfig` runs — so on `bomly --help` / `bomly <cmd> --help` (the banner's primary path) resolved config simply does not exist yet. A `logo.animate` config key would silently work only for bare `bomly` and `bomly help <cmd>`, which is a trap. When animation is gated off but stderr is a TTY, the static final frame prints instead (plain under `NO_COLOR`, colored otherwise); non-TTY stderr prints nothing.
552
+
-**Gating is env-var-only (`BOMLY_LOGO` to opt in; `NO_COLOR`, `BOMLY_NO_ANIMATION`, `CI`, `BOMLY_QUIET` to force static), deliberately not a config key.** Cobra's `execute()` returns `flag.ErrHelp` right after flag parsing, *before* the `PersistentPreRunE` chain where `options.ResolveConfig` runs — so on `bomly --help` / `bomly <cmd> --help` (the banner's primary path) resolved config simply does not exist yet. A `logo.animate` config key would silently work only for bare `bomly` and `bomly help <cmd>`, which is a trap. When animation is gated off but stderr is a TTY, the static final frame prints instead (plain under `NO_COLOR`, colored otherwise); non-TTY stderr prints nothing.
551
553
-**The animation leaves cursor visibility unchanged.** Hiding the cursor would make the animation slightly cleaner, but a process-level interrupt can bypass deferred cleanup and leave the user's shell cursor hidden. Avoiding that terminal-state mutation keeps interruption safe without introducing signal handling into the render package.
Copy file name to clipboardExpand all lines: docs/TROUBLESHOOTING.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -129,21 +129,21 @@ ANSI escapes are auto-stripped when stdout is not a TTY, but some CI runners rep
129
129
NO_COLOR=1 bomly scan
130
130
```
131
131
132
-
## Controlling the startup animation
132
+
## Controlling the startup logo
133
133
134
-
`bomly --help`plays a short (~2s) logo animation when stderr is an interactive terminal. A random variant plays each run; pin a favorite with `BOMLY_LOGO`(`reveal`, `rain`, `glitch`, or `slide`):
134
+
`bomly --help`prints a static logo when stderr is an interactive terminal. To play a short (~1.3s) logo animation instead, set `BOMLY_LOGO`to a truthy value — a random variant plays each run:
135
135
136
136
```bash
137
-
BOMLY_LOGO=rain bomly --help
137
+
BOMLY_LOGO=1 bomly --help
138
138
```
139
139
140
-
To skip the animation and print a static logo instead:
140
+
Pin a favorite variant by name (`reveal`, `rain`, `glitch`, or `slide`):
141
141
142
142
```bash
143
-
BOMLY_NO_ANIMATION=1 bomly --help
143
+
BOMLY_LOGO=rain bomly --help
144
144
```
145
145
146
-
The animation is also skipped automatically when `CI` or `BOMLY_QUIET` is set, and `NO_COLOR` switches to a plain uncolored logo. When stderr is not a terminal (pipes, redirects), no logo is printed at all.
146
+
The animation is skipped even when `BOMLY_LOGO` is set if `BOMLY_NO_ANIMATION`, `CI`, or `BOMLY_QUIET` is set, and `NO_COLOR` switches to a plain uncolored logo. When stderr is not a terminal (pipes, redirects), no logo is printed at all.
0 commit comments