Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

224 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cinder

CI

A local-first macOS notes-and-todos app. Markdown notes with WYSIWYG editing, a Todoist-equivalent todo system, and an Eisenhower matrix view — all in a hardened Electron shell.

Status: feature-complete and shipping. Download the latest signed and notarised DMG from Releases, or see Development to run locally.


Why another notes app

Most notes-and-todos products require you to send your content to someone else's server. Cinder is built on the opposite premise:

  • Local-first. All your notes and tasks live in an encrypted SQLite database on your own machine. There is no account to sign up for and no server to talk to.
  • Security as a foundation, not a feature. Every renderer is sandboxed, every IPC channel is validated, the database is encrypted at rest with a key stored only in the macOS Keychain. The full security model is documented in ARCHITECTURE.md §3.
  • Designed for sync, shipping without it. v1 has no cloud sync — sync is where security architectures usually collapse. The data model (UUIDv7 IDs, updated_at, soft deletes) is sync-friendly, so when sync arrives it will be CRDT-based with end-to-end encryption rather than naïve REST.

What works today

Notes

  • WYSIWYG Markdown editor via TipTap (ProseMirror) with full keyboard support
  • Autosave with a 500 ms debounce and explicit ⌘S flush
  • Full-text search across titles and bodies (SQLite FTS5), plus a ⌘F find-in-note bar that highlights matches and steps through them inside the editor
  • Local attachments served via a custom attachment:// protocol, pasted or dragged in
  • Wiki links — type [[Note Title]] to create clickable inter-note links; clicking navigates to the target note or creates it on the fly
  • Project membership — file a note under a project (the same projects that group tasks), so a project gathers both its notes and its tasks in one place
  • Note ↔ task links — link a note to related tasks (and vice versa) and jump between them in either direction
  • Drag-and-drop import — drop .md, .markdown, .html, or .htm files directly into the sidebar or the empty state; HTML is converted to Markdown automatically via Turndown
  • Export — export any note as a self-contained .md file (images, including live drawing embeds, are inlined as data URIs so the file is portable outside the app), or as Word (.docx) or PDF; export all notes to a folder in any of those formats, via a native Save dialog

