Repository navigation
fix: 30 bugs you can see on screen, each confirmed with a before/after screenshot - #61
Merged
Merged
Conversation
Each of these was reproduced in real piped output and screenshotted
before the change:
- Report truncation from the renderer instead of searching the line for
"...": a CWD segments path, a long Custom Command preview or a Link made
the TUI warn "Some lines are truncated" when nothing was cut.
- Regular mode now treats preserve-colors widgets like Powerline mode
does: the widget background is restored after a reset inside the
content, and styles the content leaves open (bold, underline) are closed
before the rest of the line.
- Drop a visible separator left dangling before a flex gap when every
widget between them renders empty ("Opus | $0.42").
- Treat output with no visible text (a script wrapping an empty variable
in color codes) as empty, so it keeps no separators and no Powerline
segment.
- A merge blocked by a separator or flex separator no longer makes two
widgets share a regular-theme palette slot.
- With the terminal width unknown, a flex separator at a line edge renders
nothing instead of a stray " | ".
- inheritSeparatorColors follows the regular-mode theme color the widget
was actually drawn with.
- Dim-parens styling leaves OSC 8 hyperlinks alone; a branch like
"fix(ui)" no longer breaks its link and prints part of the URL.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TuwfSyvahcufah5vLXqVwS
… editor
Each was reproduced in real output and screenshotted before the change:
- Context Bar no longer shows "(100%)" while tokens are still free
(199k/200k next to Context % reading 99.6%).
- Tokens derived from a fractional used_percentage are rounded instead of
printing "699.9999999999999".
- Token counts past a billion use a B suffix ("1.2B") instead of
"1246.4M", with the same round-up promotion as k to M.
- Block and Weekly Reset Timer show "[Not started]" when usage has loaded
at 0% but the window has no reset time yet, instead of "[Loading]"
forever.
- The editor labels the long Context Bar "(long bar)", like the usage
widgets; it showed no modifier while the default said "(medium bar)".
- Compaction Counter's editor label reads "icon-and-number": the stored
"icon-space-number" id stays for existing configs, but the space it
names was dropped from the output.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TuwfSyvahcufah5vLXqVwS
…ion screens
Each was reproduced in the real TUI (tmux, 120x40) and screenshotted
before the change:
- Terminal Width marks "Full width always" as the default, matching the
schema, README and USAGE; its description says the renderer's actual
6-column reserve instead of 4.
- The width-detection note in Edit Line stacks its two lines instead of
laying them out as two squeezed columns.
- The delete-line dialog reads "☰ Line 2", and Edit Colors
"(s)how separators: OFF", with the missing spaces.
- Leaving Powerline Setup after toggling powerline keeps the highlight on
Powerline Setup; install/uninstall return targets also account for the
Theme entry powerline hides.
- After the first-run preset picker is answered, Presets shows its own
title and the "replaces your entire configuration" warning.
- Edit Colors no longer lists Flex Separators, whose colors never render.
- Re-entering a line list after deleting the last line no longer opens on
"← Back".
- Theme names show as the picker names ("One Dark", not "Onedark"), and
the theme hint points to "Powerline Setup", the screen's real name.
- The color-level confirmation prints its "Continue?" question.
- The widget picker shows a 12-row window with "Showing x-y of n"
instead of drawing all 90+ widgets off the top of the terminal.
- Global Overrides aligns "Compact Labels:" with the other rows.
- The install package step reopens on the remembered manager when npm is
missing instead of on "← Back".
- The pinned-mismatch screen labels the relaunch command as one ("Relaunch
the pinned version with:") instead of as the "Current pinned version".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TuwfSyvahcufah5vLXqVwS
The test ran a real printf through Custom Command, which other test files mock in the full bun test run; stub the widget's output instead so the color-only case is exercised deterministically. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TuwfSyvahcufah5vLXqVwS
An independent review of this PR's own changes found four cases where
a fix made something else visibly wrong:
- Edit Lines: the remembered line was clamped on every render, so
deleting a line other than the remembered one moved the highlight to
a different line. It is now clamped once, on entry from the main menu.
- Context Bar: with the percent capped below 100, 199,600 of 200,000
tokens read "200k/200k (99%)". The used count gets one more digit
("199.6k/200k (99%)") when it would round up to the total.
- Regular themes: a merge glued across an empty widget (the dropped
separator after it belongs to the merge) gave the two glued widgets
different palette colors. The palette now follows the same glue rule.
- Dim parens: a (...) span wrapping a whole hyperlink was no longer
dimmed. Spans may contain complete OSC sequences again, while no
style code is ever inserted inside one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TuwfSyvahcufah5vLXqVwS
axisrow
commented
Oct 15, 2026
axisrow
left a comment
Owner
Author
There was a problem hiding this comment.
Approved — no changes required.
Reviewed the full diff against main (renderer, colors, widgets, TUI) plus the new regression tests.
- The rendering changes are internally consistent. I traced the new resolvedForegrounds map, the merge-glue rule (mergesWithNextRenderedWidget) and the shouldAddSeparator check across combinations: merge blocked by separator/flex, merge glued across an empty widget, dangling separator before a flex gap, trailing and doubled separators — the palette, the dropped separators and the default-separator suppression agree with each other.
- The dangling-separator scan deliberately skips spacing-only separators (they remain the boundary when a fully occupied line leaves the flex gap at zero columns); visible separators are the ones dropped. Both sides are covered by tests.
- formatTokens B-promotion mirrors the documented k-to-M boundary arithmetic (999949999 -> 999.9M, 999950000 -> 1.0B).
- ContextBar percent cap and the extra-digit used count interact correctly. At 199999/200000 the line reads 200.0k/200k (99%): the fractional digit keeps it distinguishable from the total and the percent stays honest. No change requested.
- The bar itself still fills fully at 99.96 percent while the text shows 99 percent — an explicit test pins that as intended.
- findLastIndex in the flex fallback is fine for the stated Node >=18 engine (added in Node 18.0.0).
- TUI changes check out against the components: the remembered line is clamped once on entry (no highlight drift on later deletes), main-menu index re-resolution accounts for the powerline-hidden Theme entry, InstallMenu maps the remembered manager onto enabled entries, and the inline ConfirmDialog indeed never renders its message prop, so printing Continue? outside it is correct.
CI is green and each fix carries a test that fails on the pre-fix code. Optional nit, summary only: the helper set duplicated in renderer-visible-output.test.ts and renderer-separator-collapse.test.ts could be extracted someday; not worth the churn now.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A bug hunt with one rule: a bug only counts if you can see it. Every item below was reproduced in the real program and screenshotted before any code changed:
The same scenario was re-run after the fix for the "after" screenshot. Candidates that did not show up on screen were dropped (see below).
Each fix has a regression test, and each of those tests fails on the code before the fix.
Closes #63, which describes every bug with steps and links to the pre-fix code. The Powerline font-detection bug stays open in #62.
Status line rendering —
src/utils/renderer.ts,src/utils/colors.tsfull-minus-40plus any...in widget text: CWD segments.../a/b, a Custom Command preview over 20 chars, a Link, a max widthwasTruncatedfrom both the regular and the Powerline paths) instead of searching the line for...\x1b[0mprintf '\033[1;4mX')\x1b[0mwhen it carries SGROpus 4.6 | $0.42: a dangling|sep, flexpair and spacing-only separators are kept as beforeA | | B, and an empty block in Powerlinemergeblocked by a separator or flex|(ui)⎇ fix(ui): link lost, text leaks, line wider than measureddim: parens, branchfix(ui)applyParensDimnever puts a style code inside an OSC sequence. A(...)span that wraps a whole link is still dimmedWidgets
199k/200k (100%)next to Context %99.6%199.6k/200k (99%))Ctx: 699.9999999999999(fractionalused_percentage, nocurrent_usage)Cached: 1246.4MBtier, promoted the same way as k→MWeekly Reset: [Loading]forever once usage has loaded at 0% with no reset time[Not started](docs/USAGE.md updated)(medium bar)(long bar)(icon-space-number), output is↻2icon-and-number. The stored id is unchangedTUI
(default)moves to Full width always (the schema default), and the text says "minus 6"flexDirection='column'☰ Line2 (3 widgets)and(s)how separators:OFFgetVisibleRangemoved tosrc/utils/visible-range.tsBefore / after
Each image shows the same scenario before and after the fix.
A

