Skip to content
Agentmart
Submit a tool

CLAUDE.md · Foundry376/Mailspring

CLAUDE.md from Foundry376/Mailspring: 234 lines covering Build and Development Commands, Architecture Overview, Core Data Flow: Sync Engine, Tasks, and…

Template by Foundry376

IndexedGPL-3.0★ 17,938
Write a review

Install

Works with Claude Code. Read the repository before you give any tool access to your data.

curl -fsSL https://raw.githubusercontent.com/Foundry376/Mailspring/master/CLAUDE.md -o CLAUDE.md

Read it and adapt it to your project before use.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

The CLAUDE.md file that Foundry376/Mailspring (17,939 stars) keeps for coding agents. It has 234 lines in 6 sections: Build and Development Commands; Architecture Overview; Core Data Flow: Sync Engine, Tasks, and Observable Database; Comment Style; Development Notes; Claude Hooks. Use it as a model for your own project's instructions.

Use cases: code-generation

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

What's in it

A CLAUDE.md file: project memory Claude Code loads at the start of every session.

For
Claude Code
Length
234 lines
File
CLAUDE.md

Sections

  1. Build and Development Commands
  2. Architecture Overview
  3. Core Data Flow: Sync Engine, Tasks, and Observable Database
  4. Comment Style
  5. Development Notes
  6. Claude Hooks

