- Updated npm.md with release history for beta.12.2
- Successfully published to npm with beta tag
- Verified authenticate-pam as optional dependency
- All installation tests passed
- Add vitest integration test for vt command functionality
- Add shell script test for build-time validation
- Include vt tests in main check script to run in CI
- Tests cover: syntax validation, help functionality, error handling, npm package config
- Add pnpm run test:vt script for easy testing
- Exclude vt symlink from package.json bin section to avoid conflicts with other vt installations
Co-authored-by: hewigovens <360470+hewigovens@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
- Modified postinstall script to extract authenticate-pam prebuilds when npm skips optional deps
- Updated authenticate-pam-loader to load from optional-modules directory
- Prepared beta.12 release with all fixes consolidated
- Moved Docker test script to scripts folder
- Updated documentation in npm.md
This commit addresses the Ubuntu installation issues reported in issue 380:
**PAM Module Fix:** - Fix .npmignore to include authenticate-pam module in npm package - Previously node_modules/ exclusion prevented
authenticate-pam from being packaged - Resolves \"PAM Authentication Warning: The native authenticate-pam module isn't found\"
**npm_config_prefix Conflict Detection:** - Add detection for npm_config_prefix conflicts with NVM in postinstall script - Warn users when
npm_config_prefix overrides NVM's per-version configuration - Provide clear instructions to resolve the conflict - Document
troubleshooting steps in docs/npm.md
- Use web/README.md as single source of truth for npm package
- Remove generated README from build-npm.js, now copies from web/
- Fix incorrect --auth parameter (should be --no-auth)
- Add complete CLI options based on actual code parsing
- Remove non-existent --username/--password CLI flags (env vars only)
- Add missing options: --vapid-email, --repository-base-path, etc.
- Clarify installation differences between npm and source
- Add troubleshooting section for npm installation issues
- Keep port as 4020 (our standard port)
Closes#381
The vt script now operates silently by default, removing the
'# Using VibeTunnel from Mac app bundle' debug message that was
printed to stderr. Error messages are still shown when appropriate.
Closes#383
The file browser was rendering behind the session create form modal because its z-index (200) was lower than the modal backdrop (1000). Increased FILE_BROWSER z-index to 1100 to ensure proper layering.
Also added debug logging to handleBrowse method for better troubleshooting.
Update all project dependencies to their latest versions while keeping
Tailwind CSS at v3.4.17 to avoid breaking changes.
Notable updates:
- Express: 4.19.2 → 5.1.0 (major version upgrade)
- Chalk: 4.1.2 → 5.4.1 (major version upgrade to ESM)
- CodeMirror packages: Updated to latest v6 versions
- TypeScript types: Updated to latest versions
- Development tools: Biome, Playwright, Puppeteer, etc.
All code quality checks pass successfully after the updates.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Extract improvements from PR #318:
1. Set default user ID in no-auth mode for auth middleware
- Ensures consistent behavior when authentication is disabled
- Prevents potential issues with undefined user IDs
2. Convert to type-only imports in push notification service
- Use TypeScript type imports for better tree shaking
- Remove .js extensions from imports for consistency
- Minor logging improvement for service worker registration
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Enable arrow key navigation (up/down/left/right) through sessions
- Press Enter to open selected session
- Add visual feedback for keyboard-selected sessions
- Fix global event listener conflict by scoping to component
- Make session-list focusable with proper focus indicators
- Pass selected state to session-card for visual highlighting
Adopts PR #322 with improvements based on review feedback
- Remove non-null assertion in favor of proper null check
- Add z-index comments for clarity in modal overlays
- Remove unused Z_INDEX imports after switching to comments
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add stopPropagation to Browse button click handler in session-create-form
- Add debug logging to track state changes
- Match the pattern used in session-header for consistency
- Swap file picker and settings buttons in session header (settings now at the end)
- Disable all button transitions in session view with body.in-session-view
- Disable modal backdrop fade-in animation (0.3s) in session view
- Fix file browser briefly showing then going dark by preventing event bubbling
- Add stopPropagation to file browser button click to prevent duplicate modals
The session detail page should now have zero animations when toggling sidebar
or opening modals.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove animate-fade-in class from compact mode session list items
- Prevent sessions-showing/hiding animation classes when in session detail view
- Disable View Transitions API for navigating back from session detail view
- Add body.in-session-view class to disable all animations in session view
- Remove transition-all duration-200 from compact session list items
- Disable grid transitions when in session view
This eliminates all staggered animations and transitions that were causing
the perceived 1-2 second delay when toggling the sidebar in session detail view.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Make inline-edit pencil always visible on touch devices with CSS media query
- Remove terminal resize animation (transition: all 0.3s ease-out)
- Remove magic wand AI button that was confusing users
- Reorganize touch device layout: close button left of time
- Disable View Transitions API for session navigation
- Add CSS overrides to disable all button transitions in session view
- Fix TypeScript errors by adding missing handleDeleteSession method
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add check for session detail view in handleCreateSession()
- Add check for session detail view in handleCreateModalClose()
- Modal now appears/disappears instantly in session detail view
- Animation preserved in grid view where it works properly
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove duplicate screen share button from sidebar
- Remove file browser button from sidebar
- Remove file picker/upload button from session header
- Move settings/notification icon from sidebar to session header (next to file browser)
- Disable sidebar slide animations to prevent terminal resize issues
- Simplify sidebar to only show Create Session button and User menu
- Settings button is now in session detail view for better context
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove tablet-specific renderTabletLayout() method
- Remove deviceType property from terminal-quick-keys component
- Remove tablet-specific CSS classes (.tablet-layout, .compact)
- Simplify code to use the same 3-row keyboard for all mobile devices
- Provides consistent experience across iPhone and iPad
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace user agent detection with capability-based detection
- Support any touch device (iPad, Android, Surface, etc.)
- Add smart detection for hybrid devices (touch + trackpad)
- Add user preference support (auto/always/never)
- Add keyboard mode toggle button in mobile controls
- Fix landscape mode detection on all touch devices
- Use hardware capabilities instead of brittle UA strings
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Pass isMobile instead of isPhone to setupMobileFeatures and setupEventListeners
- Tablets need VirtualKeyboard API, Visual Viewport API, and touch event listeners
- Only the keyboard layout should differ between phones and tablets, not core mobile features
- Detect device type (phone vs tablet) based on screen size
- Show custom keyboard on iPads with optimized compact layout
- Portrait mode: 2 rows with essential terminal keys
- Landscape mode: Single row with most important keys
- Properly handle device rotation and window resizing
- Add TypeScript declarations for window.__deviceType
Fixes#223
The magic wand feature now uses emphatic language to ensure AI assistants
use the 'vt title' command instead of injecting terminal escape sequences.
This prevents Claude from being "too smart" and bypassing our title filtering.
Fixes#248
- Ensure bash, zsh, and fish spawn as login shells to read config files
- Add -i and -l flags for bash/zsh, --interactive and --login for fish
- Avoid duplicate flags if already present
- Add user feedback when starting shells in login mode
Fixes#251
fix: prevent file browser flashing and reduce log verbosity
- Split visibility and session change handling to avoid redundant directory loads
- Only reload directory when component becomes visible or session changes while visible
- Change directory browse success log from info to debug level to reduce noise
- Fixes issue where file browser would flash/reload unnecessarily on prop changes
```
- Add focus management check in lifecycle keyboard handler
- Skip keyboard capture when overlays/modals are displayed
- Add debug logging for session name change events
- Prevents keyboard conflicts with form inputs in overlays
- Add titleInjectionInProgress flag to prevent concurrent injections
- Update lastWriteTimestamp immediately before enqueueing to prevent quiet period violations
- Clear pendingTitleToInject only after successful write completion
- Compare titles before clearing to avoid losing newer updates
- Stop injection timer only when no pending titles remain
- Use try-finally to ensure in-progress flag is always cleared
This prevents both lost title updates and quiet period violations that could
occur when titles were cleared prematurely or timestamps updated too late.
- Modified initLogger() to return early if already initialized
- Removed explicit false parameter in server.ts to preserve debug mode from CLI
- Fixes test failure where log file was being deleted after first write
- Change periodic activity update interval from 500ms to 1000ms
- Ensure all title updates go through debouncer (including session name changes)
- Prevents excessive terminal updates while maintaining responsiveness
- Fix menu bar button highlighting using state instead of highlight()
- Extract process name from command path for cleaner display
- Show session name next to command with dash separator
- Fix corner radius on new session dialog
- Make Create button darker green for better visibility
- Update editing to properly handle session names
- Implement modern color scheme with cyan/teal primary colors
- Redesign sidebar with card-based sessions and enhanced status indicators
- Create unified header design with gradient backgrounds
- Add JetBrains Mono font and improve typography throughout
- Implement smooth micro-interactions and animations
- Enhance terminal area with better focus states and loading overlays
- Update all buttons and inputs with consistent hover/focus effects
- Remove stdin handler cleanup that was contradicting the comment
- Remove unused stdinHandler and stdinDataListener from PtySession interface
- Stdin is handled via IPC socket, not process.stdin listeners
- Add stdin cleanup handlers for process.stdin listeners
- Implement event listener tracking to prevent memory leaks
- Add lazy watcher initialization for session.json monitoring
- Add explicit isExternalTerminal flag for better terminal detection
- Optimize activity file writing to only write on state changes
- Track last written activity state to avoid unnecessary disk I/O
- Fix timer management in setupSessionJsonWatcher to properly assign timer before setTimeout
- Improve IPC socket error handling to throw error instead of silently returning
- Socket path length validation now fails fast with clear error message
- Display activity status (e.g., 'Browsing', 'Considering') below each session
- Show status inline with working directory path, separated by dot
- Match visual style from web frontend with orange status text
- Add compact path display with ~ for home directory
- Remove unused imports to clean up test files
- Use shorter session IDs to avoid path length issues
- Adjust timing in tests for better reliability
- Improve test descriptions and assertions
- Validate session ID format to prevent injection attacks
- Sanitize title input: limit to 256 chars, filter control characters
- Prevent potential security issues with malformed session titles
- Placed file browser button between notification and create session buttons
- Matches the layout of the full header for better consistency
- Maintains same styling and functionality as main page
- Integrated SafePTYWriter and PTYStreamAnalyzer from PR #171 to prevent terminal corruption
- Fixed stdin listener duplication bug - stdin is now handled via IPC socket only
- Fixed IPC socket handler to properly handle both stdin data and control commands using framed message protocol
- Updated socket paths from 'i.sock' to unified 'ipc.sock'
- Added comprehensive tests for SafePTYWriter and PTYStreamAnalyzer
- Removed global process.stdin listeners to prevent duplication across sessions
- Remove controlPipePath and controlWatcher from types
- Remove setupControlPipe method entirely
- Update sendControlMessage to use socket-based IPC
- Remove control pipe cleanup code
- Keep stdin forwarding memory leak fix
The control pipe system was replaced by socket-based IPC in main.
This commit removes the old control pipe code that was accidentally
reintroduced during the rebase.
- Fix memory leak where stdin listeners were never removed
- Store stdin listener reference for proper cleanup
- Add missing controlPipePath property to session types
- Update session manager to include controlPipePath in paths
- Each session now properly tracks and cleans up its stdin listener
This fixes both the CI failures and the reported bug where input
was duplicated across all forwardToStdout sessions.
- Update session.sessionJsonDebounceTimer when creating new timers
- Clear timer reference after callback execution
- Remove incorrect initial null assignment
- Fixes memory leak where timers continued after session cleanup
The bug occurred because the timer ID was only stored in a local variable,
preventing proper cleanup during session termination.
- Add --update-title flag to fwd.ts for cleaner session title updates
- Replace complex bash/jq/python/sed logic with single fwd.ts call
- Leverage existing SessionManager for type-safe JSON handling
- Improve error handling and messaging
- Reorganize vt script to locate app path before processing commands
This eliminates the fragile bash JSON manipulation in favor of a
robust TypeScript implementation that reuses existing infrastructure.
- Fix command injection vulnerability by using jq --arg for safe parameter passing
- Add Python fallback for systems without jq for safe JSON manipulation
- Improve sed fallback with proper escaping (last resort)
- Add debouncing (100ms) to file watcher to prevent rapid updates
- Add error handling for file watcher failures
- Clean up debounce timer on session cleanup
- Fix issue where lastSessionName wasn't properly tracked
Security fix prevents arbitrary command execution through malicious title strings.
Debouncing prevents performance issues from rapid file changes.
- Add error handling for 'vt title' when used outside a session
- Create unit tests for session.json watcher in PtyManager
- Add integration tests for vt title command with edge cases
- Test all 4 title modes (none, filter, static, dynamic)
- Test special characters, concurrent updates, and error scenarios
- Ensure proper cleanup of file watchers on session exit
- Add 'vt title' command that updates session names from within terminal sessions
- Implement file watcher in PtyManager to detect session.json changes
- Integrate title updates with all 4 title modes (none, filter, static, dynamic)
- Updates terminal titles in real-time when session name changes
- Works by directly editing session.json using the VIBETUNNEL_SESSION_ID env var
This allows users to easily set descriptive names for their terminal sessions,
making it easier to manage multiple VibeTunnel windows.
* Implement ultra-low-latency WebSocket input system
This change eliminates input lag on slow networks by replacing HTTP requests
with a fire-and-forget WebSocket system for terminal input transmission.
Key optimizations:
- Raw text transmission (no JSON overhead): 1 byte vs 87+ bytes per keystroke
- Fire-and-forget input (no ACK blocking): eliminates 20-50ms roundtrip latency
- Single persistent connection per session: zero connection overhead
- Direct PTY write path: fastest possible server processing
- Graceful HTTP fallback: maintains full backward compatibility
Performance improvements:
- 99% bandwidth reduction per keystroke
- 90% latency reduction on slow networks
- Zero blocking waits for rapid typing
- Eliminates HTTP/1.1 connection overhead
Files changed:
- Add: src/client/services/websocket-input-client.ts (WebSocket client)
- Add: src/server/routes/websocket-input.ts (WebSocket input handler)
- Modify: src/client/components/session-view/input-manager.ts (WebSocket integration)
- Modify: src/server/server.ts (WebSocket routing for /ws/input endpoint)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add socket_input URL parameter feature flag
Adds ?socket_input=true/false URL parameter to control WebSocket input behavior:
- socket_input=true (default): Enable WebSocket input with HTTP fallback
- socket_input=false: Force HTTP-only input mode (disable WebSocket)
This feature flag enables:
- A/B testing between WebSocket and HTTP input performance
- Debugging WebSocket connection issues
- Gradual rollout control
- Easy fallback mechanism for production issues
Examples:
- http://localhost:4020/?socket_input=true&session=abc123 (WebSocket enabled)
- http://localhost:4020/?socket_input=false&session=abc123 (HTTP only)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix WebSocket input key mapping for special keys
The server was receiving key names like "enter" and writing them literally
as text instead of interpreting them as actual key presses.
Added proper key mapping:
- "enter" → '\r' (carriage return)
- "escape" → '\x1b' (ESC key)
- "backspace" → '\x7f' (DEL)
- "tab" → '\t' (TAB)
- "arrow_up" → '\x1b[A' (VT100 up arrow)
- "arrow_down" → '\x1b[B' (VT100 down arrow)
- "arrow_left"/"arrow_right" → '\x1b[D'/'\x1b[C' (VT100 arrows)
- Function keys F1-F12 → proper VT100 sequences
- Regular text → sent as-is
Now "enter" actually triggers ENTER key instead of typing "enter" text.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Reuse existing key mapping logic instead of duplicating
Instead of duplicating the key mapping logic (enter → \r, etc.), now properly
reuse the existing PtyManager.sendInput() method which already handles:
- Key mapping via convertSpecialKey() method
- SessionInput type validation
- Special key vs regular text determination
- Error handling and session management
This ensures consistency between HTTP /input and WebSocket /ws/input endpoints
and avoids maintaining duplicate key mapping tables.
Benefits:
- Single source of truth for key mappings
- Consistent behavior across input methods
- Proper type safety with SessionInput/SpecialKey types
- Reuses existing error handling and validation
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix special key detection in pasted text using null-byte markers
Problem: Pasting text like "i am entering the world" would incorrectly
interpret "enter" as the ENTER key instead of literal text.
Solution: Use null-byte markers to distinguish special keys from literal text:
- Special keys: "\x00enter\x00" → ENTER key press
- Regular text: "enter" → literal text "enter"
- Pasted text: "i am entering the world" → literal text
This maintains the raw text protocol while solving the ambiguity:
- Single keystroke "enter" → "\x00enter\x00" → ENTER key
- Pasted word "enter" → "enter" → literal text "enter"
- Multi-word paste → always literal text
Benefits:
- Preserves ultra-minimal bandwidth (just 2 null bytes overhead)
- Maintains raw text protocol (no JSON)
- Solves paste ambiguity correctly
- Null bytes rarely appear in normal text input
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix paste text ambiguity and control sequence handling
- Modified sendInputText to always treat pasted content as literal text
- Added sendControlSequence method for control characters like Ctrl+R
- Updated direct keyboard manager to use sendControlSequence for control chars
- This ensures pasted text containing words like "enter", "backspace" is sent as literal text
- Control sequences like Ctrl+R (\x12) are properly transmitted via WebSocket with null-byte escaping
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add debug logging for WebSocket input transmission
- Added detailed logging on client side to show what's being sent
- Added server side logging to show what's being received
- This will help debug the enter key transmission issue
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add comprehensive input logging to track key processing
- Added logging in WebSocket handler to show parsed input
- Added logging in PtyManager to show key conversion and output
- This will show the complete flow: received key -> parsed input -> converted output
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add DEBUG environment variable for enabling debug logging
- Added DEBUG=true environment variable option alongside --debug flag
- Makes it easier to enable debug logging during development
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix WebSocket input handling for HQ mode and mobile keyboards
- Add WebSocket proxy support for remote sessions in HQ mode
- Fix mobile keyboard special key handling to use sendInput() instead of sendInputText()
- Make InputManager.sendInput() public for use by mobile components
- Update DirectKeyboardManager to correctly send special keys from custom keyboard
- Handle WebSocket data type conversion for native WebSocket API compatibility
This ensures special keys are properly wrapped with null bytes (\x00) when sent
via WebSocket, and enables low-latency input for remote sessions in HQ mode.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: eliminate code duplication in input-manager and fix TypeScript typing
- Extract common WebSocket/HTTP fallback logic into sendInputInternal()
- Reduce ~155 lines of duplicate code across sendInput, sendInputText, and sendControlSequence methods
- Add proper WebSocketRequest interface to replace any type usage
- Fix linting issues in server.ts WebSocket handling
* up
* Add comprehensive tests for WebSocket input handler
- Test special key handling with null-byte wrapped keys (\x00enter\x00)
- Test text containing key names ('i enter the world') treated as literal text
- Test HQ mode remote session proxying vs local PTY handling
- Test edge cases: empty messages, malformed keys, binary data, Unicode
- Test error handling and connection lifecycle
- Remove duplicate special key validation logic
- Delegate key conversion to ptyManager for consistency
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix TypeScript linting issues in WebSocket input handler tests
- Replace all 'any' types with proper type definitions
- Add MockEventListener type for test event handlers
- Use 'unknown' instead of 'any' for type assertions
- Remove unused SessionInput import
- Fix formatting issues per Biome requirements
All 20 WebSocket input handler tests now pass with proper TypeScript types.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>