Textee: my own text editor for macOS

A native text editor that replaces TextMate as my clipboard scratchpad. Against TextMate, CotEditor, Sublime Text and TextEdit, it wins 12 of 16 speed and memory measures.

The Textee app icon: the hexagon edelweiss logo on a blue gradient square, with the name Textee under it

12 Oct 2026

Textee is my own text editor for macOS. It replaces TextMate, and its main job is the clipboard scratchpad: I type ca in Alfred, and the clipboard lands in a new text file, in a Textee tab, a fraction of a second later.

It's the sibling of Notee: my own Markdown editor for macOS, which replaced VS Code for my Markdown notes. Same family of -ee apps, same way of building them (The era of personal software is here), but no shared code: each app is optimised for its 1 job.

The code is public on GitHub: ndeville/textee, under the MIT licence. Anyone with a Mac and Xcode can build it.

Textee with 3 tabs and a Markdown file open: orange heading, yellow bold text, green code block, line numbers on the left and a blue status bar with line, word and character counts

Why I built it

Before writing a line of code, Claude analysed how I actually used TextMate. The answer surprised me: TextMate was mostly a clipboard dump.

  • The Alfred keyword ca wrote the clipboard to ~/txt/YYMMDD-HHMMSS.txt and opened it in TextMate. That folder held 3,144 files since April 2025, about 8 a day.
  • 95% of those files never changed after the first hour. Read once, keep for search.
  • 24% contained Markdown, mostly LLM answers I pasted to read or edit.
  • I had 2 workarounds for things TextMate didn't do: a rebound word count command, and a Hammerspoon overlay that drew a character count on the TextMate status bar every 0.5 s.
  • TextMate's Edit > Paste is a submenu, which broke my global Copy (⌘D) and Paste (⌘F) remaps.

TextMate is still a good, native editor (TextMate). But development has slowed, and I wanted the scratchpad to work exactly the way I use it.

What it does

The full list, as of 15th October.

Scratchpad

Feature How it works
Clipboard scratch ca in Alfred (or ⇧⌘N) writes the clipboard to ~/txt/YYMMDD-HHMMSS.txt and opens it in a tab
New scratch file ⌘N creates an empty timestamped file. If it's still empty when I close the tab, it's gone
Auto-save 1 s after I stop typing, on a tab switch, when I switch apps and on quit. No Save dialog
Tabs 1 window, 1 tab per file. Each tab keeps its own editor, so switching is instant
Counts Line and column, lines, words and characters, and the same for the selection
LinkedIn count Green up to 300 characters (an invitation note), amber over 3,000 (the post limit)

Editing

