Last updated: Sep 1, 2025, 01:10 PM UTC

Current Architecture Documentation

Version: 1.0.0
Status: ACCURATE
Date: 2025-01-29
Purpose: Documents the ACTUAL current implementation

System Overview

Sasha Studio is a file-system-driven reactive application where Claude CLI writes to the file system and the UI observes changes through file watchers.

Architecture Diagram

User Input β†’ UI β†’ WebSocket β†’ Server β†’ Claude CLI β†’ File System
                                             ↓
                                     JSONL Session Files
                                             ↑
                                     Chokidar Watcher
                                             ↓
                              WebSocket Broadcast to All Clients
                                             ↓
                                    Full Projects Array Update
                                             ↓
                                     UI Re-renders Everything

Current Implementation Details

1. Claude CLI Integration

Location: server/claude-cli.js

How it works:

  • Server spawns Claude CLI process: claude --output-format stream-json
  • Claude writes responses to JSONL files in ~/.claude/projects/{project-id}/sessions/
  • Claude does NOT directly execute file system tools
  • Tool executions are recorded in JSONL but executed by the server

Current Issues:

  • No distinction between Claude's tool requests and actual execution
  • Confusing logs about "Claude writing files" when it's actually the server

2. File System Monitoring

Location: server/index.js (setupProjectsWatcher function)

Current Configuration:

{
  watched: '~/.claude/projects/',
  debounce: 300ms,
  ignored: ['node_modules', '.git', 'dist', 'build', '*.tmp', '*.swp', '.DS_Store']
}

Current Behavior:

  • ANY file change triggers full project reload
  • Server calls getProjects() which reads ALL projects
  • Sends entire projects array via WebSocket
  • No differentiation between file types

Performance Impact:

  • Saving one file causes 10-20 component re-renders
  • Full projects array (~100KB+) sent on every change
  • All clients receive all updates (no filtering)

3. WebSocket Communication

Location: utils/websocket.js, hooks/useProjectWebSocketV2.js

Current Message Flow:

// Server sends (on EVERY file change):
{
  type: 'projects_updated',
  projects: [...], // ENTIRE array
  timestamp: '...',
  changeType: 'add|change|unlink', // IGNORED by client
  changedFile: 'path/to/file'      // IGNORED by client
}

Client Processing:

  • Receives message in useProjectWebSocketV2
  • Dispatches WEBSOCKET_UPDATE action
  • Replaces ENTIRE projects array
  • Triggers re-render cascade

4. State Management

Location: reducers/projectReducer.js

Current State Structure:

{
  projects: [],              // Full array replaced on every update
  selectedProjectId: null,
  selectedSessionId: null,
  isLoadingProjects: true,
  pendingNavigation: null,
  pendingOperation: null,
  operationQueue: [],
  fileCache: {},
  flags: {
    isSelectingProject: false,
    isCreatingSession: false,
    isProcessingWebSocket: false,  // SET but NEVER CHECKED
    isNavigating: false,           // SET but NEVER CHECKED
    isOnboarding: false,
    isLoadingFiles: false
  }
}

Issues with Current Flags:

  • isProcessingWebSocket: Set to true/false but never read
  • isNavigating: Duplicates React Router state
  • Multiple boolean flags instead of state machine

5. URL Routing

Current Routes:

/                           # Welcome screen
/session/{sessionId}        # Direct session view (legacy)

Missing Features:

  • No project context in URL
  • No tab state in URL
  • Can't bookmark specific views
  • Browser back/forward broken

6. Component Re-render Issues

App.jsx (Lines 128-209):

  • 80+ line useEffect with multiple responsibilities
  • Dependencies on full objects (projects, location)
  • Triggers on every projects array update

ChatInterface.jsx:

  • Multiple useEffects for storage operations
  • Refs used to prevent re-render loops
  • Complex onboarding flow with ref-based state

7. Browser Storage Usage

localStorage (Current):

auth-token                    # JWT token
autoExpandTools              # UI preference
showRawParameters            # UI preference
autoScrollToBottom           # UI preference
sendByCtrlEnter             # UI preference
showTaskUpdates             # UI preference
permissionMode              # Claude permissions
whisperMode                 # Voice settings
activePersona               # AI persona
sasha_chat_messages_*       # PROBLEMATIC - caching messages

sessionStorage (Current):

organizationResearchPrompt   # Onboarding prompt (GOOD)
pendingSessionId            # PROBLEMATIC - duplicates state
activeSessionId             # PROBLEMATIC - duplicates state
sessionState                # PROBLEMATIC - duplicates reducer

8. Performance Metrics (Actual)

Operation Current Performance Problem
File save β†’ UI update ~800ms Too slow
Re-renders per file change 10-20 Way too many
Project switches per action 3-5 Should be 1
File fetches per project 10-40 Should be 1
WebSocket message size ~100KB Too large

9. Onboarding Flow (Current)

What Works:

  1. Organization setup screen appears
  2. Research prompt is generated
  3. Prompt stored in sessionStorage

What's Broken:

  1. Auto-selection happens multiple times
  2. Research prompt sometimes submitted twice
  3. UI flashes during project creation
  4. File fetches happen 40+ times

10. Debouncing Issues

Current Debounce Values:

  • File watcher: 300ms (too short for batch operations)
  • No debouncing on WebSocket client side
  • No debouncing on project selection
  • No debouncing on file fetches

Result: Rapid fire updates overwhelm the UI

Critical Problems Summary

Problem 1: Full Array Replacement

Every file change replaces the entire projects array, causing massive re-renders.

Problem 2: Ignored WebSocket Fields

Server sends changeType and changedFile but client ignores them, missing optimization opportunity.

Problem 3: Object Dependencies in useEffect

Components depend on objects/arrays that change every render, causing effect loops.

Problem 4: No Update Targeting

Can't update just messages or just files - everything updates together.

Problem 5: Multiple Selection Triggers

Project selection triggered by route changes, WebSocket updates, AND user actions.

Problem 6: Storage Duplication

Same data stored in localStorage, sessionStorage, AND reducer state.

Problem 7: Missing State Machine

Complex flows use multiple boolean flags instead of coherent state machines.

File Locations Reference

Component File Path Key Issues
Project Reducer reducers/projectReducer.js Full array replacement, unused flags
WebSocket Hook hooks/useProjectWebSocketV2.js Ignores message details
Server Watcher server/index.js:setupProjectsWatcher Reloads everything
Claude CLI server/claude-cli.js Confusing tool execution
App Component src/App.jsx:128-209 Mega useEffect
Chat Interface src/components/ChatInterface.jsx Complex ref dance

Actual WebSocket Messages

// What server ACTUALLY sends:
{
  type: 'projects_updated',
  projects: [
    {
      id: 'project-123',
      name: 'my-project',
      sessions: [
        {
          id: 'session-456',
          messages: [...],  // ALL messages
          timestamp: '...'
        }
      ],
      files: [...]  // ALL files
    }
    // ... ALL other projects
  ],
  timestamp: '2025-01-29T10:00:00Z',
  changeType: 'change',        // IGNORED
  changedFile: 'docs/guide.md'  // IGNORED
}

Browser Behavior (Actual)

  1. On file save: 10-20 component re-renders
  2. On project switch: 3-5 selection attempts
  3. On session creation: Full projects reload
  4. On documentation change: Full projects reload (should be toast only)

This document represents the ACTUAL current state of the system as of 2025-01-29.