When pressing Enter on a highlighted slash command suggestion (e.g., typing
`/mod` with `/model` highlighted), the completion is now applied before
submitting. Previously, the partial text was submitted instead of the
selected command.
Fixes#49
- Fixed catastrophic regex backtracking in extractPathPrefix that caused
terminal to hang when text contained many / characters (e.g., URLs).
Replaced complex regex with simple lastIndexOf approach. (#18)
- Fixed arrow keys moving both autocomplete selection and editor cursor
by adding missing return statement after handling arrow keys in
autocomplete mode.
Closes#18
- Consolidated theme system into single src/theme/ directory
- Created Theme class with fg(), bg(), bold(), italic(), underline()
- Added dark and light built-in themes with 36 color tokens
- Support for custom themes in ~/.pi/agent/themes/*.json
- JSON schema for theme validation
- Theme selector UI with /theme command
- Save theme preference to settings
- Uses chalk for text formatting to preserve colors
TODO:
- Replace hardcoded colors throughout TUI components
- Apply markdown theming to Markdown components
- Add theme support to all TUI elements
The horizontal borders around the input editor now change color based on
the current thinking level, providing immediate visual feedback:
- off: gray (default)
- minimal: dim blue
- low: blue
- medium: cyan
- high: magenta
The more thinking, the brighter/more vibrant the color.
Changes:
- Add public borderColor property to Editor component (packages/tui)
- Use borderColor instead of hardcoded chalk.gray for borders
- Add getThinkingBorderColor() helper in TuiRenderer
- Add updateEditorBorderColor() to apply color changes
- Update border color when:
- Cycling with Tab key
- Selecting via /thinking command
- Restoring session with thinking level set
- Created shared wrapTextWithAnsi() function in utils.ts
- Handles word-based wrapping while preserving ANSI escape codes
- Properly tracks active ANSI codes across wrapped lines
- Supports multi-byte characters (emoji, surrogate pairs)
- Updated Markdown and Text components to use shared wrapping
- Removed duplicate wrapping logic (158 lines total)
- Use 'charCodeAt(0) >= 32' instead of open 'else' in handleInput()
- Use same filter in handlePaste() for consistency
- Prevents control characters while allowing all unicode
- More explicit and safer than accepting everything
- Add Ctrl+W for word deletion (stops at whitespace/punctuation)
- Add Ctrl+U for delete to start of line (merges with previous line at col 0)
- Change Ctrl+K from delete entire line to delete to end of line (merges with next line at EOL)
- Add Option+Backspace support in Ghostty (maps to Ctrl+W via ESC+DEL sequence)
- Cmd+Backspace in Ghostty works as Ctrl+U (terminal sends same control code)
- Update README and CHANGELOG with new keyboard shortcuts
Fixes#2, Fixes#3
- State upfront: pi does not support MCP
- Provide minimal working example (README + bash script)
- Show simple usage pattern
- Remove verbose explanations
fix(tui): don't show duplicate URL when link text equals href
- Add generateDiffString() function in edit tool to create unified diffs with line numbers and 4 lines of context
- Store only the formatted diff string in tool result details instead of full file contents
- Update tool-execution renderer to parse and colorize the diff string
- Filter out message_update events from session saving to prevent verbose session files
- Add markdown nested list and table rendering tests
- Custom SessionList component with 2 lines per item
- First line: message text (bold when selected)
- Second line: metadata (time · message count) in dim
- Blue › cursor for selected item
- Added "Resume Session" header
- Handle Ctrl+C (‹x03›) in SelectList for consistency
- Improved date formatting (38 minutes ago, 8 hours ago, etc.)
Thinking selector fix:
- Replace hardcoded 50-character borders with DynamicBorder component
that adjusts to viewport width
- Prevents crash when terminal is resized narrow
Text/Markdown rendering fixes:
- Fix Markdown wrapSingleLine to check if adding next character would
exceed width BEFORE adding it (was checking AFTER, causing lines to
be 1 character too long)
- Add word truncation in Text component for words longer than
contentWidth (prevents long unbreakable words from exceeding width)
These fixes prevent "Rendered line exceeds terminal width" errors.
SelectList fixes:
- Use hardcoded visual width for arrow prefix instead of string length
which includes ANSI codes
- Truncate scroll indicator text to prevent exceeding terminal width
- Fixes crash when terminal is resized narrow and arrow keys are pressed
Thinking level fix:
- Restore thinking level even if it's "off" (removed !== "off" check)
- This ensures the thinking level selector shows the correct state on continue
Replace tabs with 3 spaces for consistent rendering and width calculation:
- Updated visibleWidth() to normalize tabs before measuring
- Updated Text and Markdown components to replace tabs when rendering
- Updated tool-execution display for read/write tools to replace tabs
This fixes background color rendering issues when displaying files with tab indentation.
- Show tool execution components immediately when tool calls appear in streaming
- Update components with streaming arguments as they come in
- Handle incomplete/partial arguments gracefully with optional chaining
- Fix error handling: tools now throw exceptions instead of returning error messages
- Fix bash abort handling to properly reject on abort/timeout
- Clean up error display
- Create UserMessageComponent - handles user messages with spacing
- Create AssistantMessageComponent - handles complete assistant messages
- Create ThinkingSelectorComponent - wraps selector with borders
- Add setSelectedIndex to SelectList for preselecting current level
- Simplify tui-renderer by using dedicated components
- Much cleaner architecture - each message type is now a component
- Add background color support to Text component
- Replace Markdown component with Text in ToolExecutionComponent
- Use chalk.bold for formatting instead of markdown syntax
- Remove unnecessary markdown parsing overhead
- Add /thinking slash command with autocomplete for setting reasoning levels (off, minimal, low, medium, high)
- Fix Ctrl+C behavior: remove hardcoded exit in TUI, let focused component handle it
- Add empty lines before and after tool execution components for better visual separation
- Fix stats rendering: display stats AFTER tool executions complete (matches web-ui behavior)
- Remove "Press Ctrl+C again to exit" message, show "(esc to interrupt)" in loader instead
- Add bash tool abort signal support with immediate SIGKILL on interrupt
- Make Text and Markdown components return empty arrays when no actual text content
- Add setCustomBgRgb() method to Markdown for dynamic background colors
- Added string-width library for proper terminal column width calculation
- Fixed wrapLine() to split by newlines before wrapping (like Text component)
- Fixed Loader interval leak by stopping before container removal
- Changed loader message from 'Loading...' to 'Working...'
- Remove old TUI implementation and components (LoadingAnimation, MarkdownComponent, TextComponent, TextEditor, WhitespaceComponent)
- Rename components-new to components with new API (Loader, Markdown, Text, Editor, Spacer)
- Move Text and Input components to separate files in src/components/
- Add render caching to Text component (similar to Markdown)
- Add proper ANSI code handling in Text component using stripVTControlCharacters
- Update coding-agent to use new TUI API (requires ProcessTerminal, uses custom Editor subclass for key handling)
- Remove old test files, keep only chat-simple.ts and virtual-terminal.ts
- Update README.md with new minimal API documentation
- Switch from tsc to tsgo for type checking
- Update package dependencies across monorepo
- Paste markers now show line count: [paste #1 +50 lines]
- Update replacement logic to handle both old and new marker formats
- Provides better visibility into paste size
- Add paddingX and paddingY support to Text component (default 1, 1)
- Fix padding calculation bug in both Text and Markdown
- Right padding now correctly fills to terminal width
- Remove unused Spacer import from chat-simple
- Enable bracketed paste mode for handling large pastes
- Fix editor duplicate line rendering bug at terminal width
- Add padding support to Markdown component (paddingX/Y)
- Add Spacer component for vertical spacing
- Update chat-simple with spacers between messages
- Implemented new renderLineBased method that properly handles scrollback boundaries
- Fixed ANSI code preservation in MarkdownComponent line wrapping
- Added comprehensive test to reproduce and verify the fix
- Root cause: PARTIAL rendering strategy couldn't position cursor in scrollback
- Solution: Component-agnostic line comparison with proper viewport boundary handling
Fixed rendering artifact where duplicate bottom borders appeared when components
dynamically shifted positions (e.g., Ctrl+C in agent clearing status container).
Root cause: Container wasn't reporting as "changed" when cleared (0 children),
causing differential renderer to skip re-rendering that area.
Solution: Container now tracks previousChildCount and reports changed when
child count changes, ensuring proper re-rendering when containers are cleared.
- Added comprehensive test reproducing the layout shift artifact
- Fixed Container to track and report child count changes
- All tests pass including new layout shift artifact test
The demos were not showing any output until user input because:
- Components were added before ui.start() was called
- addChild calls requestRender() but it returns early if \!isStarted
- So no initial render happened until user input triggered one
Now ui.start() triggers an initial render if components exist.
- New renderDifferentialSurgical method with three strategies:
- SURGICAL: Only update specific changed lines (1-2 lines per render)
- PARTIAL: Clear and re-render from first change when line counts change
- FULL: Clear scrollback and re-render all when changes above viewport
- Preserves all content in scrollback buffer correctly
- Reduces redraws from ~14 lines to ~1.3 lines for common updates
- All 24 tests pass including scrollback preservation tests
- Massive performance improvement: 90% reduction in unnecessary redraws