fullRender wrote \x1b[3J\x1b[2J\x1b[H (clear scrollback, then clear
screen). But \x1b[2J pushes on-screen content into scrollback, undoing
the preceding \x1b[3J. Reorder to \x1b[2J\x1b[H\x1b[3J so the screen is
cleared first and scrollback is wiped last.
- Remove height change detection (only width changes trigger full redraw)
- Change clearOnShrink default to false (use PI_CLEAR_ON_SHRINK=1 to enable)
- Fix viewport check to use previousLines.length instead of maxLinesRendered
(prevents false positive redraws when appending lines after content shrunk)
- Add clearOnShrink setting to /settings in coding-agent
- Remove line truncation in custom message component (always show full content)
- Add height change detection (analogous to existing width detection)
- Auto-detect when content shrinks below maxLinesRendered and trigger
full re-render to clear leftover empty rows
- Only triggers when no overlays are active (overlays need padding)
Fixes empty rows appearing below footer when:
- Closing /tree or other selectors
- Clearing multi-line editor content
- Any component shrinking
Also adds regression tests for resize handling and content shrinkage.
- Add isImageLine() to terminal-image.ts with single startsWith check based on detected terminal protocol
- Replace dual includes() checks in tui.ts with imported isImageLine()
- Add image line handling to markdown.ts to skip wrapping and margins for image escapes
- Consolidate Box cache into RenderCache type with childLines/width/bgSample/lines fields
- Use in-place mutation in applyLineResets() to avoid array allocation
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
- Add maxLinesRendered to track terminal's working area (grows with content, only resets on full clear)
- Fix viewport calculation: use maxLinesRendered instead of cursorRow for correct viewport bounds
- Separate cursorRow (end of content for viewport calc) from hardwareCursorRow (actual cursor position)
- Refactor full render into fullRender(clear) helper to reduce duplication
- Fix shrink-clearing: properly clear extra lines when content shrinks
- Add PI_TUI_DEBUG=1 env var for render debugging (writes to /tmp/tui/)
The core issue was that after partial renders (e.g., overlay show/hide), the viewport
calculation used cursorRow which reflected where rendering stopped, not where content
ended. This caused incorrect viewport bounds, leading to cursor movement into scrollback
(unreachable) or rendering at wrong positions.
Additionally, when content shrank (e.g., selector dismissed), the terminal still had
the old lines as blank space. maxLinesRendered tracks this so viewport calculations
account for the terminal's actual working area.
Fixes cursor visibility issues in JetBrains IDE terminals (IntelliJ, PyCharm) where
the hardware cursor either blinks or becomes invisible depending on settings.
Fixes#771
- Add Focusable interface for components that need hardware cursor positioning
- Add CURSOR_MARKER (APC escape sequence) for marking cursor position in render output
- Editor and Input components implement Focusable and emit marker when focused
- TUI extracts cursor position from rendered output and positions hardware cursor
- Track hardwareCursorRow separately from cursorRow for differential rendering
- visibleWidth() and extractAnsiCode() now handle APC sequences
- Update overlay-test.ts example to demonstrate Focusable usage
- Add documentation for Focusable interface in docs/tui.md
Closes#719, closes#525
Add OverlayOptions for configurable positioning (anchor, margins, offsets,
percentages). Add OverlayHandle for programmatic visibility control with
hide/setHidden/isHidden. Add visible callback for responsive overlays.
Extension API: ctx.ui.custom() now accepts overlayOptions and onHandle callback.
Examples: overlay-qa-tests.ts (10 test commands), doom-overlay (DOOM at 35 FPS).
- Send SIGWINCH to self on terminal start to refresh stale dimensions (Unix only)
- Change requestRender(true) to set previousWidth = -1 to trigger widthChanged
- Update first render condition to skip when widthChanged is true
Fixes#599
Adds overlay rendering capability to the TUI, enabling floating modal
components that render on top of existing content without clearing the screen.
- Add showOverlay(), hideOverlay(), hasOverlay() methods to TUI
- Implement ANSI-aware line compositing via extractSegments()
- Support overlay stack (multiple overlays, later on top)
- Add { overlay: true } option to ctx.ui.custom()
- Add overlay-test.ts example extension
Also fixes pre-existing bug where bash tool output cached visual lines
at fixed terminal width, causing crashes on terminal resize.
Co-authored-by: Nico Bailon <nico.bailon@gmail.com>
The cell size query response parser was incorrectly holding back Kitty
keyboard protocol sequences, thinking they might be incomplete cell size
responses. This caused Ctrl+C/Ctrl+D to require multiple presses in iTerm2.
Fixed by only waiting for more data if the buffer doesn't end with a
terminal escape sequence terminator character.
- Image component returns correct number of lines (rows) for TUI accounting
- Empty lines rendered first, then cursor moves up and image is drawn
- This clears the space the image occupies before rendering
- Add spacer before inline images in tool output
- Create ShowImagesSelectorComponent with borders like other selectors
- Use showSelector pattern for /show-images command
- Add getCellDimensions/setCellDimensions to terminal-image.ts
- TUI queries cell size on startup via CSI 16 t
- Parse response and filter it from user input
- Invalidate and re-render when cell dimensions received
- Pass rows parameter to Kitty protocol for correct aspect ratio
- Add /compact command for manual context compaction with optional custom instructions
- Add /autocompact command to toggle automatic compaction
- Auto-trigger compaction when context usage exceeds threshold (contextWindow - reserveTokens)
- Add CompactionComponent for TUI display with collapsed/expanded states
- Add compaction events to HTML export with collapsible summary
- Refactor export-html.ts to eliminate duplication between session and streaming formats
- Use setTimeout to break out of agent event handler for safe async compaction
- Show compaction summary in TUI after compaction completes
fixes#92