- Document all frontend components with JSDoc headers describing their purpose and events
- Add @fires and @listens tags for all component events with detailed parameter descriptions
- Update spec.md with complete Component Event Architecture section
- Add shared terminal-text-formatter.ts for consistent text formatting between client/server
- Implement event-driven activity detection replacing polling-based approach
- Add content-changed event to vibe-terminal-buffer for activity monitoring
- Remove ESC prompt detection in favor of general activity detection
- Add plain text endpoint with optional style formatting (/api/sessions/:id/text?styles)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Only show loading state on initial load, not on periodic refreshes
- Prevents "Loading sessions..." from briefly appearing every 3 seconds
- Help text now remains stable after first load
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Move spawn_terminal logic after remote forwarding to properly handle remotes
- Add spawn_terminal parameter to remote forwarding requests
- Handle ECONNREFUSED when socket exists but no listener is active
- Gracefully fall back to normal PTY spawn in all failure cases
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update spec.md build system section with Node.js SEA details
- Update README.md production build section to clarify SEA executable
- Both files now correctly reflect the transition from Bun to Node.js
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove all Jest-related dependencies (using Vitest)
- Remove pre-commit hooks (husky, lint-staged) and related files
- Consolidate test configuration into single vitest.config.ts
- Fix build-native.js to use correct entry point (src/cli.ts)
- Add bun.lock to .gitignore (generated during native build)
- Update README.md with simplified, accurate documentation
- Make npm run build include native executable build
- Remove unused type declarations and test setup files
The build system is now minimal, clean, and consistent.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Consolidate complex npm scripts into minimal, clear commands
- Remove confusing bundle:*, watch:*, ensure:dirs scripts
- Add format:check script for CI compatibility
- Add @types/mime-types dev dependency to fix TypeScript errors
- Scripts are now cross-platform using Node.js instead of shell commands
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rename index.ts to cli.ts as single entry point
- Merge app.ts and shutdown-state.ts into server.ts
- Update all imports and references to use new structure
- Update e2e tests and dev script to spawn via cli.ts
- Remove execution code from server.ts (only cli.ts executes)
- Clean up tsconfig.client.json exclude path
This creates a cleaner separation where cli.ts is the only entry
point that decides whether to run server or forward mode.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
The CSS file was moved but the watch:css script wasn't updated, causing npm run dev to fail.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add global shutdown state tracking via shutdown-state.ts module
- Update refresh-sessions endpoint to return 503 during shutdown
- Skip HQ notifications in control-dir-watcher during shutdown
- Disable remote health checks during server shutdown
- Suppress expected connection errors when servers are shutting down
This prevents the flood of "Failed to refresh sessions" and "Failed to
notify HQ" errors that were appearing in the HQ e2e test logs when
servers were shutting down.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed cursor rendering with inverse video by applying cursor styling
after inverse processing to ensure it takes precedence
- Added missing overline attribute support (isOverline() → .overline class)
- Improved consistency by applying all persistent styles after inverse
video processing, which clears and rebuilds the style string
This fixes multiple edge cases in terminal rendering including cursor
visibility in inverted text and proper text decoration support.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed the terminal renderer to properly handle inverse video attributes
when no explicit colors are set. Nano's header bar uses SGR 7 (inverse)
without explicit foreground/background colors, which now correctly swaps
the default terminal colors (#e4e4e4 foreground, #0a0a0a background).
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix hanging TestNewStdinWatcher by not calling Stop() without Start()
- Fix TestSession_Signal and TestSession_KillWithSignal by adding PID values
- Fix isProcessRunning to use syscall.Signal(0) instead of os.Signal(nil)
- Update websocket test to expect new 'Unknown WebSocket endpoint' error message
- Add timeout handling to websocket integration test
- Enhanced /buffers WebSocket endpoint to aggregate updates from all remotes
- Added remote WebSocket connection management with proper Bearer auth
- Implemented connection pooling and automatic reconnection
- Forward binary buffer messages transparently from remotes to clients
- Track subscriptions per remote and handle cleanup properly
- Support both local and remote sessions through unified interface
This enables real-time terminal viewing across distributed VibeTunnel instances.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Complete architectural overview of VibeTunnel server
- Detailed protocol specifications for all components
- Binary buffer encoding format documentation
- HQ mode distributed architecture details
- API endpoint reference with examples
- WebSocket protocol specifications
- File system structure and session storage format
- Implementation notes for cross-language compatibility
This specification enables implementing VibeTunnel servers in any language
while maintaining full compatibility with the protocol and architecture.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove registration retry from HQClient, let caller handle retries
- Make HQClient destroy method async and await unregister
- Remove session ID namespacing - UUIDs are unique enough
- Add /api/health endpoint for cheaper health checks
- Remove unnecessary RemoteServer.status field
- Track sessions by remote using sessionIds Set
- Fix remote session creation to use remote's token (not HQ's auth)
- Update session proxy to lookup remote by session ID
- Make cleanup-exited work across all remotes
- Remove tty_fwd_path code - always use node-pty
- Fix duplicate HQ endpoints
- Improve health check to try /api/health first, fall back to /api/sessions
- Remove offline remotes automatically on failed health check
BREAKING CHANGES:
- HQClient.destroy() is now async
- RemoteServer no longer has status field
- Session IDs are no longer namespaced with remoteId prefix
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add mandatory --name parameter when using --hq-url
- Ensure remote server names are unique across the HQ
- Return 409 Conflict when duplicate name is registered
- Track remotes by both ID and name in RemoteRegistry
- Add /api/remotes endpoints for HQ mode
- Improve error messages for registration failures
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add VIBETUNNEL_USERNAME/PASSWORD env vars and --username/--password CLI args
- Separate local auth from HQ registration auth (--hq-username/--hq-password)
- Validate that both username and password are provided or neither
- Update authentication to use configured username instead of hardcoded 'admin'
- Fix type errors and lint issues
BREAKING CHANGE: Authentication now requires both username and password to be specified together
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remote servers now accept both Basic Auth (for clients) and Bearer token (for HQ)
- Basic Auth now requires username 'admin' (not any username)
- Remote sends its token to HQ during registration for HQ to use
- HQ uses Bearer token when calling remote APIs (not Basic Auth)
- Remote uses HQ's Basic Auth when registering/unregistering with HQ
- WebSocket connections also support both auth methods
- Display token in console when running as remote for debugging
This creates proper separation:
- Clients authenticate with servers using Basic Auth
- Remotes authenticate with HQ using HQ's Basic Auth
- HQ authenticates with remotes using remote's Bearer token
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove heartbeat mechanism from HQClient - now just registers and forgets
- Update RemoteRegistry to actively check remote health via GET /api/sessions
- Remove /api/remotes/:remoteId/heartbeat endpoint as it's no longer needed
- Pass password to RemoteRegistry for authenticated health checks
- Remote servers no longer need to maintain connection to HQ after registration
- HQ checks remote health every 15 seconds with 5 second timeout
This simplifies the architecture - remotes just tell HQ they exist, and HQ
is responsible for monitoring their health status.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Modify GET /api/sessions to aggregate sessions from all online remotes
- Add remoteId and remoteName fields to session responses
- Implement session ID namespacing (remoteId:sessionId) to prevent collisions
- Add remoteId parameter to POST /api/sessions for creating remote sessions
- Create proxy middleware for forwarding session operations to remote servers
- Apply proxy middleware to all session-specific endpoints
- Handle offline remotes gracefully with proper error responses
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add --hq flag to enable HQ mode for centralized management
- Add --join-hq flag for remote servers to register with HQ
- Implement RemoteRegistry for managing remote server connections
- Add HQClient for remote servers to register and send heartbeats
- Add /api/remotes endpoints for registration, heartbeat, and listing
- Enforce HTTPS requirement for HQ URLs for security
- Add graceful shutdown handling for HQ components
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added HackNerdFontMono-Bold.ttf to improve terminal font rendering
with better bold character support and enhanced readability.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add terminal max width option
- Add terminal preferences manager for persistent settings storage
- Add maxCols property to terminal component with width constraint logic
- Add UI toggle button (∞/80) in session header for easy width control
- Default behavior unchanged: unlimited width (takes full container)
- Optional 80-column max width limit when enabled
- Preferences saved to localStorage and restored on page load
- Real-time updates without page refresh
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: enhance terminal width selector with common presets and custom input
- Add common terminal width presets: ∞, 80, 100, 120, 132, 160
- Add custom width input field (20-500 columns)
- Replace simple toggle with dropdown selector UI
- Include helpful descriptions for each preset
- Support keyboard shortcuts (Enter to submit, Escape to cancel)
- Add click-outside-to-close functionality
- Maintain all existing preferences persistence
- Show current width in button label and tooltip
Common widths:
- 80: Classic terminal
- 100: Modern standard
- 120: Wide terminal
- 132: Mainframe width
- 160: Ultra-wide
- Custom: User-defined (20-500)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: prevent WebSocket send on closed channel panic
Added safeSend helper function with panic recovery to handle race conditions
when multiple goroutines access WebSocket channels. Replaces unsafe channel
sends with graceful error handling.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
- Update color scheme to use dark backgrounds (#0a0a0a, #1a1a1a, #242424)
- Add vibrant green accent colors (#00ff88) with glow effects
- Update Tailwind configuration with new theme colors and utilities
- Add reusable CSS component classes (btn-primary, btn-secondary, btn-ghost, card, input-field)
- Replace inline styles across all components with theme classes
- Create new terminal icon component with glow effect
- Update app header with redesigned layout and session stats
- Update session cards with improved visual hierarchy
- Redesign session create form and file browser modals
- Update session view with consistent theme styling
- Apply theme to mobile controls and overlays
- Update all status indicators to use theme colors
- Add smooth transitions and hover effects throughout
- Add checkForEscPrompt() method to scan buffer content on each update
- Emit 'esc-prompt-change' event when prompt presence changes
- Apply orange border to session card when prompt is detected
- Case-insensitive search for 'esc to interrupt' text
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Properly measure character width at 14px and scale proportionally
- Calculate visible rows based on container height
- Show bottom N lines that fit in the viewport
- Remove overly conservative character width estimates
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Switch from JSON to binary format for buffer data transfer
- Optimize encoding with run-length encoding for empty rows
- Reduce data size with efficient cell encoding (1 byte for spaces, variable for complex cells)
- Support both palette and RGB colors with minimal overhead
- Pre-calculate exact buffer sizes to avoid allocations
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove fontSize and fitHorizontally properties as they're no longer needed
- Always auto-scale font size to fit terminal width in container
- Simplify dimension calculation logic
- Remove unused props from session-card component
- Maintain bottom-aligned terminal view with proper scaling
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Let server decide which portion of buffer to return
- Server defaults to showing bottom portion with prompt
- Only request the number of lines that fit in viewport
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Show bottom portion of buffer when content exceeds viewport
- Keep all content visible when it fits within viewport
- Maintain fitHorizontally mode to show all content scaled
- Calculate proper start index to show the most relevant content
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace dark gray (#1e1e1e) with pure black background
- Match the expected terminal appearance
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Move terminal color definitions to shared CSS in input.css
- Use bright color palette for dark backgrounds
- Switch from Lit template rendering to direct innerHTML for terminal content
- Add display: inline-block to terminal-char for proper rendering
- Remove redundant style definitions from terminal.ts
- Fix issue where Lit's template system was interfering with terminal output
The key fix was using innerHTML directly instead of Lit's template system for
the terminal content, matching the approach used in terminal.ts.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add explicit terminal character styles to ensure proper rendering
- Include style definitions for bold, italic, underline, dim, strikethrough
- Ensure CSS variables are properly inherited from parent scope
- Fix text rendering issues where colors appeared gray
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Reduce data transfer by omitting trailing blank cells
- Keep at least one cell per line to maintain structure
- Handle empty lines efficiently with single space cell
- Add fallback rendering for completely empty lines
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add fitHorizontally mode to vibe-terminal-buffer component
- Scale font size to fit entire terminal width when enabled
- Trim blank lines from bottom of buffer to reduce data transfer
- Always show content from top down (not centered on cursor)
- Match behavior of terminal.ts fitTerminal implementation
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
The component was only fetching as many lines as could fit in its container,
which could miss important context. Now it fetches at least one full terminal
screen worth of lines (stats.rows) to ensure we capture the complete visible
terminal state.
Also improved rendering to show the bottom portion when we have more lines
than can fit in the display area.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
The binary encoding was using 16-bit unsigned integers which failed when:
- Terminal has many rows (>65k)
- Cursor is above the viewport (negative relative position)
Changes:
- Upgrade to version 2 of the binary format
- Use 32-bit integers for dimensions and positions
- Use signed integers for viewport/cursor positions
- Update header size from 16 to 32 bytes
- Update documentation to reflect new format
This fixes the issue where cursorY could be negative when the cursor
is above the visible viewport (e.g., cursorY=0, viewportY=46 results
in relative cursorY=-46).
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace terminal.ts in session-card with new buffer-based component that:
- Fetches terminal buffer snapshots via JSON API
- Polls every second only when content changes (checks lastModified)
- Automatically calculates lines needed based on container height
- Reuses terminal rendering styles and logic
Changes:
- Create terminal-renderer.ts with shared rendering logic for both components
- Add vibe-terminal-buffer component that works with buffer API
- Update session-card to use vibe-terminal-buffer instead of vibe-terminal
- Add terminal-line CSS for proper styling
- Fix color handling in terminal-manager (-1 means default color)
- Add debug logging to help diagnose rendering issues
The new approach is more efficient - no cast file parsing, just direct
buffer snapshots from the server.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major architectural change: replaced tail -f streaming with direct file watching
and server-side terminal state management for better performance and efficiency.
Key changes:
- Add StreamWatcher class using fs.watch() instead of tail -f process
- Benchmarks showed fs.watch() is faster and more efficient
- Handles multiple SSE clients per session without duplicate processes
- Streams existing content then watches for new data
- Add TerminalManager class for server-side xterm.js instances
- Maintains headless terminal state per session
- Watches stream files and feeds data into terminals
- Provides binary buffer snapshots on demand
- Add new /api/sessions/{id}/buffer endpoint
- Returns efficient binary terminal buffer snapshots
- Supports viewportY and lines parameters for partial updates
- Uses run-length encoding for compression
- Create comprehensive binary format documentation (snapshot-format.md)
- 16-byte header with dimensions and cursor position
- Variable-length cell encoding with UTF-8 and RGB support
- ~75% size reduction compared to JSON
- Fix cmdline.join() error with defensive programming
- Handle cases where cmdline might not be an array
This enables session-list.ts to efficiently show terminal states without
overwhelming client/server resources.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Move CANCEL button to the left (renamed from CLOSE)
- Keep CLEAR button in the middle when sequence exists
- Move SEND button to the right when sequence exists
- Follows standard UI convention with cancel actions on left, primary actions on right
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Made terminal container focusable to receive paste events without clipboard API
- Added tabindex="0" and paste event handling to terminal component
- Terminal now dispatches custom 'terminal-paste' events with clipboard text
- Session view listens for paste events and sends text to terminal session
- Standardized resize endpoint field names across all servers (Rust, Go, Node.js)
- Changed from width/height to cols/rows for consistency
- Removed custom clipboard handling code that required permissions
- Standard Ctrl+V/Cmd+V paste now works without permission prompts
- Maintained PID copying functionality in session cards
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
The terminal component was aggressively preventing default on ALL keyboard events, blocking important browser shortcuts like F12 (DevTools), Ctrl+C/Ctrl+V (copy/paste), and Ctrl+F (find).
Updated the keyboard handler to:
- Allow F12 and Ctrl+Shift+I/Cmd+Alt+I for DevTools
- Allow common browser shortcuts like Ctrl+A, Ctrl+F, Ctrl+R, etc.
- Allow Alt+Tab and Cmd+Tab for window switching
- Only preventDefault on keys that are actually handled by the terminal
This preserves terminal functionality while restoring essential browser shortcuts.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Set implementation to 'node-pty' and disable fallback to tty-fwd
- Remove conditional logic since we always have direct PTY access
- Simplify input handling to always use direct PTY write
- Remove fallback session status monitoring
- fwd.ts is the Node.js replacement for tty-fwd, should never use tty-fwd itself
This makes fwd.ts behavior consistent and eliminates complexity from fallback paths.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Use PTY process onExit handler for immediate exit detection instead of asciinema stream monitoring
- Remove redundant asciinema exit event parsing - that's output format, not process state
- Make session status polling a fallback only when direct PTY access isn't available
- This provides faster, more reliable exit detection at the source (PTY process)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add proper cleanup of all intervals and FIFO streams on exit
- Detect exit events directly from asciinema stream for faster response
- Reduce session monitoring polling from 1000ms to 500ms
- Remove redundant createControlPipeForExternalSession function
- fwd.ts now creates its own control pipe, PtyManager no longer needs to create them
This should eliminate the hanging issue when exiting processes wrapped with fwd.ts.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace blocking spawnSync calls with direct stdin pipe writes
- Change from 100ms polling to fs.watchFile for immediate file notifications
- Use appendFileSync instead of writeFileSync for better performance
- Add platform-specific key mapping for tty-fwd input path
- Reduce polling interval from 100ms to 50ms for watchFile
This eliminates the 5-second timeout blocking and improves input responsiveness from 1-2 seconds to near-instantaneous.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change enter key from \n (line feed) to \r (carriage return) on Windows
- Maintains \n for Unix/macOS compatibility
- Fixes enter key behavior in Windows terminals
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add platform detection for Windows vs Unix FIFO handling
- Implement polling fallback for Windows control pipes
- Add direct PTY process access for faster keyboard input
- Fix duplicate cleanup handlers and formatting issues
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add proper type guards for control message fields (cols, rows, signal)
- Handle string | Buffer types for stream data events correctly
- Fix null assignment issue in control pipe creation
- Add type conversion for chunk data in FIFO streams
All TypeScript errors resolved.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create control as FIFO instead of regular file using mkfifo
- Use same read+write streaming approach as stdin FIFO
- Rename 'control-pipe' to 'control' for consistency
- Replace polling mechanism with continuous FIFO streaming
- Update session type to use 'control' field name
- Fix PtyManager to reference correct control field
This should fix the issue where resize only worked once due to
control pipe closing after first write.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Open stdin FIFO with 'r+' mode to keep it open continuously
- Use fs.openSync + createReadStream for proper FIFO handling
- Prevent FIFO from closing when external writers disconnect
- Follow tty-fwd pattern of opening FIFO for both read and write
- Remove problematic spawn('cat') approach that was exiting
This should fix the issue where stdin FIFO closes after first input.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change enter key from '\r' to '\n' for correct shell behavior
- Swap enter and ctrl_enter mappings to match terminal expectations
- Most shells expect newline (\n) to execute commands, not carriage return (\r)
This fixes the issue where commands typed in frontend would hang
after pressing enter instead of executing properly.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add stdin FIFO monitoring to fwd.ts for web server input forwarding
- Create ReadStream to continuously read from stdin pipe
- Forward web server input to PTY process in real-time
- Prevent hanging when web server sends input to external sessions
- Maintain dual input sources: terminal keyboard + web frontend
This fixes the issue where fwd.ts would hang when receiving
input from the web server via the stdin FIFO pipe.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add automatic control pipe creation for existing external sessions
- Update session.json retroactively when control pipe is created
- Implement SIGWINCH fallback when control pipe is not available
- Support resize operations for legacy external sessions
This enables resize functionality for sessions created before
the control pipe feature was implemented.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add control-pipe field to session types for external command communication
- Create ResizeControlMessage and KillControlMessage interfaces
- Update PtyManager to send control messages via pipe for external sessions
- Enhance fwd.ts to create and monitor control pipe for resize/kill commands
- Support real-time resize operations for external sessions via IPC
- Add proper cleanup of control pipes on session exit
This enables full PTY control (resize, kill) for sessions created by
external tools like fwd.ts through a file-based IPC mechanism.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Modify sendInput to write to stdin pipe for external sessions
- Update resizeSession to handle external sessions gracefully
- Fix killSession to work with sessions created by fwd.ts
- Check filesystem for session info when not in memory map
- Support both in-memory and disk-only session management
This fixes frontend operations failing with "Session not found"
when interacting with sessions created by external tools.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create fwd.ts command-line tool for spawning PTY sessions
- Support both interactive and monitor-only modes
- Real-time bidirectional terminal communication
- Parse asciinema output format for clean terminal display
- Handle terminal raw mode and graceful cleanup
- Auto-detect PTY implementation (node-pty vs tty-fwd)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change from w-full h-full to fixed inset-0 for proper viewport centering
- Ensures loading spinner is centered relative to entire viewport
- Provides better visual positioning regardless of container constraints
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace static "No session selected" text with animated loading spinner
- Use same loading animation style as session connection state
- Shows "Waiting for session..." message with spinning indicator
- Provides better visual feedback when waiting for session selection
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add refreshTerminalAfterMobileInput() method to recalculate scroll position
- Call refresh after closing mobile input overlay (cancel, send, send+enter)
- Wait 300ms for viewport to settle before forcing scrollToBottom()
- Fixes issue where terminal scroll position gets confused after keyboard disappears
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove hideAddressBar() method and calls that were interfering with viewport
- Remove adjustTerminalForMobileButtons() method that was causing layout issues
- Terminal should now display properly on mobile without being cut off
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>