# Claude Flow — Codebase Overview ## What This Is An Electron desktop app that enforces a **Research → Plan → Implement** workflow for AI-assisted coding, using `@anthropic-ai/claude-agent-sdk`. ## Tech Stack - **Electron 38** + **Vite** + **React 19** + **TypeScript** - **better-sqlite3** — local persistence (projects, sessions, messages) - **@anthropic-ai/claude-agent-sdk** — Claude integration - **CodeMirror 6** — markdown editor in DocumentPane - **react-markdown + remark-gfm** — markdown renderer ## Project Structure ``` src/main/ # Electron main process claude/ # SDK integration + phase configs db/ # SQLite layer (schema, projects, sessions) ipc/ # IPC channel registrations index.ts # App entry, BrowserWindow preload.ts # contextBridge API surface renderer/src/ # React UI App.tsx # Root — all state management components/ # Header, DocumentPane, ChatPane, ActionBar types.ts # Shared TypeScript types styles/ # CSS variables (dark/light themes) ``` ## Key Patterns ### Phase System Phases: `research | plan | implement`. Each defined in `src/main/claude/phases.ts` with its own `systemPrompt`, `tools[]`, `permissionMode`, and `initialMessage`. Phase progression is one-way; triggered by user clicking "Submit". **Important**: All new sessions currently start at `research` phase by default (hardcoded in `sessions.createSession()`). If building phase selection UI, modify `createSession()` in both `/db/sessions.ts` and the IPC handler at `/ipc/handlers.ts` to accept an optional `phase` parameter. ### Artifact Storage Session artifacts (`research.md`, `plan.md`) stored inside the target project at `.claude-flow/sessions/{sessionId}/`. This keeps them within the SDK's allowed write boundary (project `cwd`). Add `.claude-flow/` to `.gitignore` to exclude from version control. ### Session Continuity Claude SDK session IDs are captured from the `system:init` message and stored in SQLite. Subsequent turns resume the same SDK session (`options: { resume: claude_session_id }`). ### IPC Pattern All renderer→main communication goes through named IPC channels registered in `src/main/ipc/handlers.ts`. Streaming events flow back via `mainWindow.webContents.send("claude:message", sessionId, msg)` and are received via `ipcRenderer.on()`. ### Database SQLite at `app.getPath("userData")/claude-flow.db`. Tables: `projects`, `sessions`, `messages`. Foreign keys ON, WAL mode enabled. Schema migrations: `db/index.ts::getDb()` calls `initSchema()` which uses `CREATE TABLE IF NOT EXISTS`. **New columns require explicit `ALTER TABLE` migration** run after `initSchema()`. ### SDK Permission Modes `PermissionMode` values: `'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'dontAsk'` **Known bug**: `permissionMode: 'bypassPermissions'` requires a companion flag `allowDangerouslySkipPermissions: true` in the `query()` options. This flag is currently missing from `claude/index.ts`. `allowedTools: string[]` in the SDK maps to Claude Code's `--allowedTools` CLI flag and supports patterns like `'Bash(git *)'` to auto-allow only specific Bash command forms. ## UI Architecture ### Current Layout ``` ┌─────────────────────────────────────────────────────┐ │ Header: Project selector, Session selector, Controls │ ├─────────────────────────────────────────────────────┤ │ Main Content (flex row) │ │ ├─ Document Pane (flex 1) │ │ │ └─ Markdown editor/viewer │ │ └─ Chat Pane (resizable, 380px default) │ │ └─ Chat messages + input │ ├─────────────────────────────────────────────────────┤ │ Action Bar: Review/Submit buttons, tokens, settings │ └─────────────────────────────────────────────────────┘ ``` ### Key Components - **App.tsx**: Root container, manages projects/sessions/messages state, subscription to Claude messages - **Header.tsx**: Project & session selection (dropdowns + buttons), phase indicator, theme toggle - **DocumentPane.tsx**: CodeMirror markdown editor in edit mode, react-markdown renderer in view mode - **ChatPane.tsx**: Message history, input field, collapsible (stored width in localStorage) - **ActionBar.tsx**: Review button (research/plan phases), Submit button, token usage bar, permission mode toggle ### State Management App.tsx owns all state. Key state variables: - `selectedProject` / `selectedSession` — current context - `loadingBySession[sessionId]` — per-session loading flag (tracks thinking state) - `activityBySession[sessionId]` — per-session activity status text (e.g., "Using Bash (5s)") - `viewPhase` — which artifact to display (research/plan, defaults to current phase) - `chatWidth` / `chatCollapsed` — layout preferences (persisted to localStorage) - `theme` — "dark" or "light" (persisted to localStorage) ### Per-Session Activity Tracking App subscribes to `api.onClaudeMessage()` which broadcasts all Claude SDK messages to all sessions. App updates `loadingBySession` and `activityBySession` dictionaries to track which sessions are currently processing. This allows switching between projects/sessions without losing the thinking indicator state. ### UI Patterns & Conventions #### Modal/Overlay Pattern Full-page overlays (e.g., SettingsPage) use this pattern: ```tsx
{/* Header with close button */}
{/* Content */}
``` When building new modal UI: - Use `.settings-overlay` (or similar) class for backdrop + positioning - Include a close button with `className="settings-close"` - Keep header style consistent with app header height/styling - For simple modals (not full-page), consider a centered dialog box instead #### Form Pattern Settings sections use input/select fields. Standard patterns: - Label + input field pairs - Button groups for related actions - Consistent spacing via CSS grid/flex - Validation feedback via inline text or error states #### List/Tree Pattern Sidebar demonstrates tree structure for hierarchical data: - Parent items with click handlers and action buttons - Nested items with indent/visual hierarchy - Inline edit mode for renaming (Rename modal not needed) - Context awareness (expanded/collapsed states) ## Known Bugs ### Phase Handling Issues (Critical) #### Bug #1: New Session Phase Modal Doesn't Apply Selection **Status**: Needs debugging **Description**: When creating a new session and selecting "Implementation" in the phase modal, the session is created with "Research" phase instead of the selected phase. **Key Discovery**: The system prompt is determined directly by `session.phase` (src/main/claude/index.ts lines 49, 91, 120). - If you create an "Implement" session but Claude receives the **Research system prompt**, it PROVES the session.phase is stored as "research" in the database - This is the smoking gun that reveals Bug #1 is in the **data layer**, not the display **Observable symptom**: Create an "Implement" session and send a message. If Claude says "I am in RESEARCH mode" (contains "DO NOT modify any source code files"), the phase is wrong. If Claude says "I am in IMPLEMENTATION mode" (contains "Mark tasks complete"), the phase is correct. **Code path**: NewSessionModal → App.handleConfirmNewSession → api.createSession → IPC handler → createSession function → DB INSERT **Suspected issue**: Phase parameter may be lost or reset during IPC transmission, despite code appearing correct. The IPC handler receives `phase?: Phase` as optional parameter which defaults to "research" in createSession(). **To debug**: 1. Add console.log in NewSessionModal to confirm selected state 2. Add console.log in App.handleConfirmNewSession to confirm phase parameter 3. Add console.log in IPC handler to confirm phase is received 4. Check database directly: `SELECT phase FROM sessions WHERE ... LIMIT 1` 5. Check what system prompt Claude actually receives (see observable symptom above) **Related files**: - `renderer/src/components/NewSessionModal.tsx` (phase selection) - `src/main/preload.ts` (API bridge - lines 89-90) - `src/main/ipc/handlers.ts` (IPC handler - lines 26-37) - `src/main/db/sessions.ts` (createSession function - line 39) - `src/main/claude/index.ts` (system prompt application - lines 49, 91, 120) #### Bug #2: Phase Transition State Not Synced + plan.md Not Rendering **Status**: Root cause identified ✓ **Description**: After completing research phase and submitting, the plan phase doesn't show as active in the Sidebar, and plan.md doesn't display (only shows after Claude writes to it). **Root cause**: The `sessions` array state in App.tsx is never updated after `advancePhase()` completes. Only `selectedSession` is updated. This causes: 1. **Sidebar inconsistency**: Shows old phase (session object from stale sessions array) 2. **Header is correct**: Shows new phase (uses selectedSession.phase) 3. **plan.md might initially be blank**: Loads before Claude writes it (expected, but confusing) **The fix**: In `App.tsx` handleSubmit(), after successful advancePhase, also update the sessions array: ```typescript setSessions((prev) => prev.map((s) => (s.id === id ? { ...s, phase: advanced.phase, git_branch: advanced.git_branch } : s)) ); ``` **Related files**: - `renderer/src/App.tsx` (lines 419-446, handleSubmit function) - `renderer/src/components/Sidebar.tsx` (line 194, displays phase from sessions array) - `renderer/src/components/Header.tsx` (displays phase from selectedSession - works correctly) ## Important Notes - `ANTHROPIC_API_KEY` env var must be set before launching - Artifacts are stored in `.claude-flow/sessions/` inside the target project - `bypassPermissions` mode is a user-controlled toggle in implement phase only - Token usage (from `SDKResultMessage.usage`) is displayed in the ActionBar - No git library in dependencies — use Node.js `child_process` (built-in) for git operations - Session rename auto-triggers when research phase completes if session name is default "Session N" format (extracts first sentence from research.md) ## Extensibility Notes for UI Features When adding new UI features that require user input: 1. **Modal dialogs**: Follow the SettingsPage pattern (full-page overlay with header/body) 2. **Inline editing**: Use sidebar pattern (inline input that commits on blur/Enter) 3. **Phase selection**: Phase column in DB already exists and accepts any value—no schema changes needed to support starting at different phases 4. **Settings additions**: Add to `SettingsPage.tsx` with a new section and corresponding settings UI file in `/components/settings/` 5. **IPC endpoints**: Register in `/src/main/ipc/handlers.ts` and expose in `/src/main/preload.ts` 6. **State management**: Keep state in `App.tsx` for global UI state; component local state for transient UI state (e.g., modal visibility, form input) **State sync pattern**: When updating sessions in bulk operations (like phase transitions), remember to update BOTH `selectedSession` AND `sessions` array to keep UI consistent across all components.