Repository navigation
Conversation
On Windows, getTerminalWidth() always returned null, so flex separators
collapsed and long-line truncation was disabled. Claude Code spawns the
statusline with piped stdio and no controlling PTY, so
process.stdout.columns is undefined; there's no columns field in the
statusline JSON and no COLUMNS env var to fall back on; and the
existing Unix ps/stty probe doesn't apply on Windows.
This change walks up the process tree to the claude.exe ancestor (which
owns the real console), attaches to that console via a PowerShell
P/Invoke helper, and reads the width from the Win32 console API. The
probe is invoked via spawnSync('powershell.exe', ['-EncodedCommand',
...]) to dodge cmd.exe argument truncation. Cold calls are ~3-5s
(PowerShell startup + Add-Type JIT); the result is cached at
%TEMP%/ccstatusline-win-width-<ppid>.json with a 60s TTL so warm reads
hit disk in ~5ms.
When ccstatusline runs interactively (the TUI launched via
bunx ccstatusline), the process owns its own console and AttachConsole
fails against every ancestor. Since null probe results aren't cached,
every keystroke previously respawned PowerShell. In TUI mode
process.stdout is a real TTY with columns populated, so the Windows
branch returns process.stdout.columns directly and skips the probe.
The "Terminal width detection is currently unavailable in your
environment" warning in the Items Editor has been removed — it existed
to explain the broken Windows behavior.
4f7a07b to
ec28376
Compare
|
i confirm that flex seperator in windows is not working.. a fix like this must be introduced |
|
Heads-up in case it's useful: #612 also aims to give Windows a width, from a different angle. Claude Code 2.1.153, released after this was opened, passes |
|
Closing in favor of #612. Claude Code 2.1.153+ passes 🤖 Made by a clanker |



Summary
On Windows,
getTerminalWidth()always returnednull, so flex separators collapsed and long-line truncation was disabled. Claude Code spawns the statusline with piped stdio and no controlling PTY, soprocess.stdout.columnsis undefined; there's nocolumnsfield in the statusline JSON and noCOLUMNSenv var to fall back on; and the existing Unixps/sttyprobe doesn't apply on Windows.This PR makes width detection work on Windows by walking up the process tree to the
claude.exeancestor (which owns the real console), attaching to that console via a PowerShell P/Invoke helper, and reading the width from the Win32 console API.Performance:
The probe runs synchronously inside ccstatusline (not on Claude Code's main thread, so the REPL is unaffected). Cold call: ~5s (PowerShell startup +
Add-TypeJIT). The result is cached at%TEMP%/ccstatusline-win-width-cache.jsonwith a 60s TTL, so subsequent status-line renders read from disk in ~5ms. Trade-off: up to 60s of resize lag before the cache refreshes — acceptable for a status line.Changes
src/utils/terminal.tsgetTerminalWidth(). Shells out to the probe, caches the result at%TEMP%/ccstatusline-win-width-<ppid>.jsonwith a 60s TTL, returnsnullon any failure (no regression). In TUI mode (stdout is a real TTY) it returnsprocess.stdout.columnsdirectly and skips the probe. Non-Windows paths untouched.scripts/windows-width-probe.ps1(new)CreateToolhelp32Snapshot,AttachConsoles to the owning process, readsCONSOLE_SCREEN_BUFFER_INFO.dwSize.X. Invoked viaspawnSync -EncodedCommandto avoidcmd.exearg truncation.src/tui/components/ItemsEditor.tsxsrc/utils/__tests__/terminal.test.tsprocess.platformexplicitly so they pass on Windows dev boxes.package.jsonbuildscript copies the probe intodist/so the published package ships it.Test plan
bun run vitest run src/utils/__tests__/terminal.test.ts— 12 tests pass.bun run lint— clean for touched files.bun run build, pointstatusLine.commandatdist/ccstatusline.js, add a Flex Separator, resize Windows Terminal — line spans full width, reflows on resize within the 60s TTL.