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_UPDATEaction - 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 readisNavigating: 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:
- Organization setup screen appears
- Research prompt is generated
- Prompt stored in sessionStorage
What's Broken:
- Auto-selection happens multiple times
- Research prompt sometimes submitted twice
- UI flashes during project creation
- 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)
- On file save: 10-20 component re-renders
- On project switch: 3-5 selection attempts
- On session creation: Full projects reload
- 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.