B

R9

R1

R6

R4

R7

R8

R5

W15

W12

W5

W13

W2

W8

D

E

F


T3

T4

T8

T10


T11

T13

T15

T16

T9

T1

Self-review follow-up (42bcffc)
An independent review of this PR's own diff (reviewers per area, then a skeptic per finding) found four cases where a fix made something else wrong. All four are fixed in 42bcffc, and each has a test that fails on the previous head:
200k/200k (99%)at 199,500–199,999 tokens.(...)span wrapping a whole link was no longer dimmed.Documented only, not changed (owner's call)
Powerline arrows turn into
|although a capable font is installed, tracked in #62. Detection insrc/utils/powerline.tsis a top-level file-name scan:/nerd font/iwith a space, so it misses Nerd Fonts v3 names likeJetBrainsMonoNerdFont-Regular.ttf.The same font file renders arrows under its old v2 name and
|under its v3 name.Dropped
Not visible on screen:
1024Mmemory rounding, which needs controlled RAM to reproduce.Visible, but intended:
0hr 0mplaceholder is a style choice.JjWidgetSharedBehavior.test.ts.Test plan
bun run lintis clean.bun test: 3605 pass, 9 fail. The same 9 fail on the base commit in this container and pass in CI: 8 daemon shared-mode tests, and the proxy-CONNECT deadline test.🤖 Generated with Claude Code
https://claude.ai/code/session_01TuwfSyvahcufah5vLXqVwS