Repository navigation
feat(terminal): take the width from Claude Code's COLUMNS and remove the Terminal Width options - #765
Merged
sirmalloc merged 5 commits intoOct 30, 2026
Conversation
Claude Code 2.1.153+ sets COLUMNS (and LINES) to the terminal size when it runs the status line. Reading it after CCSTATUSLINE_WIDTH and before the session cache skips the ps/stty ancestor walk on macOS/BSD and gives Windows a width without an override. Invalid values fall through to probing.
The troubleshooting entry for wrapped status lines still said Windows has no width unless CCSTATUSLINE_WIDTH is set. Claude Code 2.1.153 and later pass the width in COLUMNS, which is now read there too, so the override is only needed with older builds.
Claude Code keeps the status line full-width and, since the previous commits, its width comes from the COLUMNS it passes in. The two modes that held 40 columns back for the auto-compact message no longer have anything to choose between, so every line now renders the way the default, Full width always, did: the detected width minus 6 columns, in piped output and the TUI preview alike. Notifications that share the row outside fullscreen rendering are Claude Code's to fit; on narrow terminals it cuts the status line short. Removed: the flexMode and compactThreshold settings, the Terminal Width entry under Terminal Options (which keeps Color Level), and the Main Menu warning that pointed there when Full width minus 40 truncated the preview, together with the preview's truncation callback that only fed it. Settings files that still carry flexMode or compactThreshold load without an error or warning, whatever their values: the schema no longer defines them, so parsing drops them and the next save writes the file without them, the way a legacy git-pr widget type is rewritten. The v1 migration no longer copies them, and imports ignore them. The two config templates lose them too.
This was referenced Oct 30, 2026
Owner
|
Tweaked the right side to pad one less space to make it symmetrical on both sides. |
eric-engberg
added a commit
to eric-engberg/ccstatusline
that referenced
this pull request
Oct 31, 2026
With sirmalloc#765 Terminal Options lists only Color Level, so the steps that went through Terminal Width land on Color Level when the menu opens.
eric-engberg
added a commit
to eric-engberg/ccstatusline
that referenced
this pull request
Oct 31, 2026
…he first row With sirmalloc#765 Terminal Options lists only Color Level, so the two tests start there instead of stepping down from Terminal Width.
eric-engberg
added a commit
to eric-engberg/ccstatusline
that referenced
this pull request
Oct 31, 2026
…ade moot With sirmalloc#765, Color Level is Terminal Options' only setting and the custom-colors warning opens only from it, so the menu comes back on that row without help.
This was referenced Oct 31, 2026
pcvelz
added a commit
to pcvelz/ccstatusline-usage
that referenced
this pull request
Nov 2, 2026
Upstream: weekly limit timers (sirmalloc#768), prompt cache miss widgets (sirmalloc#770), context window size env override (sirmalloc#352, sirmalloc#407), windowed speed fixes (sirmalloc#769, sirmalloc#771), separator/renderer fixes (sirmalloc#773), custom-command styling (sirmalloc#775), clickable cwd links (sirmalloc#744), account email from live credentials (sirmalloc#724), cache timer reported expiry + short toggle (sirmalloc#576, sirmalloc#592), claude-status lock (sirmalloc#635, sirmalloc#772), dedup token metrics (sirmalloc#622, sirmalloc#725, sirmalloc#735). Not adopted: sirmalloc#765 terminal width from COLUMNS with fixed reserve - the fork keeps flexMode/compactThreshold and tmux pane priority. Hand edits outside conflicts: - README.md: kept fork Configure flex separator behavior bullet and older-updates details wrapper; dropped upstream Related Projects additions (claude-eta) - AGENTS.md: kept fork terminal width wording (sirmalloc#765 not adopted) - src/types/FlexMode.ts, src/tui/components/TerminalWidthMenu.tsx, src/tui/components/__tests__/TerminalWidthMenu.test.ts, src/tui/components/TerminalOptionsMenu.tsx, src/tui/components/__tests__/TerminalOptionsMenu.test.ts: restored, fork keeps terminal width settings - src/tui/App.tsx, src/tui/components/index.ts, src/types/index.ts: re-wired terminal width menu and FlexMode export - src/types/StatusJSON.ts: dropped fork duplicate prompt_cache key, upstream schema is a superset - src/utils/terminal.ts: COLUMNS source gated on non-tmux so tmux pane width keeps priority - src/widgets/WeeklyLimitTimer.ts, src/utils/usage-prefetch.ts, src/widgets/__tests__/WeeklyLimitTimer.test.ts: compat fix - fableUsage/fableResetAt -> weeklyFableUsage/weeklyFableResetAt - src/widgets/ApiUsage.tsx: compat fix - Context Bar honors effective context window (override, clamp, 1.0M format); Weekly renders a valid value despite a session error - src/widgets/__tests__/ApiUsage.localModelFallback.test.ts: output tokens no longer counted in context (upstream sirmalloc#730) - src/utils/__tests__/renderer-flex-width.test.ts, src/utils/__tests__/renderer-ansi.test.ts, src/utils/__tests__/gradient.test.ts, src/utils/__tests__/renderer-separator-collapse.test.ts, src/utils/__tests__/config.test.ts, src/tui/__tests__/App.test.ts: fork deviation - fork width model (flexMode, 6-column full reserve, kept settings, Terminal Width menu entry) - src/utils/__tests__/default-colors.test.ts: fork deviation - accept ansi256:/hex: defaults - src/utils/__tests__/usage-prefetch.test.ts: fork deviation - weekly usage comes from the API, fork widget imports from ApiUsage - src/widgets/__tests__/CurrentWorkingDir.test.ts, src/widgets/__tests__/CustomCommand.test.ts: Settings literal gains flexMode/compactThreshold - src/utils/__tests__/context-window.test.ts, src/utils/__tests__/jsonl-metrics.test.ts: restored fork tests upstream dropped - docs/test-retirements.md: ledger for the dev-reload snapshot-path and RemoteControlStatus glyph (sirmalloc#605) tests upstream replaced
sirmalloc
pushed a commit
that referenced
this pull request
Nov 5, 2026
… at the configured Color Level (#784) * fix(tui): keep the main menu's highlight when a save changes its entries Pressing Ctrl+S on the main menu after making changes moved the highlight back to the entry that was last opened. Saving swaps Save & Exit and Exit without saving for a single Exit, and List reset its highlight to initialSelection whenever the number of items changed. The main menu's initialSelection is the entry last opened, not the one highlighted, so the cursor left the entry the user had moved to and the next Enter opened a different screen. List gets a keepHighlightOnItemsChange prop, and the main menu sets it. With it, a new initialSelection still moves the highlight, but when just the number of items changes, the highlight stays on the item it was on; if that item is gone, it stays on the same row, inside the list. On the main menu, Install stays Install after a save, and Save & Exit or Exit without saving become the Exit that replaces them. Other lists still move the highlight to initialSelection when their item count changes. Line selection and Powerline Setup keep their initialSelection on the highlight and set it to place the highlight: appending a line highlights the new line, and turning Powerline on highlights Separator. * fix(tui): build the preview's color codes for the configured color level In a terminal that chalk detects at fewer colors than the configured color level, such as tmux with TERM=screen or ssh with TERM=xterm, the TUI preview and color menus drew different colors from the real status line. At the default 256 colors, cyan, magenta and bright black widgets were drawn black; a truecolor setting previewed 256-color approximations. chalk works out a 256-color or hex style's escape code when the style is created, at the level set at that moment. COLOR_MAP creates its styles when colors.ts loads, so its codes follow the level chalk detected for the terminal. The piped render sets chalk.level and then calls updateColorMap() to rebuild them; the TUI set chalk.level on load, on import and in Terminal Options, but never rebuilt the map. The TUI now calls updateColorMap() each time it sets chalk.level, as the piped render does. The test sandbox rebuilds the map when it puts chalk's level back, so later test files get the codes they expect. * docs(tui): say the main menu's initialSelection is the highlighted row The main menu now records its highlighted row as it moves, so initialSelection is that row's index rather than the entry last opened. Keeping the highlight on its entry across a save is still needed: the save swaps Save & Exit and Exit without saving for one Exit, which moves the entries below, so the index alone would land on another entry. The comments on MainMenu and List's keepHighlightOnItemsChange say so. * test(tui): walk the main menu to an entry rather than through a fixed list The main menu highlight tests pressed down through a hard-coded list of entries, so an entry another change adds or makes selectable (Configure Status Line opening before an install, say) broke them. They now press down until the target entry is highlighted, waiting for the highlight to move on each press. * test(app): open Color Level directly, now Terminal Options' first row With #765 Terminal Options lists only Color Level, so the steps that went through Terminal Width land on Color Level when the menu opens.
sirmalloc
pushed a commit
that referenced
this pull request
Nov 5, 2026
…fter a sub-screen (#780) * fix(tui): keep Merge highlighted after cancelling the shell-command confirmation When an import adds a Custom Command, choosing Replace All or Merge first asks "Apply this import? It adds a shell command...". Cancel says "Go back to the preview without importing", but coming back from Merge put the highlight on Replace All and switched the preview to the Replace diff. The confirmation doesn't name the mode, so pressing Enter again and confirming applied Replace All, which resets every setting the file leaves out to its default. The confirmation replaces the preview's List, and the List mounted again at its first row, then reported that row as the new selection. Mount it on the mode the preview was showing instead. * fix(tui): let Escape leave Import Preview and its shell-command confirmation Escape did nothing on Import Preview, on both the diff and the "Apply this import? It adds a shell command..." confirmation. The only way out was to arrow down to Cancel and press Enter. The Import Config path dialog one step earlier, and the other menus, go back on Escape, and docs/USAGE.md already says Escape returns from the confirmation to the preview. The dialog had no input handler of its own, and its List only handles the arrows and Enter. Escape now steps back one screen: from the confirmation to the preview, where the mode stays highlighted, and from the preview out of the import, as Cancel does. * fix(tui): keep Color Level highlighted after the custom-colors warning In Terminal Options you press Enter on Color Level to cycle through the levels. With an ansi256 or hex widget color, leaving 256 Color or Truecolor first warns "Custom colors detected!". After Yes, No or Escape the highlight was back on Terminal Width, so the next Enter opened the Terminal Width screen instead of cycling on. The warning replaces the List, and the List mounted again at its first row. Remember the highlighted row, as Powerline Setup does around its confirmations, and mount the List on it. * fix(tui): keep the cancelled setting highlighted in Configure Status Line Pressing Escape on a Refresh Interval or cache TTL prompt brought the list back with the highlight on the first row, Refresh Interval (or Git Cache TTL when Refresh Interval needs a newer Claude Code). Pressing Enter again opened a different setting from the one just left. Saving returns to the Main Menu, so only cancelling showed it. Each prompt replaces the List, and the List mounted again at its first row. Remember the highlighted row and mount the List on it. * fix(tui): keep the chosen update style highlighted when going back in Install In Install to Claude Code, going back from the package manager step (Escape or "← Back") highlighted Pinned global install again, with its description, even after choosing Auto-update. Pressing Enter then led into the pinned global install commands instead of the npx/bunx ones. The style List mounts again on the way back, and it always started on its first row. Start it on the style still held from the first pick. * test(import-preview): mark the command import with colorLevel instead of flexMode flexMode is going away with the Terminal Width options; any non-default key the import carries serves this fixture. * test(terminal-options): start the warning tests on Color Level, now the first row With #765 Terminal Options lists only Color Level, so the two tests start there instead of stepping down from Terminal Width. * fix(tui): drop the Terminal Options row change, which #765 made moot With #765, Color Level is Terminal Options' only setting and the custom-colors warning opens only from it, so the menu comes back on that row without help.
This was referenced Nov 7, 2026
Closed
Closed
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.
Relates to #498 and replaces #702.
What
COLUMNSvariable Claude Code sets for the status line, after theCCSTATUSLINE_WIDTHoverride and before any probing. This is feat(terminal): read COLUMNS from Claude Code before probing #612 by lancemarks: the first commit is that PR's commit, cherry-picked with its authorship kept.flexModeorcompactThresholdloads without an error or warning, and the next save leaves them out.Why
On #702, sirmalloc wrote:
and then:
That other PR is #612, so this builds on it rather than redoing it.
What Claude Code passes: since 2.1.153 ("Status line commands now receive
COLUMNSandLINESenvironment variables so scripts can size output to the terminal width", in its changelog), and in 2.1.310 the status line command runs through the same runner as hooks, which sets both from Claude Code's own terminal size. The status line docs say to rely on it:Until now ccstatusline found the width by walking up the process tree for a tty and running
sttyon it. On macOS that's severalps/sttyprocesses per render (lancemarks measured about 57 ms per render), and on Windows, where probing is disabled, there was no width at all unlessCCSTATUSLINE_WIDTHwas set. That PR has a Windows confirmation: withCOLUMNS, flex separators fill the line there for the first time.The width modes existed because the status line couldn't know when the auto-compact message would appear next to it; the removed menu said "Claude code does not currently provide an available width variable for the statusline". With the real width passed in, Full width always is the only mode left that makes sense. Claude Code fits its own notifications on that row: outside fullscreen rendering they still share it, and per the docs, "On narrow terminals, these notifications may truncate your status line output".
How
Width order (
getTerminalWidth()interminal.ts):CCSTATUSLINE_WIDTH, if it's a positive integerCOLUMNS, if it's a positive integer. Empty,0and non-numeric values fall through, like the override's./procon Linux, theps/sttywalk elsewhere, nothing on Windows. This is unchanged and still covers Claude Code builds that don't setCOLUMNS.lancemarks's commit applies as it is. Its only conflicts were in the docs, because
mainhas since droppedtputfrom the fallbacks; the resolution keepsmain's text and adds that commit's sentences. A second commit updates the Windows troubleshooting entry indocs/WINDOWS.md, which still said Windows has no width withoutCCSTATUSLINE_WIDTH.Removed:
resolveEffectiveTerminalWidth()inrenderer.tsnow subtracts a fixed 6 columns, in piped renders and the preview. The 40-column reserve and the context-percentage switch are gone, sorenderer.tsno longer reads the context percentage.FlexModetype, andflexModeandcompactThresholdin the schema (current and v1) and in the fields the v1 migration copies.TerminalWidthMenuand its tests, and the Terminal Width entry in Terminal Options, which keeps Color Level.terminalWidthscreen inAppand in the dev-reload screens it can restore.configTemplates/, and the modes fromdocs/USAGE.md(the section is now "Terminal Width"),docs/DEVELOPMENT.md,AGENTS.mdand the README's TUI feature list.Old settings: the settings schema is a zod object, which drops keys it doesn't define. So a file with
flexModeandcompactThresholdparses cleanly whatever their values; out-of-range values used to make the whole file invalid and fall back to defaults. Loading doesn't rewrite the file, and the next save writes it without the keys. The legacygit-prwidget type works the same way: it's rewritten in memory and the change lands on the next save. Nothing needs converting, so there's no version bump. Imports ignore the keys too: they aren't in the present-key list a merge applies.Unchanged: for anyone on the default mode the output is byte-identical (
runtime-check.shmatchesmain). Also unchanged:CCSTATUSLINE_WIDTH, the probe and itsterminalWidthCacheTtlSecondscache, and the Terminal Width widget. The visible change is for anyone who picked Full width minus 40 or Full width until compact: their lines now use the full width.Overlapping open PRs: #612's commit is the first commit here, so merging this one covers it. #629 and #728 speed up the
ps/sttyprobe, which no longer runs whenCOLUMNSis set.Demo
The TUI on the same config in both: saved with Full width minus 40, with a flex separator before a "right edge" text widget. Preview values are the widgets' sample data, so all of it is fake. Before (
main), the preview stops 40 columns short and truncates, the Main Menu warns about it, and Terminal Options → Terminal Width lists the three modes. After, the same file renders at the full width with "right edge" at the end, there's no warning, and Terminal Options has only Color Level.Powerline: before
Powerline: after
Plain: before
Plain: after
Testing
bun run lint: clean.bun test: 3690 pass, 0 fail (Bun 1.4.2), onmainas of 2.2.33.COLUMNScases from lancemarks's commit, the updated migration test, and the menu tests.The suite under Node v26.10.0 (
vitest run), compared withmain: no new failing files or tests, and every new or changed test passes.The two Ink test files whose key sequences changed (
App,ImportPreviewDialog): 10 runs, all passing.runtime-check.sh: plain and Powerline piped renders are byte-identical across Bun 1.4.2 and Node v26.10.0 and the same asmain. The TUI smoke test passes on both.Piped renders of a line with a flex separator. The table gives the visible width of line 1; plain and Powerline give the same widths, under both Bun and Node.
mainfullCOLUMNS(the probe finds a 245-column tty)fullCOLUMNS=100fullCOLUMNS=100 CCSTATUSLINE_WIDTH=120full-minus-40CCSTATUSLINE_WIDTH=100full-until-compact, context at 80%CCSTATUSLINE_WIDTH=100flexMode: "not-a-mode",compactThreshold: 500CCSTATUSLINE_WIDTH=100The TUI in tmux under Node and Bun, from a settings file with
flexMode: "full-minus-40"andcompactThreshold: 75. It loads with no warning, and Terminal Options lists only Color Level.ctrl+swrites the file without the two keys and keeps everything else (colorLevel,globalBold, the lines).