- Add debugging steps to diagnose why coverage shows 0%
- Implement multiple fallback methods for coverage extraction:
1. Standard xccov with --json flag
2. Text parsing fallback without --json
3. Test execution verification (0.1% if tests ran but coverage failed)
- Fix command order: put --json flag after xcresult path
- Add detailed logging to understand coverage extraction failures
- Check xcresult contents with xcresulttool for coverage data
This should resolve the "Failed to load coverage report" errors
and provide better visibility into what's happening in CI.
- Keep parallel execution for read-only checks (format:check, lint, typecheck)
- Make check:fix run sequentially to prevent file write conflicts
- Add documentation explaining why sequential execution is needed
- Based on best practices: lint-staged and JavaScript community recommendations
- Add tests for formatPathForDisplay covering all platforms
- Create parallel code quality check script (pnpm run check)
- Add auto-fix command for format and lint issues (pnpm run check:fix)
- Document the improved workflow in DEVELOPMENT.md
- Update CLAUDE.md with the new commands
- Remove all server-side path formatting logic
- Implement simple regex-based client-side formatting
- Support macOS, Linux, Windows, and root user paths
- Simpler implementation with no API changes needed
- Better separation of concerns (UI formatting in UI layer)
- Delete formatPathForDisplay function from path-utils.ts
- Update all components to use displayWorkingDir from server
- Clean up imports in affected components
- Add refactoring philosophy note to CLAUDE.md
- Replace hardcoded home directory with dynamic detection using os.homedir()
- Add server-side path formatting using existing abbreviatePath utility
- Add displayWorkingDir field to Session interface
- Fix mobile header overflow with proper width constraints
- Update clickable-path component to accept pre-formatted display paths
This fixes both the regression where ~ substitution was broken and the
mobile header pushing content off-screen when session paths are long.
Fixes#96
* 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>