Notee: my own Markdown editor for macOS

A native Markdown editor that keeps my VS Code shortcuts, opens a note in 20 ms and runs 4 windows in 119 MB. Built with Claude Code in 21 prompts over a weekend.

Notee is my own Markdown editor for macOS. It replaces VS Code for my notes, and only for my notes. It keeps the VS Code shortcuts my fingers know, opens each workspace in its own colour-coded window, and does it with a fraction of the memory.

The name follows the -ee family of my other tools (Dictee: my own local dictation app, Stickee: sticky notes that go full screen on every monitor). The story of why I built it is in The era of personal software is here. This note is the what and the how.

Notee with an orange workspace: Open Editors and the file tree in the sidebar, 5 tabs, and a Markdown note with coloured headings, a table and a to-do list

Why I built it

My notes moved to Markdown about 4 years ago, and I've edited them in VS Code ever since. The shortcuts, the snippets and the file navigation are muscle memory now. But VS Code is a coding environment. On the day I measured it, it used 4,013 MB across 31 processes.

The alternatives didn't fit either:

  • Obsidian: I recommend it to non-technical people, but its UI and its shortcuts don't fit how I work.
  • CotEditor: fast and native, but too basic for my workflows.

What I wanted: a Markdown app that I control and change whenever I need, with my VS Code keys and my colour-coded workspaces.

What it does

Feature How it works
Workspace windows 1 window per folder, each in its own colour, all restored at launch. ⌘` cycles them
VS Code keys My shortcuts, read from a VS Code-format keybindings.json that reloads live
⌘K command center Every shortcut in 1 searchable list, grouped like the menu bar
Quick open ⌘P lists the notes I touched last, newest first, before I type anything
Open Editors The open tabs above the file tree, with a count. The list pushes the tree down
Find in files ripgrep under the hood, results stream in as they're found
Editor Multi-cursor, line moves, folding, regex find, my VS Code snippets with tab stops
Properties panel The YAML or Pelican front matter as editable fields above the note
Markdown preview ⇧⌘V, side by side, scroll-synced. Notes for this site render with the site's own CSS
Copy for email A copy icon next to each heading copies that section, formatted for Outlook
Auto-save and safety Saves after 1.5 s, warns if the file changed on disk, shows a diff before overwriting

Notee with the Markdown preview open beside the editor: the same note rendered with red heading markers, tag pills and a table

A few details I care about:

  • Every file opened in Finder lands in the right window. Notee reads the path and routes the note to the matching workspace.
  • Copy for email keeps the blank lines. Outlook drops CSS margins, so a normal copy from a web view pasted as 1 block of text. Notee writes its own HTML with inline styles and real empty lines.
  • The sidebar follows the zoom. ⌘+ and ⌘- scale the editor, the preview and the sidebar lists together. ⌘0 resets.

Speed and memory

Speed came first, memory second. Every feature that costs either loads only when I use it. The QA script measured these on 10th October:

Measure Budget Measured
Launch to the first window < 400 ms 204 ms
Open a typical note < 30 ms 20 ms
Open my largest note (12.8 MB) < 1 s 360 ms
Keystroke to screen < 10 ms 0.8 ms (8 ms in the 12.8 MB note)
Quick open over 70,344 files < 16 ms 7 ms
Find in files, notes folder < 2 s 0.15 s
4 workspace windows, idle < 250 MB 119 MB

119 MB against VS Code's 4,013 MB isn't a fair fight: that VS Code figure includes Python tooling, Claude Code and terminals. It's still the number Notee replaces.

For business people

Notee is a tool built for 1 user. It does what I need for notes and nothing else, so it stays fast and small.

The value isn't the editor itself. It's that the editor changes when I want it to. When something bothers me, I tell Claude Code, and a few minutes later the change is built, tested and installed. In 2 days of use I sent 16 prompts of changes and questions, from a command center to a copy button for Outlook.

The trade-off: I maintain it. It runs on my Mac only, and there's no support team behind it.

For technical people

Stack

Layer Choice Why
Language and UI Swift 6 and AppKit Native, compiled, the lightest UI layer on macOS
Text engine NSTextView on TextKit 1 Proven on very large files. 1 buffer feeds many views
File tree View-based NSOutlineView, lazy children Loads a folder only when it opens
Syntax colours Own incremental tokenizer, visible range only No parser dependency, tiny cost per keystroke
Markdown to HTML swift-cmark, Apple's GFM fork of cmark Renders a long note in under 1 ms
Preview 1 WKWebView per window, created on demand WebKit memory only while the preview is open
Find in files Bundled ripgrep, streamed JSON No index in memory when idle
File watching 1 FSEvents stream per workspace Kernel-level, near zero cost
Config Plain JSON in ~/.notee/, reloaded live I, or Claude, can edit it
Shared logic Swift package NoteeCore Ready for an iOS app later

I rejected Electron and Tauri (the reason VS Code is heavy), CodeMirror in a web view (each web view starts its own WebKit process, about 50-100 MB) and TextKit 2 (reported scroll jumps on large files).

The code: about 10,100 lines of Swift, 240 lines of JavaScript for the preview, 37 unit tests and an end-to-end QA script with 129 checks.

How the QA works

The QA script never touches my real notes. It builds copies in a temp folder, launches Notee in the background with a JSON script of steps (open, type, press keys, take a screenshot, record the state), and checks the report. A read-only flag blocks every write for runs against the real folders.

Gotchas I hit

  • TextKit 1 over TextKit 2. TextKit 1 lets the same note, open in 2 windows, share 1 buffer instead of 2 copies.
  • Symlinked paths. macOS reports /private/var/... for a path that also reads /var/.... Renames, moves and file events only match after both go through realpath.
  • Ad hoc code signing. An ad hoc signature changes with every build, so macOS treated each build as a new app and asked again for permissions it already had. Signing with a Developer ID fixed it.
  • Highlighting during load. Colouring a 12.8 MB note while it loaded took 4 s. Notee now skips it during load and colours only what's on screen.
  • Background reads of the text. Reading the live text storage while I typed crashed Notee. Background work now reads a copy.
  • A view controller as the window content made the window shrink to its smallest size. Notee lays out the window by hand.

The Notee app icon: the white hexagon edelweiss logo on a black square, with the name Notee under it

How I got there: 21 prompts

I built Notee in 1 session with Claude Code, from Friday evening to Sunday evening. I wrote 21 prompts.

Phase Prompts What happened
Brief and spec 2 Claude read my VS Code setup and asked 24 questions. I answered in 1 prompt
Build 1 "Build it and don't stop until you have a working, QA'ed version"
Status checks 2 "status?"
Changes from use 16 Command center, recent notes in ⌘P, copy for email, Open Editors, fixes

What worked well:

  • Spec before code. The first prompt said "don't build anything yet". The questions surfaced choices I hadn't thought about: auto-save, conflicts with Dropbox and Claude editing the same file, which Markdown rules apply where.
  • 2 goals, in order. Speed first, memory second. Every design choice in the spec traces back to them.
  • Safety as a hard rule. My notes must never be damaged. A separate review of the save paths found 9 data-safety issues before I used the app, including a properties field that could write into the wrong note.
  • Use it, then ask. Most of the 16 changes came from friction in daily use, not from the spec.

Further reading

The open-source parts inside Notee:

NicAI
Written by NicAI, Nic's AI assistant, for his personal knowledge base. Researched and drafted by the model, not hand-written by Nic. Verify anything you plan to act on.