Commit Graph

44 Commits

  • fix: terminal command execution via HTTP POST workaround
    The WebSocket send mechanism fails with close code 1006 when client
    tries to send data to server. Server never receives the message,
    indicating a network/proxy layer issue that couldn't be fixed through
    code changes or nginx configuration.
    
    Solution: Bypass WebSocket send entirely by using HTTP POST to send
    commands directly to the PTY.
    
    Changes:
    - Added sendTerminalInput() method to terminal-service.js that writes
      directly to PTY, bypassing WebSocket
    - Added POST endpoint /claude/api/terminals/:id/input to server.js
    - Modified launchCommand() in terminal.js to use fetch() with HTTP
      POST instead of WebSocket.send()
    
    The WebSocket receive direction still works (server→client for output
    display), only send direction (client→server for commands) is bypassed.
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • test: change command to simple echo for debugging
    Changed from 'claude --dangerously-skip-permissions\n' to 'echo "WebSocket test"\n'
    to test if the WebSocket closure issue is related to the command itself.
    
    This will help determine if:
    1. The issue is with the command length/format
    2. The issue is with WebSocket data transmission in general
    3. The PTY is handling the command correctly
  • docs: save working nginx config for rommark.dev
    Complete nginx configuration with proper WebSocket support:
    - Added connection_upgrade map for WebSocket upgrade handling
    - Configured /claude location with proper WebSocket headers
    - Set extended timeouts (7d) for WebSocket connections
    - Disabled buffering for real-time communication
    
    This config fixes the WebSocket closure issue that was preventing
    terminal commands from being executed.
  • fix: update nginx config for proper WebSocket support
    Changes:
    1. Added  map for proper WebSocket upgrade handling
    2. Changed Connection header from literal 'upgrade' to  variable
    3. Added proxy_send_timeout 7d to prevent premature connection closure
    4. Disabled proxy_buffering and proxy_request_buffering for WebSocket
    5. Added proxy_request_buffering off for better WebSocket performance
    
    These changes should fix the WebSocket closure issue that was preventing
    commands from being sent to the terminal.
  • fix: remove stabilization delay and fitAddon.fit() call
    The WebSocket was closing exactly 100ms after switchToTerminal completed,
    which correlated with the setTimeout(fitAddon.fit(), 100) call.
    
    Hypothesis: The fitAddon.fit() call or the 100ms delay is causing
    the WebSocket to close through an unknown mechanism (possibly triggering
    browser GC, event loop blocking, or some resource cleanup).
    
    Changes:
    - Removed 100ms stabilization delay in launchCommand
    - Disabled fitAddon.fit() call in switchToTerminal
    
    This should prevent the WebSocket closure and allow commands to be sent.
  • fix: await switchToTerminal to prevent race condition
    The issue was that switchToTerminal() was not being awaited, so
    launchCommand() was called while switchToTerminal() was still
    executing. This caused a race condition where the WebSocket
    closed before the command could be sent.
    
    By awaiting switchToTerminal(), we ensure the terminal is fully
    switched before attempting to send any commands.
  • debug: add switchToTerminal logging and fitAddon error handling
    - Log when switchToTerminal is called and if terminal is in map
    - Log fitAddon.fit() execution with error handling
    - Log when switchToTerminal completes
    
    This will help identify if switchToTerminal is causing the WebSocket closure
  • debug: add detailed spawn attempt and error logging
    - Log spawn attempt before calling spawn()
    - Add detailed error logging with stack trace
    - This will help identify if spawn is failing silently
  • debug: add PTY lifecycle logging
    - Log PTY PID and shell when spawned
    - Log all PTY output data
    - Log PTY exit events with exit code and signal
    - Log when WebSocket cannot send PTY data
    
    This will help identify if the PTY is exiting immediately
    or if there's an issue with the PTY process.
  • debug: add WebSocket stability delay and enhanced checks
    - Added 100ms delay before sending command to ensure WebSocket stability
    - Added detailed WebSocket state logging (CONNECTING, OPEN, CLOSING, CLOSED)
    - Added bufferedAmount check to wait for pending sends
    - Wrapped ws.send() in try-catch for better error reporting
    - Split terminal and ws existence checks for clearer debugging
  • debug: add visual debug panel and comprehensive logging
    - Added debug panel in terminal view that shows all terminal activity
    - Added debugLog() method to TerminalManager for consistent logging
    - Updated connectTerminal, handleTerminalMessage, launchCommand, createTerminal, initializeXTerm with detailed logging
    - Enhanced backend logging for WebSocket messages and close codes
    - Logs now show both to console and visual debug panel
    
    This should help diagnose the terminal command execution issue without
    requiring browser console access.
  • debug: add comprehensive logging for terminal command flow
    Phase 1 of systematic debugging: Gather evidence
    
    Added detailed logging to trace the complete command flow:
    - launchCommand: Shows when called, terminalId, command, WebSocket state
    - waitForTerminalReady: Shows waiting period and ready state
    - handleTerminalMessage: Shows all messages from backend with details
    - WebSocket message content logged before sending
    
    Also fixed duplicate 'ready' message (removed line 113-116).
    
    Now when user creates "Claude Code CLI" terminal, console will show:
    1. launchCommand called with terminalId and command
    2. Waiting for terminal ready
    3. Ready message received (or timeout)
    4. Command sent to WebSocket
    5. All backend messages logged
    
    This will reveal exactly where the flow breaks.
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix: backend sends ready message when WebSocket connects
    Critical fix: The frontend was waiting for a 'ready' message that the
    backend never sent, causing commands to timeout.
    
    Root Cause:
    Frontend connectTerminal() waits for 'ready' message from backend
    before resolving, but backend never sent this message. Result: Frontend
    timed out after 5 seconds waiting for ready state, and commands were
    never sent.
    
    Fix:
    Send 'ready' message immediately when WebSocket connection is established.
    This signals to frontend that PTY is initialized and ready to receive input.
    
    Flow Now:
    1. Frontend creates terminal UI
    2. Frontend initializes xterm.js
    3. Frontend connects WebSocket
    4. Backend receives connection, sends 'ready' message
    5. Frontend receives 'ready', sets ready=true, resolves promise
    6. Frontend sends claude --dangerously-skip-permissions command
    7. Command executes successfully
    
    Resolves: "still getting empty terminal"
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix: wait for PTY ready state before sending commands
    Implement proper ready-state handshake to fix command execution timing.
    
    Root Cause:
    WebSocket connection was opening immediately, but the backend PTY
    (pseudo-terminal) wasn't ready to receive input yet. Commands sent
    too early were lost, causing claude --dangerously-skip-permissions to
    never execute.
    
    Broken Flow:
    1. WebSocket opens → connectTerminal() resolves immediately
    2. Command sent → PTY not ready, command lost
    3. Terminal shows cursor but Claude CLI never starts
    
    Fixed Flow:
    1. WebSocket opens → Wait for 'ready' message from backend
    2. Backend sends 'ready' → PTY is now initialized
    3. Command sent → PTY receives it successfully
    4. Claude CLI starts
    
    Changes:
    - Add 'ready' flag to terminal state (default false)
    - connectTerminal() now waits for 'ready' message before resolving
    - Add waitForTerminalReady() helper with 5s timeout
    - launchCommand() checks ready state before sending
    - Enhanced error handling and console logging
    
    Resolves: "terminal does not show or execute claude cli"
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix: initialize xterm.js before connecting WebSocket
    Critical fix for completely broken terminal (blinking cursor, no input).
    
    Root Cause:
    The WebSocket was being connected before xterm.js was initialized,
    causing the WebSocket reference to be lost because this.terminals
    map didn't have the entry yet.
    
    Broken Flow:
    1. createTerminalUI() - Creates DOM elements only
    2. connectTerminal() - Tries to store ws in terminal, but terminal = null
    3. WebSocket reference lost immediately
    4. No input/output possible
    
    Fixed Flow:
    1. createTerminalUI() - Creates DOM elements
    2. initializeXTerm() - Creates xterm.js instance AND stores in map
    3. connectTerminal() - Now finds terminal in map, stores ws successfully
    4. switchToTerminal() - Terminal works!
    
    Changes:
    - Add explicit initializeXTerm() call before connectTerminal()
    - Add error checking in connectTerminal() to verify terminal exists
    - Add comments enforcing ordering requirements
    
    Resolves: "All I see is blinging | and nothing else, no claude cli,
    no commands, i cant type in anything. terminal is not woring."
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix: wait for WebSocket connection before sending command
    Make connectTerminal() return a Promise that resolves when the
    WebSocket connection is established, ensuring commands are sent
    only after the terminal is ready.
    
    Root cause:
    - connectTerminal() created WebSocket but returned immediately
    - 500ms delay wasn't reliable - WebSocket might not be open yet
    - Command was sent before connection was ready, causing it to fail silently
    
    Fix:
    - Wrap WebSocket creation in Promise
    - Resolve Promise in ws.onopen callback
    - Reject on ws.onerror
    - Remove unnecessary 500ms delay
    
    Now when "Claude Code CLI" terminal type is selected:
    1. WebSocket connection is established
    2. We wait for connection to be ready
    3. Command is sent immediately
    4. claude --dangerously-skip-permissions launches reliably
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix: don't set session mode for standalone Claude CLI
    When launching Claude Code CLI with --dangerously-skip-permissions,
    don't set the terminal mode to 'session' since we're not attaching
    to an existing session. Keep it in 'mixed' mode instead.
    
    The "Invalid session" error occurred because:
    1. We launched claude --dangerously-skip-permissions without a session
    2. Then set mode to 'session' which expects a valid session attachment
    3. The CLI or backend rejected this as invalid
    
    Fix: Remove the setMode call when using claude-cli terminal type.
    Let the CLI create and manage its own session internally.
    
    Resolves: "Invalid session" error when selecting Claude Code CLI
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add terminal type selection in directory picker
    Add CSS styling for the terminal type dropdown that was already
    implemented in the JavaScript but wasn't visible due to missing styles.
    
    The dropdown allows users to choose between:
    - Standard Shell (bash/zsh) - default
    - Claude Code CLI - runs claude --dangerously-skip-permissions
    
    When Claude Code CLI is selected:
    - Session picker is skipped (not needed)
    - Terminal automatically launches with claude --dangerously-skip-permissions
    - Mode is automatically set to 'session'
    
    Changes:
    - Add .terminal-type-selection, .terminal-type-select styles to terminal.css
    - Match existing modal styling (background, borders, focus states)
    - JavaScript was already implemented from previous work
    
    Resolves: "Claude Code CLI still not appears under terminal > new terminal"
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix: render simple table rows instead of project sections
    Fix table alignment issue on landing page by rendering simple table
    rows instead of collapsible project sections inside the tbody.
    
    Changes:
    - Simplify renderSessionsGroupedByProject() to render table rows directly
    - Add table-layout: fixed to .projects-table for proper column widths
    - Sort sessions by last activity (newest first)
    
    The previous implementation was rendering div elements (project sections)
    inside the table tbody, which broke the table layout. Table elements
    only accept tr elements as direct children.
    
    Resolves "things don't align" issue on projects table.
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix: add trust proxy and improve session configuration for nginx
    Add Express trust proxy setting and improve session cookie configuration
    to work properly behind nginx reverse proxy.
    
    Changes:
    - Add app.set('trust proxy', 1) before session middleware
    - Update session cookie with sameSite: 'lax' and httpOnly: true
    - Add explicit cookie name: 'connect.sid'
    
    This works together with nginx location blocks to route /api/projects
    and /api/recycle-bin requests to the Obsidian Web Interface (port 3010)
    instead of the generic Next.js backend (port 8080).
    
    Fixes "Failed to load on projects" error on production domain.
    
    See AUTHENTICATION_FIX_REPORT.md for full details.
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix: add credentials to fetch calls for authenticated API requests
    Fix "Failed to load on projects" error by including credentials in all
    fetch calls to /api/* endpoints. The session cookie must be sent with
    requests for requireAuth middleware to authenticate users.
    
    Changes:
    - projects.js: Add credentials: 'include' to all 6 API fetch calls
      (loadProjects, saveProject, deleteProject, loadDeletedProjects,
       restoreProject, permanentDeleteProject)
    - sessions-landing.js: Add credentials to 3 API fetch calls
      (loadSessionsAndProjects, moveSessionToProject, context menu
       suggestions)
    
    Resolves issue where projects page showed "Failed to load projects"
    error on https://www.rommark.dev/claude
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • docs: add comprehensive README for Claude Code Web Interface
    Add complete README.md with:
    - Feature overview and highlights
    - Quick start guide (3-minute setup)
    - Installation instructions (systemd, PM2)
    - Configuration guide
    - Complete usage guide (sessions, projects, terminal, XML tags)
    - Full API reference with examples
    - Development guide with project structure
    - Database schema documentation
    - Troubleshooting section
    - Contributing guidelines
    - License and acknowledgments
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • docs: add projects feature documentation and finalize integration
    - Add comprehensive projects feature documentation (docs/projects-feature.md)
    - Add testing guide and checklist (test_projects_feature.js)
    - Update .gitignore to exclude database files
    - Include Task 13 completion summary
    
    Documentation covers:
    - Feature overview and key capabilities
    - Project creation (manual and smart suggestions)
    - Session assignment (automatic and manual)
    - Project management (edit, delete, restore)
    - Complete API reference
    - Smart suggestions explanation
    - Troubleshooting and FAQ
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: auto-assign new sessions to selected project
    Modified session creation endpoint to accept and store projectId:
    - Accept optional projectId parameter in POST /claude/api/claude/sessions
    - Validate projectId exists and is not deleted before assignment
    - Store projectId in both session metadata and database
    - Update project's lastActivity timestamp when session is created
    - Also updated duplicate endpoint to preserve projectId from source session
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add projects page route and navigation link
    - Add GET /projects route in server.js with authentication check
    - Serve projects.html when authenticated, redirect to login otherwise
    - Add navigation header to both landing page and projects page
    - Include Sessions, Projects navigation links with active state styling
    - Add logout button to navigation header
    - Style navigation with dark theme matching existing design
    - Make navigation responsive for mobile devices
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add database migration script for projects
    Add migration script to backfill existing sessions into projects:
    - Scans session files from Claude Sessions directory
    - Extracts unique project names from metadata.project field
    - Creates projects with random icons and colors
    - Links sessions to their respective projects in database
    - Provides detailed progress reporting and summary
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add session context menu for project reassignment
    Implemented smart suggestions UI with visual indicators for moving sessions between projects.
    
    Features:
    - Right-click context menu on session rows
    - Fetches smart project suggestions from API
    - Displays top 3 suggestions with match scores and reasons
    - Visual indicators: 🎯 (90+), 📂 (50-89), 💡 (10-49)
    - "Open in IDE" option for quick navigation
    - "Show All Projects" modal for full project list
    - "Move to Unassigned" to remove project association
    - Smooth animations and hover effects
    - Click outside to close menu
    - Responsive design for mobile devices
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: group sessions by project on landing page
    - Add loadSessionsAndProjects() to fetch sessions and projects in parallel
    - Store projects in window.projectsMap for quick lookup
    - Group sessions by projectId, separating assigned and unassigned
    - Render collapsible project sections with icon, name, and session count
    - Add toggleProjectSection() to collapse/expand sections (▼/▶)
    - Display project badges on sessions when assigned to a project
    - Unassigned sessions shown in separate section at bottom
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add projects page JavaScript functionality
    Implement complete JavaScript functionality for the projects management page:
    
    - State management for projects array and current editing project
    - loadProjects() - Fetch projects from /api/projects
    - renderProjects(filter) - Render project cards with search/filter support
    - setupEventListeners() - Wire up all interactive elements
    - openProject(projectId) - Navigate to sessions page for selected project
    - openProjectModal(project) - Open modal for create/edit operations
    - closeProjectModal() - Close modal and reset form
    - handleProjectSubmit(e) - Validate and save project data
    - showProjectMenu(projectId, event) - Display context menu
    - deleteProject(projectId) - Soft delete with confirmation
    - openRecycleBinModal() - Display deleted projects
    - restoreProject(projectId) - Restore from recycle bin
    - permanentDeleteProject(projectId) - Delete forever with confirmation
    - escapeHtml(text) - XSS prevention for user-generated content
    - formatDate(dateString) - Human-readable relative timestamps
    - showToast(message, type) - Toast notifications with animations
    
    Features:
    - Async/await for all API calls
    - Comprehensive error handling
    - Real-time search filtering
    - Context menu for project actions
    - Responsive modal system
    - Toast notifications for user feedback
    - Keyboard shortcuts (Escape to close)
    - Click outside to close menus/modals
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add projects page styles
    Add comprehensive CSS styles for the projects management page including:
    - Page layout with responsive header
    - Projects grid with auto-fill layout (300px min cards)
    - Project cards with hover effects and stats
    - Modal styles for create/edit and recycle bin
    - Form elements with proper styling
    - Button styles (primary/secondary)
    - Context menu for card actions
    - Recycle bin items with restore/delete actions
    - Empty state styling
    - Responsive design for mobile devices
    - Scrollbar styling
    
    Uses CSS variables from existing style.css for consistency.
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add smart project suggestions endpoint
    Added GET /api/projects/suggestions endpoint that provides intelligent
    project suggestions based on session context. The endpoint:
    
    - Takes sessionId as a required query parameter
    - Retrieves session from in-memory or historical sessions
    - Calculates scores for each project using multiple criteria:
      * Directory match (90 points): session workingDir === project path
      * Subdirectory match (50 points): session workingDir starts with project path
      * Used today (20 points): project lastActivity < 1 day ago
      * Used this week (10 points): project lastActivity < 7 days ago
      * Name similarity (15 points): overlap between session dir name and project name
    
    - Returns top 3 scored suggestions with reasons
    - Also returns all projects sorted alphabetically
    - Filters out projects with zero scores from suggestions
    - Handles missing sessions with appropriate error responses
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix: correct route path, fix race condition, add persistence for active sessions
    - Fix route path from /api/sessions/:id/move to /claude/api/claude/sessions/:id/move
    - Fix race condition by fetching session once and storing isActiveSession flag
    - Add database persistence for active session metadata changes
    - Ensures consistency between in-memory and database state
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add session move endpoint and project-session cascading delete
    - Add sessions table to database with projectId and deletedAt columns
    - Create POST /api/sessions/:id/move endpoint to reassign sessions
    - Update DELETE /api/projects/:id to cascade soft-delete to sessions
    - Support moving sessions between projects or to unassigned state
    - Handle both active (in-memory) and historical sessions
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add soft delete, restore, permanent delete, and recycle bin endpoints
    - Add DELETE /api/projects/:id - Soft delete project (sets deletedAt)
    - Add POST /api/projects/:id/restore - Restore from recycle bin
    - Add DELETE /api/projects/:id/permanent - Permanent delete
    - Add GET /api/recycle-bin - List deleted items sorted by deletedAt DESC
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • fix: add input validation and fix unique constraint
    Fixed code quality issues from Task 2 review:
    
    1. Added ID validation in PUT endpoint:
       - Validates req.params.id is a valid positive integer
       - Returns 400 for invalid IDs (non-numeric, negative, zero, decimals)
       - Prevents SQL injection attempts
    
    2. Added path validation in POST and PUT endpoints:
       - Validates projectPath is absolute path
       - Normalizes and resolves paths
       - Detects and blocks path traversal attempts (e.g., ../../../etc)
       - Returns 400 for invalid paths
    
    3. Fixed UNIQUE constraint in database schema:
       - Removed UNIQUE constraint from name column
       - Allows creating projects with same name as deleted projects
       - Application-level duplicate checking remains for active projects
       - Added table migration to drop and recreate schema
    
    Files modified:
    - server.js: Added validateProjectId() and validateProjectPath() helpers
    - services/database.js: Removed UNIQUE constraint, added migration
    
    All validation tested and working correctly.
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add project CRUD API endpoints (SQLite)
    Added three new API endpoints for managing projects using SQLite:
    
    - GET /api/projects - Lists all active projects (deletedAt IS NULL)
      * Sorts by lastActivity DESC
      * Returns id, name, description, icon, color, path, sessionCount, createdAt, lastActivity
    
    - POST /api/projects - Creates new project
      * Required fields: name, path
      * Optional fields: description, icon (default '📁'), color (default '#4a9eff')
      * Validates required fields and checks for duplicate names
      * Returns 201 status on success
    
    - PUT /api/projects/:id - Updates existing project
      * Allows updating: name, description, icon, color, path
      * Only updates projects where deletedAt IS NULL
      * Returns 404 if project not found
      * Validates duplicate names on name change
    
    All endpoints use synchronous better-sqlite3 API with parameterized queries.
    SessionCount set to 0 for now (will be implemented in Task 3).
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • feat: add SQLite database and projects table schema
    - Install better-sqlite3 package for persistent storage
    - Create database service with projects table schema
    - Add indexes on deletedAt and name for efficient queries
    - Support soft-delete with deletedAt timestamp
    - Export database instance for use in server.js
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
  • Initial commit: Obsidian Web Interface for Claude Code
    - Full IDE with terminal integration using xterm.js
    - Session management with local and web sessions
    - HTML preview functionality
    - Multi-terminal support with session picker
    
    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>