Daily Notes

  • One note per calendar day, auto-created on first access — no setup required
  • Today → shortcut in the sidebar always opens the current day's note
  • Collapsible year → month → day tree shows every day you've written; navigate with a single click
  • Fully integrated — daily notes support attachments, the triage "+ Todo" button, FTS5 search, and Markdown export; they're invisible in the main Notes list to keep both areas clean
  • Markdown template — configure a reusable template (e.g. ## Goals / ## Journal / ## Gratitude) in Settings → Daily Notes; applied to every new daily note

Draw

  • Freehand sketches and diagrams on an embedded Excalidraw canvas — rectangles, ellipses, arrows, lines, freehand strokes, and text
  • Its own mode with a sidebar list of drawings; create, rename, and delete from there
  • Embed into notes — insert a drawing into a note as a live embed (always shows the drawing's current state; double-click to edit) or a static snapshot PNG; copy & paste shapes straight from a drawing also works
  • Autosave of the scene as you work; text inside a drawing is included in full-text search
  • Fully local and offline — fonts and assets are self-hosted (no CDN), drawings live in the encrypted database, and the renderer stays sandboxed under the same strict CSP (no unsafe-eval)

Tasks

  • Full task CRUD with title, description, priority (P1–P4), due date, and project assignment
  • Projects and sections — hierarchical organisation with manual ordering; projects span both tasks and notes, and the project view lists its notes alongside its tasks
  • Labels — cross-cutting tags, multiple per task
  • Recurring tasks using RFC 5545 RRULE strings; completing a recurring task advances the due date automatically
  • Saved filters with a typed DSL (today & p1, @work & overdue, !done & upcoming)
  • Natural-language quick-add — type "Submit report tomorrow at 5pm p1 @work" and the parser extracts due date, priority, and labels
  • Inline editing — double-click any task title, or press e, to edit title and description in place
  • Views — Inbox (no project), Today (due today or overdue), Upcoming (future due dates), per-project, per-label, saved filter
  • Export tasks as CSV with project, label, priority, and date columns

Eisenhower Matrix

  • 2×2 quadrant view classifying all active tasks by urgency (due date window) and importance (priority cutoff) — both configurable
  • Drag tasks between quadrants to update their priority and due date in a single drop; diagonal moves prompt for confirmation
  • Snapshot mode — freeze the current layout to compare against a live view
  • Task detail panel — click any card to open an inline editor for all fields
  • Project and label filters — scope the matrix to a specific project or label

Vault Import

  • Obsidian vault import — scan-then-preview-then-import flow; supports regular notes, daily notes (date detection by path), wiki-link conversion, and folder-prefix title strategies
  • Attachment import![[embeds]] are resolved against vault files, copied to Cinder's attachment storage, and converted to attachment:// URLs; toggleable checkbox in the preview modal
  • Unrecognised or missing attachments are left as ![[…]] in the body for manual follow-up

⌘K Command Palette

  • Fuzzy-match search across all navigation targets, task scopes, projects, labels, saved filters, and actions
  • Navigate to Notes, Tasks, Matrix, or Daily; jump to any project or label; create notes; open Help, Settings, or trigger exports — all from the keyboard

Collapsible sidebar

  • Hide the left nav panel with ⌘, the ⇤/⇥ button at the far left of the toolbar, or the "Hide/Show sidebar" command in the ⌘K palette
  • Gives the editor (or any mode's main pane) the full window width — good for distraction-free writing and for hiding your document list when screen-sharing on a call

⌘⇧F Search everything

  • Application-wide content search across every note (regular, daily, drawings, imported HTML) and every task — including completed and triage tasks — from one overlay
  • Matching text is highlighted in the results; selecting one jumps straight to it in the right mode (Notes, Daily, Draw, or the task's project/Inbox/Triage view)
  • Distinct from the ⌘K palette (which navigates) and the Notes-sidebar box (which filters the current folder)

Connect to Claude (MCP connector)

  • Local Model Context Protocol server lets Claude (Desktop) connect to Cinder as a custom connector and work with your notes and tasks
  • Local-first and private — the server runs inside Cinder, binds to 127.0.0.1 only, requires a secret bearer token, and runs only while the app is open; it is off by default
  • Read by default, write on request — Claude can search and read notes, daily notes, tasks, projects, folders, and labels out of the box; creating/updating notes and capturing tasks is gated behind an Allow writes toggle, and captured tasks land in the Triage queue
  • Notes as @-mentions via MCP resources, plus ready-made prompts (Triage my inbox, Summarize today, Weekly review)
  • Audit log in Settings → Connectors shows every action Claude takes, and the token can be rotated at any time

Settings

  • Persistent preferences stored in the encrypted database
  • Appearance: Auto / Light / Dark theme with live system-preference tracking
  • Matrix: urgency window (days ahead that count as urgent) and importance cutoff (which priorities are "important")
  • Tasks: default scope on startup (Inbox / Today / Upcoming), show-completed toggle
  • Notifications: enable or disable due-task macOS alerts
  • Connectors: enable the Claude connector, copy the connection URL/token, toggle write access, rotate the token, and review the activity log
  • Changes take effect immediately; matrix updates live while the panel is open
  • Open with ⌘, or the ⚙ button in the toolbar

Export & Backup

  • Export any single note as .md, .docx (Word), or .pdf
  • Export all notes to a folder in any of those formats (collision-safe filenames)
  • Export all tasks as .csv (includes project, labels, priority, recurrence, dates)
  • Full database backup as a .db snapshot
  • All operations use native macOS Save/Open dialogs — the app never touches arbitrary file paths

Triage queue

  • "+ Todo" button in Notes, Daily, Tasks, and Matrix headers captures a task without breaking your flow — the task is held in a Triage queue rather than going straight to Inbox
  • ⌘⇧Space global shortcut opens a lightweight capture popup from the macOS menu-bar tray icon, even when Cinder is in the background
  • Each triage task is shown as a card with inline editing for title, description, priority, due date, and project; captured-from-note tasks show a clickable backlink to the source note
  • Acknowledge promotes the task into normal flow (Inbox or its assigned project) in one click; Discard hard-deletes noise captures
  • Normal views (Inbox, Today, Matrix, filters) stay clean — triage tasks are invisible until acknowledged

Due-task notifications

  • macOS native notifications for tasks due today and overdue tasks, checked every 15 minutes
  • Clicking a notification brings Cinder to the front and navigates to Tasks › Today
  • Toggled in Settings › Notifications (on by default)

Auto-update

  • Checks for updates automatically 10 seconds after launch (production builds only)
  • Downloads in the background without interrupting work
  • Slim banner appears when a download is in progress or an update is ready to install
  • "Restart to apply" one-click install; "Check for updates" also available in Settings and the command palette

Help & Feedback

  • Full in-app documentation covering every feature, searchable by keyword
  • Open with ⌘/ or the ? button; navigate sections with the keyboard
  • Feedback & Support section links directly to GitHub Issues — report a bug or request a feature without leaving the app

Accessibility

  • Focus is trapped inside all modals and returned to the opener on close
  • Skip-to-main-content link for keyboard users
  • ARIA landmarks, roles, and labels throughout (combobox, listbox, activedescendant, switch, region, list, current)
  • All interactive elements reachable and operable by keyboard alone

Tech stack

Concern Choice
Shell Electron 42 (hardened runtime, sandboxed renderer)
UI React 18, Tailwind CSS
State Zustand (UI state), TanStack Query (server/IPC state)
Build electron-vite + Vite + TypeScript (strict + noUncheckedIndexedAccess, exactOptionalPropertyTypes)
Database SQLite (SQLCipher, AES-256) via @journeyapps/sqlcipher — see ADR-0001
ORM Drizzle (via sqlite-proxy adapter)
Editor TipTap (ProseMirror)
Validation Zod (schemas shared between main and renderer)
NLP chrono-node (date parsing in quick-add)
Recurrence rrule (RFC 5545 RRULE generation and advancement)
HTML import Turndown (HTML → Markdown, sandboxed renderer, no Node required)
Auto-update electron-updater (GitHub Releases)
Tests Vitest, fast-check (property tests)

Development

Prerequisites

  • macOS (arm64 or x64)
  • Node 24 (nvm use 24) — Electron 42 requires Node ≥ 22.12 at build time
  • Python 3 (for occasional native-module rebuilds)

Setup

git clone https://github.com/<your-fork>/cinder.git
cd cinder
npm ci

npm ci runs electron-rebuild automatically (via postinstall), which compiles @journeyapps/sqlcipher against Electron's bundled Node headers.

Scripts

Command What it does
npm run dev Start the electron-vite dev server and launch the Electron app with HMR
npm run build Production build (main, preload, renderer) — does not sign
npm run typecheck tsc --noEmit against both the main and renderer tsconfigs
npm run lint ESLint flat config (security rules + TypeScript rules)
npm test Vitest unit tests (335 tests across 18 suites)
npm run smoke Build + launch the real app (Playwright/_electron) and assert it boots, the DB initialises, and a notes IPC round-trip works — catches runtime/packaging regressions unit tests can't
npm run release Production build + electron-builder publish to GitHub Releases (requires GH_TOKEN)

For the signed and notarised release build pipeline, see the workflow files in .github/workflows/.


Project layout

src/
  main/                     # Electron main process — trusted
    db/                     # schema, migrations, Drizzle wrapper
    ipc/                    # one file per domain (notes, tasks, export, settings, update, …)
    security/               # CSP, IPC sender verification, openExternal allow-list
    services/               # business logic
  preload/                  # contextBridge surface — the only path renderer → main
  renderer/                 # React app — sandboxed, no Node access
    features/               # notes/, tasks/, matrix/, export/, settings/, update/, …
    components/             # shared UI primitives (Toast, …)
    hooks/                  # useFocusTrap, useDebouncedCallback, …
    state/                  # Zustand stores
  shared/                   # framework-free; imported by both sides
    ipc/                    # channel name constants
    schemas/                # Zod input/output schemas
    matrix/                 # Eisenhower classification logic (pure, tested)
    filter/                 # DSL lexer, parser, compiler (pure, tested)
    recurrence/             # RRULE advancement helpers (pure, tested)
docs/
  adr/                      # Architecture Decision Records
ARCHITECTURE.md             # authoritative spec
CLAUDE.md                   # conventions and security rules for contributors

Security

The renderer is treated as hostile. Every IPC channel is a public API and validated as such. The headline rules — all enforced either by ESLint or by Electron itself:

  • sandbox: true, contextIsolation: true, nodeIntegration: false, webviewTag: false
  • CSP set via response headers (not <meta> tags)
  • Every IPC payload validated with Zod before reaching business logic
  • assertMainFrame() check on every handler
  • shell.openExternal gated behind an https:-only allow-list
  • eval, new Function, dangerouslySetInnerHTML (outside the sanitisation wrapper), and Node built-ins in renderer code all rejected at lint time
  • All file I/O (export, backup, attachment save) happens in the main process via native dialogs — the renderer never supplies or receives raw file paths

The full model is in ARCHITECTURE.md §3.

If you find a security issue, please report it privately via SECURITY.md rather than opening a public issue.


License

MIT.

About

Note taking and todo list manager

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages