Skip to content

Conversation

@pyramation
Copy link
Contributor

@pyramation pyramation commented Dec 27, 2025

feat(inquirerer): add Claude Code-style terminal UI with welcome box

Summary

This PR implements a Claude Code-style terminal UI based on the terminal UI spec Dan provided. The implementation adds:

  • ViewportRenderer (dev/ai/viewport.ts): A renderer that reserves a fixed region at the bottom of the terminal and updates it in-place using cursor positioning to avoid flicker
  • AICodeUI (dev/ai/aicode.ts): A complete chat interface with streaming text display, line editor for input, status bar, and in-app scrolling
  • Demo (dev/demo-ai-code.ts): Interactive demo showcasing the new components with simulated AI responses

Note: The AI code files are intentionally placed in dev/ai/ rather than src/ui/ so they are not bundled with the published package. This is demo/experimental code. The keypress.ts additions (new KEY_CODES for readline-style editing) remain in src/ as they are purely additive and useful for other components.

Key features:

  • Claude Code-style welcome box: Rounded corners (╭╮╰╯), two-column layout with tips and keybindings
  • Conversation markers: > prefix for user messages, bullet for assistant responses
  • Animated streaming spinner: Braille spinner with "Thinking..." status during AI responses
  • Full-width separators: Horizontal lines span the entire terminal width
  • Input hints: Shows ↵ send when input has content
  • Readline-style line editing: Ctrl+A/E (start/end of line), Alt+B/F (word navigation), Ctrl+W/K/U (word/line deletion), Home/End keys
  • Multiline input: Ctrl+J inserts newline, Enter submits. Input area grows dynamically up to available viewport space
  • Smart UP/DOWN navigation: Navigates between lines in multiline input; falls back to history at boundaries
  • Message scrolling: PageUp/PageDown scroll through chat history
  • Extensible keybinding system: addBinding()/removeBinding() methods for customization

Updates since last revision

  • Moved AI code to dev/ai/ folder: aicode.ts and viewport.ts are now in dev/ai/ instead of src/ui/ so they won't be bundled with the published package. The keypress.ts additions (purely additive KEY_CODES) remain in src/.
  • Enforced viewport height invariant: Added bottom-anchored clamping to guarantee exactly viewportHeight lines every frame, preventing content from rendering below the terminal viewport.
  • Moved string-width to devDependencies: Since string-width is only used by the AI code demo in dev/ai/, it's now a devDependency rather than a production dependency.
  • Removed unused dependencies: Removed ansi-diff and js-yaml from dependencies - they were not imported anywhere in the codebase and were adding unnecessary install footprint for consumers.

Review & Testing Checklist for Human

This is a yellow risk PR - the code compiles and existing tests pass, but the new functionality has no automated tests and requires manual verification in a real terminal.

  • Test the demo works after reorganization: Run cd packages/inquirerer && pnpm dev:ai-code and verify the demo launches correctly with the welcome box
  • Test viewport stability: Verify the UI stays stable on launch (no "filling screen upward" with duplicate status lines)
  • Test streaming: Send a message (try "typescript") and verify content appears only once during streaming

Notes

  • The AI code is in dev/ai/ and excluded from the npm package build - this is intentional
  • The keypress.ts changes are purely additive (new KEY_CODES) and don't affect existing functionality
  • string-width is now a devDependency since it's only used by the demo code
  • ansi-diff and js-yaml were removed entirely (not imported anywhere)
  • No unit tests were added for the new components - this is a demo/MVP implementation
  • Terminal compatibility: Box-drawing characters (╭╮╰╯│─) and Unicode symbols (⏺, ↵) may not render correctly in all terminals/fonts
  • Spinner animation runs at 100ms intervals (also controls cursor blink)

Link to Devin run: https://app.devin.ai/sessions/df242c2990d74fc6aa58e95e8e050d86
Requested by: Dan Lynch (@pyramation)

- Add ViewportRenderer class with ansi-diff for minimal flicker rendering
- Add AICodeUI class for claude-code style terminal interface
- Implement two-channel output model (committed scrollback + live viewport)
- Add line editor with cursor movement and character input
- Add streaming text support for AI-style responses
- Add demo-ai-code.ts showcasing the new interface
- Add pnpm dev:ai-code script

This implements the terminal UI spec for building interactive coding tools
with scrollback preservation and diff-based updates.
@devin-ai-integration
Copy link

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

