A Granola.ai-inspired desktop app for AI-powered meeting notes. Captures system audio, lets you take freeform notes in real time, then uses Claude to merge your jots with the transcript into polished structured notes.
| Layer | Technology |
|---|---|
| Desktop shell | Electron 29 |
| UI | React 19 + TypeScript + Tailwind CSS |
| Transcription | OpenAI Whisper API |
| Note enhancement & chat | Anthropic Claude (claude-sonnet-4-20250514) |
| Local storage | SQLite via better-sqlite3 |
| Settings | electron-store |
- Live recording — captures system audio via
desktopCapturer/getDisplayMedia - Freeform note-taking — distraction-free editor with auto-save every 5 seconds
- AI transcription — sends audio to Whisper API after meeting ends
- AI note enhancement — Claude merges raw notes + transcript using your chosen template
- 6 built-in templates — Default, Customer Discovery, 1-on-1, User Interview, Standup, Pitch
- Custom templates — create your own with named sections
- AI chat panel — ask Claude anything about the meeting (streaming)
- Export — copy as Markdown, plain text, Slack format, or export
.mdfile - Follow-up email — Claude drafts a follow-up email in one click
- Meeting metadata — editable title, attendees, tags, auto-generated title from transcript
# Install dependencies
npm install
# Add your API keys in Settings (gear icon)
# - Anthropic API key (for Claude)
# - OpenAI API key (for Whisper transcription)
# Development mode
npm run dev # Start renderer (Vite) + watch main process
# In a separate terminal:
npm run electron:dev # Launch Electron pointing at localhost:5173
# Production build
npm run build # Build both renderer and main
npm run electron # Launch the built appsrc/
├── main/ # Electron main process
│ ├── main.ts # App entry, BrowserWindow setup
│ ├── preload.ts # Context bridge (IPC exposure to renderer)
│ ├── database.ts # SQLite schema, queries
│ ├── ipc.ts # IPC handler registration
│ └── ai.ts # Whisper transcription, Claude streaming
├── renderer/ # React UI
│ ├── App.tsx # Root component, data loading
│ ├── components/
│ │ ├── Sidebar.tsx # Meeting list + search
│ │ ├── MeetingView.tsx # Main meeting panel (notes/enhanced/transcript/chat tabs)
│ │ ├── NoteEditor.tsx # Textarea editor + Markdown viewer
│ │ ├── ChatPanel.tsx # AI chat with streaming
│ │ ├── RecordingStatusBar.tsx
│ │ ├── SettingsModal.tsx # API keys, theme, templates
│ │ └── NewMeetingModal.tsx # New meeting setup
│ ├── store/
│ │ └── appStore.ts # Zustand global state
│ ├── hooks/
│ │ └── useAudioRecorder.ts # MediaRecorder wrapper
│ └── utils/
│ └── date.ts # Date formatting helpers
└── shared/
└── types.ts # Shared TypeScript types + IPC channel names
| Table | Purpose |
|---|---|
meetings |
id, title, dates, attendees, template, tags, status |
notes |
raw_content, enhanced_content, transcript per meeting |
chat_messages |
Chat history per meeting |
templates |
Built-in + custom note templates |
MIT