diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..67a5ede --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,59 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Hohoff Editor — an Electron desktop app for novel editing with AI-powered writing analysis. Built with React 18, TypeScript, CodeMirror 6, and Zustand. Uses the Anthropic Claude API for chat and text analysis features. + +## Commands + +- `npm run dev` — Start Electron dev server with hot reload +- `npm run build` — Production build (outputs to `out/`) +- `npm run typecheck` — Type-check both Node and browser TypeScript configs +- `npm run preview` — Preview production build + +No test runner or linter is configured. + +## Architecture + +**Electron three-process model:** + +- **Main process** (`src/main/`) — Node.js environment. Handles file I/O (`fileSystem.ts`), Claude API streaming (`aiService.ts`), and IPC handlers (`ipcHandlers.ts`). +- **Preload** (`src/preload/index.ts`) — Bridges main↔renderer via `contextBridge`. Exposes `window.api.*` methods. +- **Renderer** (`src/renderer/`) — React app with CodeMirror editor. All file/AI operations go through `window.api.*` IPC calls, never direct Node access. + +**State management:** Single Zustand store (`src/renderer/store/editorStore.ts`) holds all app state — active file, chat history (per-file), annotations (per-file), UI preferences. State auto-persists to `.session.json` in the draft directory with 1500ms debounce. + +**Key renderer components:** + +| Directory | Purpose | +|-----------|---------| +| `components/Editor/` | CodeMirror 6 markdown editor with custom annotation decorations and theme compartments | +| `components/AIChat/` | Streaming chat interface, per-file conversation history, attachment support (images/PDF/text) | +| `components/Feedback/` | AI annotation panel — highlights parsed from AI responses, hover tooltips, one-click apply | +| `components/FileTree/` | Drag-and-drop file navigation with custom ordering (`.order.json`) | +| `components/Revisions/` | Version history with word count tracking, stored in `.revisions/` directory | +| `components/Toolbar/` | Analysis mode triggers (passive voice, consistency, style, critique) | + +## Key Patterns + +**IPC flow:** Renderer calls `window.api.method()` → preload forwards via `ipcRenderer.invoke()` → main process handler in `ipcHandlers.ts` executes and returns result. AI streaming uses event-based IPC (`ai:chunk` events). + +**CodeMirror annotations:** Custom `StateField` tracks annotation positions. Positions are remapped through document changes via `tr.changes.mapPos()`. Annotations auto-dismiss 1.2s after the user edits the annotated region. Apply/dismiss actions integrate with CodeMirror undo history via `invertedEffects`. + +**Annotation parsing** (`src/renderer/utils/annotationParser.ts`): AI responses are parsed for quoted text, which is matched against document content (exact match first, then normalized whitespace fallback). Each quote becomes a positioned annotation with type, message, and optional suggestion. + +**Path alias:** `@renderer/*` resolves to `src/renderer/*` (configured in both Vite and tsconfig.web.json). + +## Environment + +Requires `.env.local` in project root with: +- `ANTHROPIC_API_KEY` — Claude API key +- `DRAFT_PATH` — Absolute path to the directory containing markdown draft files + +## TypeScript Configuration + +Two separate tsconfig files referenced from root `tsconfig.json`: +- `tsconfig.node.json` — Main and preload processes (Node.js environment) +- `tsconfig.web.json` — Renderer process (browser environment, has `@renderer/*` path alias)