- Remove ansi-diff usage in favor of simple cursor positioning
- Fix viewport to reserve space on first render
- Move cursor back to viewport start before each redraw
- Clear and redraw each line for reliable updates
- Remove commitMessage calls that were causing duplicate output

The viewport now uses a simple approach:
1. On first render, reserve space by printing empty lines
2. On subsequent renders, move cursor up and redraw in-place
3. Each line is cleared before writing new content
@devin-ai-integration devin-ai-integration bot changed the title feat(inquirerer): add AICodeUI with diff-based viewport rendering feat(inquirerer): add AICodeUI with viewport rendering Dec 27, 2025
…support

- Add comprehensive KEY_CODES for readline-style editing (Ctrl+A/E, Alt+B/F, Ctrl+W/K/U, Home/End)
- Implement prompt history navigation (UP/DOWN arrows)
- Support multiline input (Shift+Enter for newline, Enter to submit)
- Move message scrolling to PageUp/PageDown
- Add extensible keybinding system with addBinding/removeBinding methods
- Update LineEditorState to support multiple lines
- Add kill ring for Ctrl+K/U operations
- Show history position in status bar
@devin-ai-integration devin-ai-integration bot changed the title feat(inquirerer): add AICodeUI with viewport rendering feat(inquirerer): add AICodeUI with readline-style keybindings Dec 27, 2025
- Replace block cursor character with inverse video on current char
- This fixes the jittery cursor that shifted text due to width differences
- Add CTRL_J as fallback for newline insertion since Shift+Enter
  doesn't work in most terminals without special configuration
- Update help text to show Ctrl+J instead of Shift+Enter
…rsation markers

- Add welcome box with rounded corners and two-column layout
- Add conversation markers: > for user, ⏺ for assistant
- Add animated spinner for streaming indicator
- Use full-width separators
- Add ↵ send hint in input area
- Fix UP/DOWN arrows to navigate multiline input with preferredCol tracking
- Add string-width dependency for proper display width calculations
@devin-ai-integration devin-ai-integration bot changed the title feat(inquirerer): add AICodeUI with readline-style keybindings feat(inquirerer): add Claude Code-style terminal UI with welcome box Dec 27, 2025
Skip messages with isStreaming=true in the main message loop since
they are already rendered separately in the streaming section.
- Remove trailing newline after render to prevent scroll when at bottom row
- Add truncateToWidth() to prevent soft-wrap which desyncs cursor position
- Lines are now truncated to terminal width before rendering
On first render, cursor is at bottom after printing newlines, so move up viewportHeight.
On subsequent renders, cursor is on last viewport row (no trailing newline), so move up viewportHeight-1.
This prevents the 'filling screen upward' bug where each render landed one row higher.
When input has too many lines, limit visible lines to prevent overflow.
Shows scroll indicators when there are hidden lines above/below.
Keeps cursor line visible by centering the view around it.
- Use fixed max of 5 visible input lines for stable layout
- Layout calculation and rendering now use the same max height
- Show 'ln X/Y' indicator when multiline instead of scroll indicators
- Keeps cursor visible with context when scrolling through input
- Removes extra indicator rows that were stealing layout space
- Remove 5-line limit on input area
- Input area grows as user adds newlines, conversation area shrinks
- Simpler approach matching Claude Code's behavior
- Input area can grow up to (viewportHeight - chrome - 1) lines
- Conversation area dynamically shrinks as input grows
- Input lines are windowed when they exceed available space
- Shows 'ln X/Y' indicator when input is scrolling
- Keeps cursor line visible with context when scrolling
- Total rendered lines never exceed viewport height
- Add bottom-anchored clamping to guarantee exactly viewportHeight lines
- Fix renderConversation to reserve space for scroll indicator
- Clamp availableContentLines to prevent negative values
- This ensures the UI never goes below the terminal
- Move aicode.ts and viewport.ts from src/ui/ to dev/ai/
- These files are now demo-only and not bundled with the package
- Update imports in demo-ai-code.ts
- Remove exports from src/ui/index.ts
- Keypress additions remain in src/ as they're useful for other components
string-width is only used by the AI code demo in dev/ai/, which is not
bundled with the published package. Moving it to devDependencies ensures
consumers don't install it unnecessarily.
These dependencies were not imported anywhere in src/ or dev/ and were
adding unnecessary install footprint for consumers.
@pyramation pyramation merged commit 882d5e9 into main Dec 28, 2025
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants