co-mono/packages/tui/CHANGELOG.md
Mario Zechner a6f9c3cf0d fix(tui): fix scrollback overwrite when appending lines past viewport
Appended lines were not committed to terminal scrollback because the
renderer used cursor movement (CSI B) and carriage return without
linefeed. This caused earlier content to be overwritten when the
viewport filled up.

Changes:
- For appended lines, emit \r\n to create real scrollback lines
- When target row is below viewport, scroll with \r\n before positioning
- Add PI_TUI_WRITE_LOG env var for debugging raw ANSI output
- Add fullRedraws readonly property to TUI class
- Add viewport-overwrite-repro.ts test script

fixes #954
2026-01-26 16:51:28 +01:00

16 KiB

Changelog

[Unreleased]

Added

  • Added fullRedraws readonly property to TUI class for tracking full screen redraws
  • Added PI_TUI_WRITE_LOG environment variable to capture raw ANSI output for debugging

Fixed

  • Fixed appended lines not being committed to scrollback, causing earlier content to be overwritten when viewport fills (#954)
  • Slash command menu now only triggers when the editor input is otherwise empty (#904)
  • Center-anchored overlays now stay vertically centered when resizing the terminal taller after a shrink (#950 by @nicobailon)
  • Fixed editor multi-line insertion handling and lastAction tracking (#945 by @Perlence)
  • Fixed editor word wrapping to reserve a cursor column (#934 by @Perlence)
  • Fixed editor word wrapping to use single-pass backtracking for whitespace handling (#924 by @Perlence)
  • Fixed Kitty image ID allocation and cleanup to prevent image ID collisions between modules

[0.49.3] - 2026-01-22

Added

  • codeBlockIndent property on MarkdownTheme to customize code block content indentation (default: 2 spaces) (#855 by @terrorobe)
  • Added Alt+Delete as hotkey for delete word forwards (#878 by @Perlence)

Changed

  • Fuzzy matching now scores consecutive matches higher and penalizes gaps more heavily for better relevance (#860 by @mitsuhiko)

Fixed

  • Autolinked emails no longer display redundant (mailto:...) suffix in markdown output (#888 by @terrorobe)
  • Fixed viewport tracking and cursor positioning for overlays and content shrink scenarios
  • Autocomplete now allows searches with / characters (e.g., folder1/folder2) (#882 by @richardgill)
  • Directory completions for @ file attachments no longer add trailing space, allowing continued autocomplete into subdirectories

[0.49.2] - 2026-01-19

[0.49.1] - 2026-01-18

Added

  • Added undo support to Editor with Ctrl+- hotkey. Undo coalesces consecutive word characters into one unit (fish-style). (#831 by @Perlence)
  • Added legacy terminal support for Ctrl+symbol keys (Ctrl+, Ctrl+], Ctrl+-) and their Ctrl+Alt variants. (#831 by @Perlence)

[0.49.0] - 2026-01-17

Added

  • Added showHardwareCursor getter and setter to control cursor visibility while keeping IME positioning active. (#800 by @ghoulr)
  • Added Emacs-style kill ring editing with yank and yank-pop keybindings. (#810 by @Perlence)
  • Added legacy Alt+letter handling and Alt+D delete word forward support in the editor keymap. (#810 by @Perlence)

[0.48.0] - 2026-01-16

Added

  • EditorOptions with optional paddingX for horizontal content padding, plus getPaddingX()/setPaddingX() methods (#791 by @ferologics)

Changed

  • Hardware cursor is now disabled by default for better terminal compatibility. Set PI_HARDWARE_CURSOR=1 to enable (replaces PI_NO_HARDWARE_CURSOR=1 which disabled it).

Fixed

  • Decode Kitty CSI-u printable sequences in the editor so shifted symbol keys (e.g., @, ?) work in terminals that enable Kitty keyboard protocol (#779 by @iamd3vil)

[0.47.0] - 2026-01-16

Breaking Changes

  • Editor constructor now requires TUI as first parameter: new Editor(tui, theme). This enables automatic vertical scrolling when content exceeds terminal height. (#732)

Added

  • Hardware cursor positioning for IME support in Editor and Input components. The terminal cursor now follows the text cursor position, enabling proper IME candidate window placement for CJK input. (#719)
  • Focusable interface for components that need hardware cursor positioning. Implement focused: boolean and emit CURSOR_MARKER in render output when focused.
  • CURSOR_MARKER constant and isFocusable() type guard exported from the package
  • Editor now supports Page Up/Down keys (Fn+Up/Down on MacBook) for scrolling through large content (#732)
  • Expanded keymap coverage for terminal compatibility: added support for Home/End keys in tmux, additional modifier combinations, and improved key sequence parsing (#752 by @richardgill)

Fixed

  • Editor no longer corrupts terminal display when text exceeds screen height. Content now scrolls vertically with indicators showing lines above/below the viewport. Max height is 30% of terminal (minimum 5 lines). (#732)
  • visibleWidth() and extractAnsiCode() now handle APC escape sequences (ESC _ ... BEL), fixing width calculation and string slicing for strings containing cursor markers
  • SelectList now handles multi-line descriptions by replacing newlines with spaces (#728 by @richardgill)

[0.46.0] - 2026-01-15

Fixed

  • Keyboard shortcuts (Ctrl+C, Ctrl+D, etc.) now work on non-Latin keyboard layouts (Russian, Ukrainian, Bulgarian, etc.) in terminals supporting Kitty keyboard protocol with alternate key reporting (#718 by @dannote)

[0.45.7] - 2026-01-13

[0.45.6] - 2026-01-13

Added

  • OverlayOptions API for overlay positioning and sizing with CSS-like values: width, maxHeight, row, col accept numbers (absolute) or percentage strings (e.g., "50%"). Also supports minWidth, anchor, offsetX, offsetY, margin. (#667 by @nicobailon)
  • OverlayOptions.visible callback for responsive overlays - receives terminal dimensions, return false to hide (#667 by @nicobailon)
  • showOverlay() now returns OverlayHandle with hide(), setHidden(boolean), isHidden() for programmatic visibility control (#667 by @nicobailon)
  • New exported types: OverlayAnchor, OverlayHandle, OverlayMargin, OverlayOptions, SizeValue (#667 by @nicobailon)
  • truncateToWidth() now accepts optional pad parameter to pad result with spaces to exactly maxWidth (#667 by @nicobailon)

Fixed

  • Overlay compositing crash when rendered lines exceed terminal width due to complex ANSI/OSC sequences (e.g., hyperlinks in subagent output) (#667 by @nicobailon)

[0.45.5] - 2026-01-13

[0.45.4] - 2026-01-13

[0.45.3] - 2026-01-13

[0.45.2] - 2026-01-13

[0.45.1] - 2026-01-13

[0.45.0] - 2026-01-13

[0.44.0] - 2026-01-12

Added

  • SettingsListOptions with enableSearch for fuzzy filtering in SettingsList (#643 by @ninlds)
  • pageUp and pageDown key support with selectPageUp/selectPageDown editor actions (#662 by @aliou)

Fixed

  • Numbered list items showing "1." for all items when code blocks break list continuity (#660 by @ogulcancelik)

[0.43.0] - 2026-01-11

Added

  • fuzzyFilter() and fuzzyMatch() utilities for fuzzy text matching
  • Slash command autocomplete now uses fuzzy matching instead of prefix matching

Fixed

  • Cursor now moves to end of content on exit, preventing status line from being overwritten (#629 by @tallshort)
  • Reset ANSI styles after each rendered line to prevent style leakage

[0.42.5] - 2026-01-11

Fixed

  • Reduced flicker by only re-rendering changed lines (#617 by @ogulcancelik)
  • Cursor position tracking when content shrinks with unchanged remaining lines
  • TUI renders with wrong dimensions after suspend/resume if terminal was resized while suspended (#599)
  • Pasted content containing Kitty key release patterns (e.g., :3F in MAC addresses) was incorrectly filtered out (#623 by @ogulcancelik)

[0.42.4] - 2026-01-10

[0.42.3] - 2026-01-10

[0.42.2] - 2026-01-10

[0.42.1] - 2026-01-09

[0.42.0] - 2026-01-09

[0.41.0] - 2026-01-09

[0.40.1] - 2026-01-09

[0.40.0] - 2026-01-08

[0.39.1] - 2026-01-08

[0.39.0] - 2026-01-08

Added

  • Experimental: Overlay compositing for ctx.ui.custom() with { overlay: true } option (#558 by @nicobailon)

[0.38.0] - 2026-01-08

Added

  • EditorComponent interface for custom editor implementations
  • StdinBuffer class to split batched stdin into individual sequences (adapted from OpenTUI, MIT license)

Fixed

  • Key presses no longer dropped when batched with other events over SSH (#538)

[0.37.8] - 2026-01-07

Added

  • Component.wantsKeyRelease property to opt-in to key release events (default false)

Fixed

  • TUI now filters out key release events by default, preventing double-processing of keys in editors and other components

[0.37.7] - 2026-01-07

Fixed

  • matchesKey() now correctly matches Kitty protocol sequences for unmodified letter keys (needed for key release events)

[0.37.6] - 2026-01-06

Added

  • Kitty keyboard protocol flag 2 support for key release events. New exports: isKeyRelease(data), isKeyRepeat(data), KeyEventType type. Terminals supporting Kitty protocol (Kitty, Ghostty, WezTerm) now send proper key-up events.

[0.37.5] - 2026-01-06

[0.37.4] - 2026-01-06

[0.37.3] - 2026-01-06

[0.37.2] - 2026-01-05

[0.37.1] - 2026-01-05

[0.37.0] - 2026-01-05

Fixed

  • Crash when pasting text with trailing whitespace exceeding terminal width through Markdown rendering (#457 by @robinwander)

[0.36.0] - 2026-01-05

[0.35.0] - 2026-01-05

[0.34.2] - 2026-01-04

[0.34.1] - 2026-01-04

Added

  • Symbol key support in keybinding system: SymbolKey type with 32 symbol keys, Key constants (e.g., Key.backtick, Key.comma), updated matchesKey() and parseKey() to handle symbol input (#450 by @kaofelix)

[0.34.0] - 2026-01-04

Added

  • Editor.getExpandedText() method that returns text with paste markers expanded to their actual content (#444 by @aliou)

[0.33.0] - 2026-01-04

Breaking Changes

  • Key detection functions removed: All isXxx() key detection functions (isEnter(), isEscape(), isCtrlC(), etc.) have been removed. Use matchesKey(data, keyId) instead (e.g., matchesKey(data, "enter"), matchesKey(data, "ctrl+c")). This affects hooks and custom tools that use ctx.ui.custom() with keyboard input handling. (#405)

Added

  • Editor.insertTextAtCursor(text) method for programmatic text insertion (#419)
  • EditorKeybindingsManager for configurable editor keybindings. Components now use matchesKey() and keybindings manager instead of individual isXxx() functions. (#405 by @hjanuschka)

Changed

  • Key detection refactored: consolidated is*() functions into generic matchesKey(data, keyId) function that accepts key identifiers like "ctrl+c", "shift+enter", "alt+left", etc.

[0.32.3] - 2026-01-03

[0.32.2] - 2026-01-03

Fixed

  • Slash command autocomplete now triggers for commands starting with ., -, or _ (e.g., /.land, /-foo) (#422)

[0.32.1] - 2026-01-03

[0.32.0] - 2026-01-03

Changed

  • Editor component now uses word wrapping instead of character-level wrapping for better readability (#382 by @nickseelert)

Fixed

  • Shift+Space, Shift+Backspace, and Shift+Delete now work correctly in Kitty-protocol terminals (Kitty, WezTerm, etc.) instead of being silently ignored (#411 by @nathyong)

[0.31.1] - 2026-01-02

Fixed

  • visibleWidth() now strips OSC 8 hyperlink sequences, fixing text wrapping for clickable links (#396 by @Cursivez)

[0.31.0] - 2026-01-02

Added

  • isShiftCtrlO() key detection function for Shift+Ctrl+O (Kitty protocol)
  • isShiftCtrlD() key detection function for Shift+Ctrl+D (Kitty protocol)
  • TUI.onDebug callback for global debug key handling (Shift+Ctrl+D)
  • wrapTextWithAnsi() utility now exported (wraps text to width, preserving ANSI codes)

Changed

  • README.md completely rewritten with accurate component documentation, theme interfaces, and examples
  • visibleWidth() reimplemented with grapheme-based width calculation, 10x faster on Bun and ~15% faster on Node (#369 by @nathyong)

Fixed

  • Markdown component now renders HTML tags as plain text instead of silently dropping them (#359)
  • Crash in visibleWidth() and grapheme iteration when encountering undefined code points (#372 by @HACKE-RC)
  • ZWJ emoji sequences (rainbow flag, family, etc.) now render with correct width instead of being split into multiple characters (#369 by @nathyong)

[0.29.0] - 2025-12-25

Added

  • Auto-space before pasted file paths: When pasting a file path (starting with /, ~, or .) and the cursor is after a word character, a space is automatically prepended for better readability. Useful when dragging screenshots from macOS. (#307 by @mitsuhiko)
  • Word navigation for Input component: Added Ctrl+Left/Right and Alt+Left/Right support for word-by-word cursor movement. (#306 by @kim0)
  • Full Unicode input: Input component now accepts Unicode characters beyond ASCII. (#306 by @kim0)

Fixed

  • Readline-style Ctrl+W: Now skips trailing whitespace before deleting the preceding word, matching standard readline behavior. (#306 by @kim0)