aboutsummaryrefslogtreecommitdiffstats
path: root/CLAUDE.md
blob: 5d256562987c7092bb80b28723ababb40750e4f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# 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
<div className="settings-overlay">
  <div className="settings-header">
    {/* Header with close button */}
  </div>
  <div className="settings-body">
    {/* Content */}
  </div>
</div>
```

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)

## 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)