* Add keyboard shortcut highlighter to terminal
- Create keyboard-shortcut-highlighter.ts with comprehensive pattern matching
- Integrate highlighter into terminal component alongside URL highlighting
- Support clickable shortcuts like "Ctrl+R", "Ctrl+A", "esc to interrupt"
- Style shortcuts with greyish color and dotted underlines (not blue links)
- Send actual key sequences when shortcuts are clicked
- Handle overlapping matches and avoid double-processing
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix keyboard shortcut input handling - add missing event listener
The keyboard shortcut highlighter was dispatching 'terminal-input' events
but the session-view component wasn't listening for them. Added:
- @terminal-input event listener on vibe-terminal component
- handleTerminalInput method that forwards to inputManager.sendInputText()
Now clicked shortcuts like 'Ctrl+R' properly send input to the terminal.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add Claude Code interactive prompt support to keyboard shortcut highlighter
Make numbered options in Claude Code prompts clickable:
- Pattern: '❯ 1. Yes' or ' 2. Yes, and don't ask again'
- Clicking sends the number (1, 2, 3, etc.) to terminal
- Handles both selected (❯) and unselected options
- Uses multiline regex matching for line-start patterns
Now users can click numbered options instead of typing numbers.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix Claude Code prompt patterns to handle indented options
Previous patterns required line-start anchors which failed for indented
options within bordered terminal output. Updated patterns:
- Remove restrictive line-start anchors (^)
- Add whitespace-flexible patterns for indented options
- Support both cursor-selected (❯) and plain numbered options
- Handle 'Yes, proceed' and 'No, exit' style options
Now correctly matches:
'❯ 1. Yes, proceed' and ' 2. No, exit' patterns.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Simplify Claude Code prompt patterns to be fully generic
Replace keyword-specific patterns with generic numbered option matching:
- ❯ 1. (cursor-selected options)
- 1. xxxxx (any numbered option with text)
Now matches any numbered list item regardless of content:
'1. Yes, proceed', '2. No, exit', '3. Maybe later', etc.
Much cleaner and more flexible than keyword-based matching.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix Claude Code prompt patterns to highlight full option lines
Changed from matching only first word to matching entire lines:
- /❯\s*(\d+)\.\s+.*/ - highlights complete cursor-selected option
- /(\d+)\.\s+.*/ - highlights complete numbered option
Now '1. Yes, proceed' and '2. No, exit' are fully underlined
instead of just '1. Yes' and '2. No'.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Implement WriteQueue to serialize all async write operations and handle backpressure:
- Add shared WriteQueue utility class for serializing async operations
- Move write queue inside AsciinemaWriter to handle all write methods
- Add backpressure handling using stream 'drain' events
- Ensure all AsciinemaWriter methods (writeHeader, writeRawJson) use queue
- Add drain() method to wait for pending writes on close
- Store stdout queue reference in PtySession for cleanup on process exit
This prevents race conditions where concurrent fs.fsync calls could interleave,
causing out-of-order disk flushes and potential data corruption.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added comprehensive IME composition support to prevent duplication of Japanese, Chinese, and Korean text input on mobile devices.
Changes:
- DirectKeyboardManager: Added composition event handlers to wait for final text
- MobileInputOverlay: Added composition state tracking to prevent intermediate updates
- Fixed null safety issues and unused parameter warnings
- Comprehensive documentation explaining IME implementation
Bug Fixed:
Previously, intermediate composition characters were sent to terminal during Japanese typing, causing duplicated text. Now properly waits for composition completion before sending final text to terminal.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
* Add Shift+Tab key to mobile QuickKeyboard per PR #105 feedback
Implements Peter's suggestion to add Shift+Tab key to mobile quick keyboard
for enhanced Claude Code planning mode support on mobile devices.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix Monaco Editor keyboard input cancellation
Enhanced isKeyboardShortcut detection to properly handle Monaco Editor
elements, preventing keyboard event interference while maintaining
terminal functionality.
- Added contentEditable detection
- Added .monaco-editor container detection
- Added data-keybinding-context detection
- Added .editor-container detection
This resolves the 'Canceled: Canceled' errors when typing in Monaco Editor
while preserving Shift+Tab functionality for Claude Code planning mode.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Fixed the 'command not found' error for shell aliases like claude command.
Root Cause:
Previously, commands were executed as:
/bin/zsh -c 'source ~/.zshrc 2>/dev/null || true; claude'
Shell alias expansion happens at parse time, before the source command runs,
so aliases defined in .zshrc were not available during command parsing.
Solution:
Use interactive mode with login shell flags:
/bin/zsh -i -l -c 'claude'
The -i flag enables interactive mode (loads aliases)
The -l flag makes it a login shell (sources RC files)
This ensures aliases are properly loaded and expanded before command execution.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
* Prevent recursive VibeTunnel sessions (GitHub #95)
Added detection and prevention of nested VibeTunnel sessions to avoid
recursive 'vt' command execution.
Changes:
- Set INSIDE_VIBETUNNEL and VIBETUNNEL_SESSION environment variables when creating PTY sessions
- Added check in vt script to detect if already inside a VibeTunnel session
- Shows helpful error message when recursive session is attempted
This prevents the confusing behavior where users could run 'vt' inside a
VibeTunnel session, creating nested terminal instances. Now users get a
clear error message explaining they're already in a VibeTunnel session.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Improve recursive session prevention based on PR feedback
- Consolidate to single environment variable VIBETUNNEL_SESSION_ID
- Add session ID for debugging purposes as requested
- Show session ID in error message for better user feedback
- Remove redundant environment variables (INSIDE_VIBETUNNEL, VIBETUNNEL_SESSION)
This addresses feedback from PR #104 to use a single, more informative
environment variable that serves both purposes: preventing recursion
and providing debugging information.
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add Shift+Tab support for Claude Code planning mode (GitHub #100)
Added proper Shift+Tab key sequence handling to enable Claude Code mode switching.
Changes:
- Added 'shift_tab' to SpecialKey type definition
- Updated input-manager.ts to detect Shift+Tab combination (e.shiftKey)
- Updated direct-keyboard-manager.ts for mobile Shift+Tab support
- Added shift_tab mapping to PTY manager (sends \x1b[Z escape sequence)
This allows users to press Shift+Tab in VibeTunnel to switch between Claude Code
modes (autoaccept, planning, regular) as expected.
Technical Details:
- Shift+Tab sends the standard terminal escape sequence \x1b[Z (CSI Z)
- Both desktop and mobile input handlers now support the key combination
- Maintains backward compatibility with regular Tab functionality
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix Shift+Tab not being sent as special key
Added 'shift_tab' to the special keys list in input-manager.ts so it gets
sent as {"key": "shift_tab"} instead of {"text": "shift_tab"}.
This was the missing piece - the frontend was correctly detecting Shift+Tab
but then sending it as text instead of a special key, so the server couldn't
map it to the \x1b[Z escape sequence.
Now Shift+Tab will properly send {"key": "shift_tab"} in the API request.
* Fix failing CI test in session-list.test.ts
Updated test expectation to check for 'compactMode' instead of
non-existent 'showCreateModal' property. This was a stale test
that was unrelated to the Shift+Tab changes but was blocking CI.
All tests now pass.
---------
Co-authored-by: Claude <noreply@anthropic.com>
- Add backpressure handling for process.stdout.write() in PTY output forwarding
- Pause PTY output when stdout buffer is full
- Resume on drain event to prevent CPU spinning
- Add backpressure logging for socket writes in sendInput()
- Add backpressure logging for file stream writes in AsciinemaWriter
- Remove unused bell detection code (was already commented out)
These changes prevent the hanging issue when pasting large amounts of text
by properly handling stream backpressure instead of blindly writing data.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add claude-patch.ts to enable debugging Claude Code with Node.js --inspect flag
- Temporarily disable bell character handling in pty-manager.ts due to VS Code terminal hanging issue
- Fix TypeScript linter errors across test files (replace any types with proper interfaces)
The bell character handling was causing VS Code terminals to hang when pasting certain content.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>