First lines (shown under the repo's GPL-3.0 license)

# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Build and Development Commands

```bash
# Install dependencies
npm install

# Run the app in development mode (uses --dev flag, data stored in Mailspring-dev folder)
npm start

# Run linting (prettier runs as an eslint rule); lint:check reports without fixing
npm run lint
npm run lint:check

# TypeScript type checking
npm run typecheck

# Run all tests, or only spec files whose path matches a regex
npm test
npm test -- --spec-file-pattern='calendar'

# Run window-specific tests
npm run test-window

# Run Playwright end-to-end tests
npm run test:e2e

# TypeScript type checking in watch mode
npm run tsc-watch

# Build for production
npm run build
```

## Architecture Overview

Mailspring is an Electron-based email client written in TypeScript with React. It uses a plugin architecture where features are implemented as internal packages.

### Key Directories

- **`app/src/`** - Core application source code
  - `browser/` - Main process code (application lifecycle, window management, auto-updates)
  - `flux/` - Flux-based state management (actions, stores, models, tasks)
  - `components/` - Reusable React UI components
  - `services/` - Application services (search, sanitization, etc.)
  - `registries/` - Extension registries (components, extensions, database objects)
  - `global/` - Global exports (`mailspring-exports`, `mailspring-component-kit`)

- **`app/internal_packages/`** - Built-in plugins implementing features (composer, message-list, thread-list, preferences, themes, etc.)

> **IMPORTANT:** Application source code lives in **both** `app/src/` and `app/internal_packages/`. When searching for usages of a module, symbol, or pattern, always search both directories. Searching only `app/src/` will miss a large portion of the codebase and lead to incomplete changes.

- **`app/spec/`** - Jasmine test specs

### Core Modules

**Global exports for plugins:**
- `mailspring-exports` - Core APIs: Actions, Stores, Models, Tasks, Utils, database access
- `mailspring-component-kit` - Reusable UI components

**Flux Architecture:**
- **Models** (`flux/models/`) - Data models: Message, Thread, Contact, Account, Folder, Label, etc.
- **Stores** (`flux/stores/`) - Application state: DatabaseStore, DraftStore, AccountStore, etc.
- **Tasks** (`flux/tasks/`) - Async operations: SendDraftTask, ChangeFolderTask, etc.
- **Actions** (`flux/actions.ts`) - Application-wide action dispatcher

### Plugin Structure

Each plugin in `internal_packages/` has:
- `package.json` - Metadata with `windowTypes` specifying where plugin loads
- `lib/main.ts` - Entry point with `activate()` and `deactivate()` lifecycle hooks
- `lib/` - Plugin source code
- `styles/` - LESS stylesheets
- `keymaps/` - Keyboard shortcut definitions

## Core Data Flow: Sync Engine, Tasks, and Observable Database

**Important:** The UI is read-only with respect to the database. All database modifications happen in the C++ sync engine (Mailspring-Sync). The Electron app requests changes via Tasks, and the sync engine streams entity changes back to create a real-time UI.

### Sync Engine Communication (`mailsync-process.ts`, `mailsync-bridge.ts`)

The sync engine is a separate C++ process spawned per account:

1. **Electron → Sync Engine**: JSON messages sent via stdin (task requests, commands)
2. **Sync Engine → Electron**: Newline-delimited JSON streamed via stdout (database change deltas)

```
┌─────────────────┐         stdin (JSON)          ┌──────────────────┐
│   Electron UI   │ ──────────────────────────────▶│  Mailspring-Sync │
│  (TypeScript)   │                                │      (C++)       │
│                 │ ◀────────────────────────────── │                  │
└─────────────────┘    stdout (JSON deltas)        └──────────────────┘
```

The `MailsyncBridge` (in main window only) manages sync process lifecycle, listens to `Actions.queueTask`, and forwards tasks to the appropriate account's sync process.

### Task System (`flux/tasks/`)

Tasks represent operations the user wants to perform (send email, star thread, move to folder). They are **persisted models** stored in the database.

**Task Lifecycle:**
1. UI calls `Actions.queueTask(new SomeTask({...}))`
2. `MailsyncBridge._onQueueTask()` validates and sends to sync engine via stdin
3. Sync engine executes the task (local changes + remote API calls)
4. Sync engine persists task status updates and emits deltas
5. Task completion triggers `onSuccess()` or `onError()` callbacks

**Task States** (`flux/tasks/task.ts`):
- `local` - Not yet executed
- `remote` - Local phase complete, waiting for remote
- `complete` - Finished successfully
- `cancelled` - Cancelled before completion

**Key Task Classes:**
- `SendDraftTask`, `DestroyDraftTask` - Email composition
- `ChangeLabelsTask`, `ChangeFolderTask` - Organization
- `ChangeStarredTask`, `ChangeUnreadTask` - Status flags
- `SyncbackMetadataTask` - Plugin metadata sync
- `SyncbackEventTask` - Calendar event sync

**Undoable Tasks:**

Tasks can support undo/redo by implementing `canBeUndone` and `createUndoTask()`. The `UndoRedoStore` automatically registers tasks with `canBeUndone = true` for undo.

Two patterns exist:
1. **Toggle pattern** (`ChangeStarredTask`): Undo simply flips a boolean flag
2. **Snapshot pattern** (`SyncbackMetadataTask`, `SyncbackEventTask`): Store original state in `undoData`, swap on undo

```typescript
// Snapshot pattern example
const undoData = { ics: event.ics, recurrenceStart: event.recurrenceStart };
event.ics = newIcs;  // Modify after capturing
Actions.queueTask(SyncbackEventTask.forUpdating({ event, undoData, description: 'Edit event' }));
```

See `docs/undo-redo-task-pattern.md` for detailed implementation guide.

### Task Queue (`flux/stores/task-queue.ts`)

The TaskQueue store observes Task model changes from the database and provides:
- `queue()` - Active tasks
- `completed()` - Finished tasks
- `waitForPerformLocal(task)` - Promise that resolves when task runs locally
- `waitForPerformRemote(task)` - Promise that resolves when task fully completes

### Observable Database Pattern

**Database is read-only in Electron** (`flux/stores/database-store.ts`):
- `DatabaseStore.inTransaction()` throws - writes are not allowed
- Uses SQLite in WAL mode via better-sqlite3 for concurrent reads
- The sync engine exclusively handles writes

**Change Records** (`flux/stores/database-change-record.ts`):

When the sync engine modifies data, it emits JSON deltas that become `DatabaseChangeRecord` objects:
```typescript
{

Signals

Stars
17,938
Forks
1,064
Open issues
5
Last commit (this folder)
Oct 7, 2026 (22 days ago)
Last release
Oct 22, 2026 (7 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
GPL-3.0
First seen
Oct 24, 2026
Last checked
Oct 24, 2026
Cite this page

CLAUDE.md · Foundry376/Mailspring. Agent Mart. https://agentmart.dev/templates/foundry376-mailspring-claude-md (last updated 2026-10-24)