Feature How it works
Multiple cursors ⌥↩ adds the next match, ⇧⌘A selects every match, ⌥-click adds a cursor, Esc goes back to 1
Line commands ⌘T duplicates, ⌥D deletes the line (as in VS Code), ⌥↑ and ⌥↓ move it, ⌘] and ⌘[ indent
Plain text Copy and paste carry no formatting. 3 cursors and 3 lines on the clipboard: 1 line per cursor
Indentation Return keeps the indent. Tab inserts 4 spaces, or indents the selected lines
Markdown bold ⇧⌘B wraps the selection in **
View Soft wrap (⌥Z), line numbers, current line band, zoom (⌘= ⌘- ⌘0), all kept between launches
Selection A strong blue, the same as the status bar, so a selection is clear on the dark theme

Colours

TextMate's Blackboard theme, for 5 formats. Textee colours only the lines on screen, and the next ones when I scroll.

Format Coloured
Markdown Front matter, headings, bold, italic, code, fences, links
JSON Keys, strings, numbers, true/false/null, comments
YAML Keys, strings, scalars, anchors, comments
Python Keywords, strings, decorators, function and class names
Shell Keywords, builtins, strings, variables, comments

Markdown in a .txt scratch file stays plain, and files over 5 MB aren't coloured.

Find and open

Feature How it works
Quick open ⌘P (or ⌘H) searches recent files and all of ~/txt by name, first line and content
Find and replace ⇧⌘F: match case, regex with $1 templates, every match coloured, "2 of 16", All as 1 undo
Open in Notee ⌥⌘O hands a file to Notee when it deserves a real Markdown workspace
Reveal and copy path ⌥⌘R shows the file in Finder, ⇧⌘D copies its path

Safe saving

Feature How it works
Atomic saves The file is replaced in 1 step and keeps its metadata, its line endings (LF or CRLF), its BOM
Changes on disk A file another app changed reloads by itself. With unsaved edits, a banner asks which to keep
No accidents Auto-save never writes an empty buffer over a file with content
Read-only A file that isn't valid UTF-8 opens read-only, with a banner, so Textee can't damage it

Settings

~/.textee/settings.json holds 2 settings. I edit the file, and Textee applies a save at once, with no restart. All my apps share the same 2 keys, starting with Filee: my own file manager for macOS, so I can compare square and rounded corners across them.

Key Values Default Sets
windowCorners "rounded" or "square" "rounded" The window corners and shadow
cornerRadius 0 (square) to 10 4 The tab highlights, the close button, quick open

Mine is set to square and 0. macOS 26 has no public setting for square windows: Textee answers a private AppKit method, _cornerMask. If a later macOS stops asking, the window stays rounded and nothing else breaks.

Keys

The menus use the standard titles, so my own App Shortcuts apply. ⌘D for Copy and ⌘F for Paste are my global remaps.

Key Command Key Command
⌘N New scratch file ⌘D Copy
⇧⌘N New from clipboard ⌘F Paste
⌘O Open… ⌥F Paste and match style
⌘P / ⌘H Quick open / recent files ⇧⌘F Find…
⌘S Save now ⌃F Hide the find bar
⌥⌘S Save as… ⌘T Duplicate line or selection
⌘W Close tab ⌥D Delete line
⌃⌘W Close window (every tab) ⌥↑ / ⌥↓ Move line
⌥⌘O Open in Notee ⌘] / ⌘[ Indent / outdent
⌥⌘R Reveal in Finder ⌥↩ Add next match
⇧⌘D Copy the path ⇧⌘A Select all matches
⇧⌘] / ⇧⌘[ Next / previous tab ⇧⌘B Markdown bold
⌥Z Soft wrap ⌘= ⌘- ⌘0 Zoom

Textee quick open searching scratch files for the word recorder: 2 results on the left, each with its first line as the title, and a preview on the right with the match highlighted

The scratch files have timestamps for names, so quick open shows the first line of each file as its title. That's what makes 3,000 files findable.

The character count follows LinkedIn as far as anyone knows. LinkedIn publishes no rule. Buffer's developer guide says it counts UTF-16 units, so an emoji counts 2, and Textee does the same: it never counts too low. Buffer also says a link counts as 24 units whatever its length. Textee doesn't apply that yet.

Textee vs 4 Mac text editors

I measured Textee against the other text editors on my Mac on 13th October: TextMate, CotEditor, Sublime Text and TextEdit. Every app was measured from outside, the same way: launch it or open a file in it, then watch the process until its CPU time stops growing. 7 rounds, medians of the last 6. Every app ran with my own settings, no session restore and a 1920 × 1080 window. My own TextMate kept running: the benchmark used a copy of it with its own bundle id.

Heat map of 16 speed and memory measures for Textee, TextMate, CotEditor, Sublime Text and TextEdit, each column headed by the app icon, green for the best and red for the worst: Textee's column is mostly solid green, with 12 wins and an average distance of 1.1x from the best

How to read it:

  • Textee wins 12 of the 16 measures. On average it's 1.1x the best value on each row. TextEdit comes next at 1.7x, then Sublime Text (3.5x), TextMate (3.7x) and CotEditor (5.8x).
  • TextEdit is the lightest on memory: 27 MB with 1 small file, 29 MB with the Markdown file. But it shows Markdown as plain text, and it opens each file in its own window. With 11 windows open it used 521 ms of CPU in 15 s of doing nothing, against 12 ms for Textee.
  • TextMate wins 1 row: 162 MB with the 22 MB file, against 174 MB for Textee.
  • Sublime Text is fast on big files, but it needs 208 MB for 1 small file. That figure includes its plugin processes.
  • CotEditor is the slowest here: 3.7 s to open 9 files, 249 MB with 11 files, and 7 s of CPU to colour the Markdown file.
  • Not compared: typing. Sending key presses to the other editors needs a permission the benchmark didn't have. Textee's own QA measures 2.6 ms per keystroke, including a full redraw of the editor.

The first run of this comparison wasn't fair, and I threw it away. Amethyst, my window manager, had left each editor's window at a different size: 673 × 439 for TextEdit, 2160 × 3809 for CotEditor. Memory grows with the window. Textee used 124 MB for the Markdown file in the tall window, and 45 MB in a 1200 × 900 one. The second run sets every window to the same size before each launch.

The benchmark also caught a bug. A first comparison with TextMate alone had Textee slower at opening 9 files (1.3 s against 0.8 s): Textee asked macOS to bring itself to the front once per file. One fix later, it was 2.4x faster.

For business people

Textee is a tool for 1 user and 1 habit. It does the scratchpad job I do 8 times a day, and the plain text editing around it, and nothing else.

The value isn't the editor. It's that 2 workarounds disappeared (the word count command and the Hammerspoon overlay), the clipboard flow got faster, and the next change is 1 prompt away.

The trade-off is the same as for every app I build: I maintain it, and nobody else supports it. The code is public, so anyone can build it and make it theirs, but I don't offer support.

For technical people

Stack

Layer Choice Why
Language and UI Swift 6 and AppKit, no third-party code Native, compiled, nothing to load at launch
Text engine NSTextView on TextKit 1 Fast on large files, with non-contiguous layout
Line numbers Own gutter view, visible lines only Draws from an index of line starts, never a full scan
Line index Line-start offsets, updated per edit Keystroke cost doesn't grow with the file
Colours Own line lexers, temporary attributes No text-storage edits, so no undo entries, no flicker
Counts Words and UTF-16 units; over 1 MB, background Typing stays fast in the 22 MB file
Saving Atomic replace, conflict check Keeps CRLF and BOMs; never writes an empty file over content
Build XcodeGen, Developer ID signing The project is a text file Claude can edit

About 4,500 lines of Swift, a QA script with 239 checks and a benchmark script. The QA works on copies of my files in a temp folder, with a private clipboard, so it never touches ~/txt or what I copied.

How the benchmark works

A small Swift probe watches the other app from outside, with no special permission: proc_pid_rusage gives CPU time and memory, the window list gives the moment the window appears. "Work done" is the moment the app's CPU time stops growing for 300 ms. The same probe measures every app, so the comparison is fair even when the absolute numbers are noisy.

Gotchas I hit

  • Views don't clip by default since macOS 14. The editor painted over the tab bar until every bar and the editor set clipsToBounds.
  • Undo merged several commands into 1 step. NSTextView merges an edit with the previous one unless breakUndoCoalescing() comes before shouldChangeText, not after.
  • QA steps aren't events. AppKit closes an undo group when it finishes an event, so the QA posts an event after each step, as a real key press would.
  • Default apps need a click now. On macOS 26, duti reports success but nothing changes until I approve a system prompt.
  • 1 activation per file is slow. macOS already brings an app to the front when it opens a file. Asking again for each file cost up to 2 s.
  • ⌥ + a letter never reaches the menu. AppKit types a character instead: ⌥D typed ∂ while the menu showed ⌥D for Delete Line. The text view now finds the ⌥ menu item and runs it. The QA missed it, because it called the menu directly, so it now sends real key presses too.
  • Square corners need a window class of its own. AppKit asks each window for its corner mask, but uses the answer only when the window's own class overrides the method. Changing every window at once does nothing.

How I got there: 4 prompts

I built Textee in 1 evening with Claude Code.

Prompt What I asked What happened
1 "Analyse my usage of TextMate, plan the app, ask me all your questions" It found the ca habit in my Alfred setup and asked 15 questions
2 My 15 answers, "blue colour scheme", "working app, QA'ed" Built, tested, installed, default app for .txt, Alfred updated
3 "Compare it with TextMate", then this note A first benchmark, and the bug it found
4 "Add CotEditor, Sublime Text and TextEdit, in a NicAI chart" The heat map, and a fairer benchmark with equal window sizes

What worked:

  • Usage data before features. The analysis showed I didn't need a project editor. I needed a fast clipboard pad with search.
  • Short answers to good questions. "No code sharing with Notee", "Blackboard", "count what LinkedIn counts": each answer cut a branch of work.
  • Measure against the thing it replaces. The comparison found a real bug that my own QA, which only measured Textee, had missed.

Further reading

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.