- Fixed tmux xterm
modifyOtherKeysmatching forBackspace,Escape, andSpace, and resolved raw\x08backspace ambiguity by treating Windows Terminal sessions differently from legacy terminals (#2293)
- Added configurable
SelectListprimary column sizing viaSelectListLayoutOptions, including custom primary-label truncation hooks (#2154 by @markusylisiurunen)
- Fixed stale scrollback remaining after full-screen redraws such as session switches by clearing the screen before wiping scrollback (#2155 by @Perlence)
- Fixed trailing blank lines after markdown block elements when they are followed immediately by the next block or end of document (#2152 by @markusylisiurunen)
- Fixed Windows shell and path handling in autocomplete to properly handle drive letters and mixed path separators
- Fixed editor paste to preserve literal content instead of normalizing newlines, preventing content corruption for text with embedded escape sequences (#2064)
- Fixed tab completion to preserve
./prefix when completing relative paths (#2087) - Fixed
ctrl+backspacebeing indistinguishable from plainbackspaceon Windows Terminal.0x08is now recognized asctrl+backspaceinstead ofbackspace, makingctrl+backspacebindable on terminals where it produces a distinct byte (#2139)
- Added paste marker atomic segment handling in editor, treating paste markers as indivisible units during word wrapping and cursor navigation (#2111 by @haoqixu)
- Fixed
Inputhorizontal scrolling for wide Unicode text (CJK, fullwidth characters) to use visual column width and strict slice boundaries, preventing rendered line overflow and TUI crashes (#1982) - Fixed xterm
modifyOtherKeyshandling forTabinmatchesKey(), restoringshift+taband other modified Tab bindings in tmux whenextended-keys-formatis left at the defaultxterm - Fixed editor scroll indicator rendering crash in narrow terminal widths (#2103 by @haoqixu)
- Fixed tab characters in editor
setText()and input paths not being normalized to spaces (#2027 by @haoqixu) - Fixed
wordWrapLineoverflow when wide characters (CJK, fullwidth) fall exactly at the wrap boundary (#2082 by @haoqixu) - Fixed tab characters in
Inputpaste not being normalized to spaces (#1975 by @haoqixu)
- Added
treeFoldOrUpandtreeUnfoldOrDowneditor actions with default bindings forCtrl+←/Ctrl+→andAlt+←/Alt+→(#1724 by @Perlence) - Added digit keys (
0-9) to the keybinding system, including Kitty CSI-u and xtermmodifyOtherKeyssupport for bindings likectrl+1(#1905)
- Fixed autocomplete selection ignoring typed text: highlight now follows the first prefix match as the user types, and exact matches are always selected on Enter (#1931 by @aliou)
- Fixed xterm
modifyOtherKeysparsing inmatchesKey()andparseKey(), restoring Ctrl-based keybindings and modified Enter keys in tmux whenextended-keys-formatis left at the defaultxterm(#1872) - Fixed slash-command Tab completion to immediately open argument completions when available (#1481 by @barapa)
- Added non-capturing overlays via
OverlayOptions.nonCapturingand newOverlayHandlemethods:focus(),unfocus(), andisFocused()for programmatic overlay focus control (#1916 by @nicobailon)
- Overlay compositing order now uses focus order so focused overlays render on top while preserving stack semantics for show/hide behavior (#1916 by @nicobailon)
- Fixed automatic focus restoration to skip non-capturing overlays and fixed
hideOverlay()to only reassign focus when the popped overlay had focus (#1916 by @nicobailon)
- Added xterm modifyOtherKeys mode 2 fallback when Kitty keyboard protocol is not available, enabling modified enter keys (Shift+Enter, Ctrl+Enter) inside tmux (#1872)
- Exported
decodeKittyPrintable()fromkeys.tsfor decoding Kitty CSI-u sequences into printable characters
- Fixed
Inputcomponent not accepting typed characters when Kitty keyboard protocol is active (e.g., VS Code 1.110+), causing model selector filter to ignore keystrokes (#1857) - Fixed editor/footer visibility drift during terminal resize by forcing full redraws when terminal width or height changes (#1844 by @ghoulr).
- Fixed markdown blockquote rendering to isolate blockquote styling from default text style, preventing style leakage.
- Fixed TUI width calculation for regional indicator symbols (e.g. partial flag sequences like
🇨during streaming) to prevent wrap drift and stale character artifacts in differential rendering. - Fixed Kitty CSI-u handling to ignore unsupported modifiers so modifier-only events do not insert stray printable characters (#1807)
- Fixed single-line paste performance by inserting pasted text atomically instead of character-by-character, preventing repeated
@autocomplete scans during paste (#1812) - Fixed
visibleWidth()to ignore generic OSC escape sequences (including OSC 133 semantic prompt markers), preventing width drift when terminals emit semantic zone markers (#1805) - Fixed markdown blockquotes dropping nested list content by rendering blockquote children as block-level tokens (#1787)
- Fixed Windows VT input initialization in ESM by loading
koffiviacreateRequire, restoring VT input mode while keepingkoffiexternalized from compiled binaries (#1627 by @kaste)
- Changed koffi import from top-level to dynamic require in
enableWindowsVTInput()to prevent bun from embedding all 18 platform.nodefiles (~74MB) into every compiled binary. Koffi is only needed on Windows.
- Added terminal input listeners in
TUI(addInputListenerandremoveInputListener) to let callers intercept, transform, or consume raw input before component handling.
- Fixed
@autocomplete fuzzy matching to score against path segments and prefixes, reducing irrelevant matches for nested paths (#1423)
- Added
pasteToEditortoEditorComponentAPI for programmatic paste support (#1351 by @kaofelix) - Added kill ring (ctrl+k/ctrl+y/alt+y) and undo (ctrl+z) support to the Input component (#1373 by @Perlence)
- Slash command menu now triggers on the first line even when other lines have content, allowing commands to be prepended to existing text (#1227 by @aliou)
- Fixed
/settingscrashing in narrow terminals by handling small widths in the settings list (#1246 by @haoqixu)
- Added
Terminal.drainInput()to drain stdin before exit (prevents Kitty key release events leaking over slow SSH)
- Fixed Kitty key release events leaking to parent shell over slow SSH connections by draining stdin for up to 1s (#1204)
- Fixed legacy newline handling in the editor to preserve previous newline behavior
- Fixed @ autocomplete to include hidden paths
- Fixed submit fallback to honor configured keybindings
- Added
PI_DEBUG_REDRAW=1env var for debugging full redraws (logs triggers to~/.pi/agent/pi-debug.log)
- Terminal height changes no longer trigger full redraws, reducing flicker on resize
clearOnShrinknow defaults tofalse(usePI_CLEAR_ON_SHRINK=1orsetClearOnShrink(true)to enable)
-
Fixed emoji cursor positioning in Input component (#1183 by @haoqixu)
-
Fixed unnecessary full redraws when appending many lines after content had previously shrunk (viewport check now uses actual previous content size instead of stale maximum)
-
Fixed Ctrl+D exit closing the parent SSH session due to stdin buffer race condition (#1185)
- Added sticky column tracking for vertical cursor navigation so the editor restores the preferred column when moving across short lines. (#1120 by @Perlence)
- Fixed Kitty keyboard protocol base layout fallback so non-QWERTY layouts do not trigger wrong shortcuts (#1096 by @rytswd)
- Optimized
isImageLine()withstartsWithshort-circuit for faster image line detection
- Fixed empty rows appearing below footer when content shrinks (e.g., closing
/tree, clearing multi-line editor) (#1095 by @marckrenn) - Fixed terminal cursor remaining hidden after exiting TUI via
stop()when a render was pending (#1099 by @haoqixu)
- Fixed
isImageLine()to check for image escape sequences anywhere in a line, not just at the start. This prevents TUI crashes when rendering lines containing image data. (#1091 by @zedrdave)
- Added Ctrl+B and Ctrl+F as alternative keybindings for cursor word left/right navigation (#1053 by @ninlds)
- Added character jump navigation: Ctrl+] jumps forward to next character, Ctrl+Alt+] jumps backward (#1074 by @Perlence)
- Editor now jumps to line start when pressing Up at first visual line, and line end when pressing Down at last visual line (#1050 by @4h9fbZ)
- Fixed autocomplete for paths with spaces by supporting quoted path tokens (#1077)
- Fixed quoted path completions to avoid duplicating closing quotes during autocomplete (#1077)
- Added
autocompleteMaxVisibleoption toEditorOptionswith getter/setter methods for configurable autocomplete dropdown height (#972 by @masonc15) - Added
alt+bandalt+fas alternative keybindings for word navigation (cursorWordLeft,cursorWordRight) andctrl+dfordeleteCharForward(#1043 by @jasonish) - Editor auto-applies single suggestion when force file autocomplete triggers with exactly one match (#993 by @Perlence)
- Improved
extractCursorPositionperformance: scans lines in reverse order, early-outs when cursor is above viewport, and limits scan to bottom terminal height (#1004 by @can1357) - Autocomplete improvements: better handling of partial matches and edge cases (#1024 by @Perlence)
- Fixed backslash input buffering causing delayed character display in editor and input components (#1037 by @Perlence)
- Fixed markdown table rendering with proper row dividers and minimum column width (#997 by @tmustier)
- Added
fullRedrawsreadonly property to TUI class for tracking full screen redraws - Added
PI_TUI_WRITE_LOGenvironment variable to capture raw ANSI output for debugging
- 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
codeBlockIndentproperty onMarkdownThemeto customize code block content indentation (default: 2 spaces) (#855 by @terrorobe)- Added Alt+Delete as hotkey for delete word forwards (#878 by @Perlence)
- Fuzzy matching now scores consecutive matches higher and penalizes gaps more heavily for better relevance (#860 by @mitsuhiko)
- 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
- 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)
- Added
showHardwareCursorgetter 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)
EditorOptionswith optionalpaddingXfor horizontal content padding, plusgetPaddingX()/setPaddingX()methods (#791 by @ferologics)
- Hardware cursor is now disabled by default for better terminal compatibility. Set
PI_HARDWARE_CURSOR=1to enable (replacesPI_NO_HARDWARE_CURSOR=1which disabled it).
- 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)
Editorconstructor now requiresTUIas first parameter:new Editor(tui, theme). This enables automatic vertical scrolling when content exceeds terminal height. (#732)
- Hardware cursor positioning for IME support in
EditorandInputcomponents. The terminal cursor now follows the text cursor position, enabling proper IME candidate window placement for CJK input. (#719) Focusableinterface for components that need hardware cursor positioning. Implementfocused: booleanand emitCURSOR_MARKERin render output when focused.CURSOR_MARKERconstant andisFocusable()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)
- 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()andextractAnsiCode()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)
- 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)
OverlayOptionsAPI for overlay positioning and sizing with CSS-like values:width,maxHeight,row,colaccept numbers (absolute) or percentage strings (e.g.,"50%"). Also supportsminWidth,anchor,offsetX,offsetY,margin. (#667 by @nicobailon)OverlayOptions.visiblecallback for responsive overlays - receives terminal dimensions, return false to hide (#667 by @nicobailon)showOverlay()now returnsOverlayHandlewithhide(),setHidden(boolean),isHidden()for programmatic visibility control (#667 by @nicobailon)- New exported types:
OverlayAnchor,OverlayHandle,OverlayMargin,OverlayOptions,SizeValue(#667 by @nicobailon) truncateToWidth()now accepts optionalpadparameter to pad result with spaces to exactlymaxWidth(#667 by @nicobailon)
- Overlay compositing crash when rendered lines exceed terminal width due to complex ANSI/OSC sequences (e.g., hyperlinks in subagent output) (#667 by @nicobailon)
SettingsListOptionswithenableSearchfor fuzzy filtering inSettingsList(#643 by @ninlds)pageUpandpageDownkey support withselectPageUp/selectPageDowneditor actions (#662 by @aliou)
- Numbered list items showing "1." for all items when code blocks break list continuity (#660 by @ogulcancelik)
fuzzyFilter()andfuzzyMatch()utilities for fuzzy text matching- Slash command autocomplete now uses fuzzy matching instead of prefix matching
- 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
- 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.,
:3Fin MAC addresses) was incorrectly filtered out (#623 by @ogulcancelik)
- Experimental: Overlay compositing for
ctx.ui.custom()with{ overlay: true }option (#558 by @nicobailon)
EditorComponentinterface for custom editor implementationsStdinBufferclass to split batched stdin into individual sequences (adapted from OpenTUI, MIT license)
- Key presses no longer dropped when batched with other events over SSH (#538)
Component.wantsKeyReleaseproperty to opt-in to key release events (default false)
- TUI now filters out key release events by default, preventing double-processing of keys in editors and other components
matchesKey()now correctly matches Kitty protocol sequences for unmodified letter keys (needed for key release events)
- Kitty keyboard protocol flag 2 support for key release events. New exports:
isKeyRelease(data),isKeyRepeat(data),KeyEventTypetype. Terminals supporting Kitty protocol (Kitty, Ghostty, WezTerm) now send proper key-up events.
- Crash when pasting text with trailing whitespace exceeding terminal width through Markdown rendering (#457 by @robinwander)
- Symbol key support in keybinding system:
SymbolKeytype with 32 symbol keys,Keyconstants (e.g.,Key.backtick,Key.comma), updatedmatchesKey()andparseKey()to handle symbol input (#450 by @kaofelix)
Editor.getExpandedText()method that returns text with paste markers expanded to their actual content (#444 by @aliou)
- Key detection functions removed: All
isXxx()key detection functions (isEnter(),isEscape(),isCtrlC(), etc.) have been removed. UsematchesKey(data, keyId)instead (e.g.,matchesKey(data, "enter"),matchesKey(data, "ctrl+c")). This affects hooks and custom tools that usectx.ui.custom()with keyboard input handling. (#405)
Editor.insertTextAtCursor(text)method for programmatic text insertion (#419)EditorKeybindingsManagerfor configurable editor keybindings. Components now usematchesKey()and keybindings manager instead of individualisXxx()functions. (#405 by @hjanuschka)
- Key detection refactored: consolidated
is*()functions into genericmatchesKey(data, keyId)function that accepts key identifiers like"ctrl+c","shift+enter","alt+left", etc.
- Slash command autocomplete now triggers for commands starting with
.,-, or_(e.g.,/.land,/-foo) (#422)
- Editor component now uses word wrapping instead of character-level wrapping for better readability (#382 by @nickseelert)
- 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)
visibleWidth()now strips OSC 8 hyperlink sequences, fixing text wrapping for clickable links (#396 by @Cursivez)
isShiftCtrlO()key detection function for Shift+Ctrl+O (Kitty protocol)isShiftCtrlD()key detection function for Shift+Ctrl+D (Kitty protocol)TUI.onDebugcallback for global debug key handling (Shift+Ctrl+D)wrapTextWithAnsi()utility now exported (wraps text to width, preserving ANSI codes)
- 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)
- 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)
- 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)