Symptom
In a narrow terminal — e.g. a small tmux split pane — the live countdown / progress bar reprints on a new line every tick instead of redrawing in place, scrolling the pane with repeated bars. Painful in tmux when devflow lives in a split.
Cause
tickLine() redraws in place with a leading \r (src/lib/display.ts:50):
process.stdout.write(`\r ${label} ${bar} ${chalk.bold(time)}${pom} `);
The bar is a fixed width — BAR_WIDTH (src/lib/display.ts:26-29) — so the rendered line has a fixed minimum length regardless of terminal size. When that length exceeds process.stdout.columns, the terminal soft-wraps the line onto a second physical row. \r only returns the cursor to the start of the current physical line, so the wrapped remainder is never overwritten — each tick leaves the wrap behind and the pane scrolls.
Fix ideas
- Make the tick line width-aware: read
process.stdout.columns and scale BAR_WIDTH (or drop the bar entirely below some threshold, showing just label + time).
- Clear the line before redraw with
\x1b[K (already used at start.ts:134) and ensure the content fits one physical row — truncate to columns so it can never wrap.
- Listen for
process.stdout.on("resize") to recompute width live as the pane is resized.
- Keep it best-effort / greyscale-compact per the existing UI conventions.
Repro
pnpm dev start --demo in a tmux pane narrowed to ~30-40 columns; watch the bar reprint each second instead of updating in place.
Symptom
In a narrow terminal — e.g. a small tmux split pane — the live countdown / progress bar reprints on a new line every tick instead of redrawing in place, scrolling the pane with repeated bars. Painful in tmux when devflow lives in a split.
Cause
tickLine()redraws in place with a leading\r(src/lib/display.ts:50):The bar is a fixed width —
BAR_WIDTH(src/lib/display.ts:26-29) — so the rendered line has a fixed minimum length regardless of terminal size. When that length exceedsprocess.stdout.columns, the terminal soft-wraps the line onto a second physical row.\ronly returns the cursor to the start of the current physical line, so the wrapped remainder is never overwritten — each tick leaves the wrap behind and the pane scrolls.Fix ideas
process.stdout.columnsand scaleBAR_WIDTH(or drop the bar entirely below some threshold, showing justlabel + time).\x1b[K(already used atstart.ts:134) and ensure the content fits one physical row — truncate tocolumnsso it can never wrap.process.stdout.on("resize")to recompute width live as the pane is resized.Repro
pnpm dev start --demoin a tmux pane narrowed to ~30-40 columns; watch the bar reprint each second instead of updating in place.