slate

plain-text notes · keyboard first · yours on disk

A local-first Markdown editor with a focused interface: one modal overlay, monospace type, a single accent colour, and a binding for everything. Your notes are ordinary .md files in an ordinary folder — openable by anything, greppable, git-able, and still yours the day slate stops existing.

Apple silicon · macOS 11+ 19 themes A calculator on every line End-to-end encrypted sync Bring your own AI, or none Works offline, always
notes
field-notes/2026-08-28.md
standard everforest

---
tags: [field, weather]
---

Thursday

Read snow as snow, not as a shower. The block wears its weather now — wx: in the frontmatter and the icon resolves at paint time.

A layout bug can be a network bug when a measure is in ch.

Today

  • Narrow the tree, reorder it, never leave the sidebar
  • Convert the XBM icons to path data
  • Write up [[the CSP rule]]

Filed under #field · see also [[weather blocks]] and **the shipping log**.

SAVED 214 words ~1 min ⎇ 2 links ← 3 backlinks ✦ opus-5 ⇡ synced 2m ago Everforest slate 0.2.0
The whole app. A top bar, a tree, the note, a status line — and nothing else. Press ⌘\ and the sidebar goes too.

01 What it is

Three commitments, and everything follows from them.

slate is not a database with a Markdown skin. It is a folder of text files with a very good editor pointed at it — which is why every decision below was easy.

01

Plain text

Your vault is a directory of .md files. Wikilinks, tags, frontmatter, tasks and tables are all just characters in the file. Rename a note and inbound [[links]] are rewritten; delete slate and nothing is trapped. There is no export because there is nothing to export from.

02

Keyboard first

Every command has an id, a palette entry, and — where it earns one — a binding. Space opens a which-key leader menu so the chord vocabulary is discoverable rather than memorised, and ⌘/ lists the lot, grouped. The mouse works. It is never the fast way.

03

Yours on disk

Files are read and written straight to the folder you picked, with no server in the path. Sync is optional and end-to-end encrypted — the server stores ciphertext it cannot open. Offline is not a degraded mode; it is the normal one.

02 Get slate

Three ways in. The vault is the same one.

The desktop app and the web build read the same folder and speak the same sync protocol. Start in a browser tab, install the app later, and nothing has to move.

Mac app 0.1.37

The native build. Real filesystem access, a built-in terminal rooted in your vault, a dock icon, the OS keychain for AI keys, and your Android phone on the same wifi — battery, signal, text messages, the clipboard and files, over KDE Connect. Apple silicon, .dmg, macOS 11 or later.

Download .dmg 7.5 MB · Apple silicon

Not signed by an identified developer yet, so macOS stops the first launch. On macOS 15, open it once and then allow it in System Settings → Privacy & Security. On macOS 11–14, right-click the app → OpenOpen. Asked once, either way.

On the web no install

The same app in a tab. Chrome, Edge, Brave or Arc can open a real local folder through the File System Access API, so the web build edits your actual .md files — not a copy in browser storage.

Open slate → nothing to install

Safari and Firefox can't open local folders yet — but Try a demo vault, on slate's first screen, works in every browser and writes nothing to disk.

Chrome clipper unpacked

Send a selection or a whole page into today's note. The clipper holds a vault id and a public key — no account, no session, no password, and nothing that can open a note. Clips are sealed in the browser before they leave.

Download .zip 18 KB · S to clip

Not on the Web Store yet: unzip, then Chrome → chrome://extensions → Developer mode → Load unpacked.

Losing the clipper costs you the ability to add lines to your daily note. It does not cost you the vault. That is a design decision, not an accident — the insert is routed through a server-side function so the extension never holds a credential that could delete or corrupt a note.

03 Start here

Five minutes, and the only thing you have to decide is which folder.

Point it at a folder

Open slate and choose Open a folder… — an empty directory, or one that already has notes in it. That folder is the vault. slate adds no hidden database beside your files; the folder after slate has touched it is a folder of .md files and whatever attachments you dropped in.

Not ready to commit? Try a demo vault loads a working vault in memory, including five example prompt notes. Nothing is written to disk.

Learn four keys, not forty

⌘K finds notes, headings, commands, tags, panes, and desks. ⌘P runs any command. ⌘⇧F searches the vault. Space — pressed on its own, outside the editor — opens the leader menu and shows you every chord there is.

When you want the rest, ⌘/ lists every command with its binding, grouped by what it does. It is the same list the palette runs from, so nothing on it is stale.

Write like it's a text file, because it is

Markdown as you type: # heading, - [ ] task, > quote, | tables |. [[wikilinks]] autocomplete against the vault and rename with their target. #tags are indexed vault-wide — type # in any palette to browse every one with its count.

Backlinks aren't chrome in a sidebar; they render at the foot of the note as one dim row that expands into the sentence each link sits in.

Make the daily note your inbox

⌘⌥D opens today's note, creating it from your template if it doesn't exist. ⌘⇧↵ logs the line you're on — or the selection — into today's note without leaving the note you're in. The Chrome clipper lands in the same place.

Turn on sync, if you want it

Set up sync for this vault from ⌘P asks for an account and a vault password. The password never leaves the device: it unwraps a key that encrypts every file before upload. The server holds ciphertext and filenames it cannot read, which also means we cannot reset that password for you.

Sync is optional and per-vault. Choose what syncs excludes folders, attachments or plugins; Earlier versions of this note pulls any synced revision back.

notes
projects/slate.md
⌘P

slate

One modal overlay, monospace type, a single accent colour, and a binding for everything.

  • Ship the desktop build
  • Sign it
> the — run a command commands
Theme
Change themelive preview⌘T
Cycle to next theme19 themes⌘⇧T
Navigate
Jump to headingoutline⌘⇧O
All tasks in vaultrollup
Vault
Connect a clipper…chrome
↑↓ move↵ runesc close ⌘P
SAVED 86 words Everforestslate 0.2.0
One overlay, five modes. Files, commands, search, outline and tags are the same box wearing a different sigil — >, /, @, #. Learn it once.

04 Terminal plugin · Mac

Your notes and your shell, in the same workspace.

Open a real interactive terminal beside the note you are working on. It starts in the current vault, follows slate's theme and type settings, and stays inside the pane system you already know.

  • A real shell. Full PTY support means interactive commands, colours, prompts, resize handling, and familiar Ctrl-C and Ctrl-D behaviour — not a simulated command box.
  • Already in context. New sessions begin at the open vault, ready for git, search, scripts, static-site builds, or whatever the folder needs.
  • Dock it or float it. Keep the terminal next to a note, move it to another pane, or make it a floating plugin window with F.
  • Permissioned by design. Shell access is an explicit plugin permission, and each session is stopped when its terminal closes.
  • Mac app only. The browser build remains sandboxed; the terminal is part of slate's native macOS app.
Open it from Plugins. Press P, enable Terminal, then open its window from the palette or the leader menu.
Terminal
~/notes
plugin
terminal dock · float
slate ~/notes % pwd
/Users/you/notes
slate ~/notes % rg "ship" projects
projects/slate.md
18:- [ ] Ship the signed Mac build
32:- [x] Ship the terminal plugin
slate ~/notes % git status --short
M projects/slate.md
# ordinary files, ordinary tools
slate ~/notes %
RUNNINGzsh Everforestvault cwd
Native underneath, slate everywhere else. The shell is backed by a native pseudo-terminal while its colours, font, focus and window controls belong to the app.

05 Keyboard shortcuts

A binding for everything, and a menu for the rest.

A handful of keys differ between the desktop app and a browser tab, because the browser owns some of them. slate resolves that per platform, so the binding shown inside the app is always the one that works there.

Navigate

Find notes, commands, tags, panes, and desksK
Command paletteP
Search the vault — tag: path: "phrase" -excludeF
Browse every tag in the vault#
Jump to headingOJ
All tasks in the vaultpalette only
Back[O
Forward]I

View

Toggle sidebar — ⌘B belongs to bold\
Zen mode — the chrome fades, the window stays.
Full screenFV
Cycle view mode — standard → zen → fullpalette only
Change theme — live preview while arrowingTT
Cycle to the next themeTT
Manage pluginsP
Dock or float this pluginF

Notes & vault

New noteNN
New note from a templateSpaceM
Today's noteD
Log this line to today
Rename note — rewrites inbound [[links]]R
Open vault folder…O
Sync this vault nowS
Save now — it already savedS

Format

Bold · italic · inline code⌘B⌘I⌘E
StrikethroughX
Link to a noteK
Cycle heading levelH
Paragraph — clear the heading00
Bullet list · numbered list⌘⇧L⌘⇧9
Task checkboxB
Blockquote · code block · table⌘⇧.⌘⌥E⌘⌥G

AI — only if you connect one

The AI console — every action in one popupK
Pick an agent · pick a model⌘⌥A⌘⌥M
Continue writing at the caret
Rewrite the selectionR
New conversation — a chat note in a splitC
Send this turn
Run a prompt from prompts/*.mdP
Stop the stream

Panes & desks

Split right · split down⌃⌥↵⌃⌥\
Close pane · maximize pane⌃⌥W⌃⌥F
Focus a pane — vim directions⌃⌥HJKL
Move a pane⌃⌥⇧HJKL
Grow a pane · equalize⌃⌥←→⌃⌥0
Go to a desk · name this desk⌃⌥Space⌃⌥N
Workspace 1–9⌃⌥19
Keyboard shortcuts — every command, grouped/

The leader menu

Space on its own opens a which-key hint menu, so the chord vocabulary is discoverable rather than memorised. Keep holding the thought; the menu tells you the letter.

SpaceF go to note SpaceS search SpaceP commands SpaceD today SpaceN new note SpaceM from template SpaceJ headings SpaceK tasks SpaceT theme SpaceB sidebar SpaceZ zen SpaceG full screen SpaceV split right SpaceQ close pane Space= equalize SpaceO open vault SpaceX plugins SpaceW plugin windows SpaceA agent SpaceI continue writing SpaceR rewrite SpaceC chat Space? all shortcuts
Every binding is yours to change. Commands are addressed by id, so a rebinding survives a rename — and slate refuses to take a key the platform has already claimed rather than silently losing to it.

06 Numbers in a note

End a line with = and the answer appears beside it. It is never written into the file.

A note is prose first. So the trigger is a deliberate, typed gesture — the line has to end in an equals sign — and everything else stays a sentence. “The deal closed at 3” never lights up with a number.

  • The answer is a rendering, not a rewrite. The file on disk still says 82 + 55 =, exactly like **bold** stays four asterisks. Click an answer to copy it, or run Insert calculation results to write them all in at once.
  • Name a value with a colonguests : 5 — and every line below it can use the name. Redefine it halfway down and only the lines under the new one change their mind.
  • Units are checked, not guessed. 5kg + 3lbs in lbs is a real dimensional conversion; 3 apples + 2 hours stays blank rather than inventing a number.
  • Code fences and frontmatter are quoted, not computed. A note about this feature can show 2 + 2 = without it answering, and count: 99 at the top of a note stays metadata.
  • Nothing is loaded until you need it. The maths engine — 150KB — is fetched the first time a document actually contains an = line, and exchange rates only when a line names a currency.
notes
projects/thanksgiving.md
zen

Shopping

guests : 5

guests * 3 =15

12 cups to teaspoons =576 teaspoons

1 tsp + 4 tbsp + 6 cups =301 tsp

350 F to C =176.67 °C

The bill

1,200 * 3 =3,600

10% off 250 =225

$24 USD to CAD =32.88 CAD

Split it evenly and everybody owes 720 —

SAVED 7 answers ↵ copy rates 4h ago slate 0.2.0
Answers sit beside the text, tinted rather than filled — so it reads as the editor answering, never as something the document now contains.

What it understands

Every line below is a real one, with the answer slate gives it. The informality — a dollar sign in front, a fraction glyph, a question asked in words — is rewritten into arithmetic before anything is evaluated.

Arithmetic

82 + 55 =137
1,200 * 3 =3,600
(18 + 24) / 2 =21
sqrt(144) + 2^5 =44
mean(12, 19, 27) =19.333333
5k * 12 =60,000

Thousands separators, × and ÷, an en-dash pasted out of a word processor, 3 x 4, and 5k for five thousand. Not 5m — that already means five metres.

Units & conversions

20cm to in =7.874 in
5ft + 3in in cm =160.02 cm
90 km/h to m/s =25 m / s
20 C to F =68 °F
3 days in hours =72 hours
1.5 GB to MB =1500 MB

Length, mass, area, volume, speed, time, data, temperature. into reads better than to in a sentence and means the same thing; a bare 20 C is Celsius, not coulombs.

Percentages

200 + 15% =230
15% of 200 =30
10% off 250 =225
what % of 200 is 50 =25
80 as a % of 200 =40
1200 increased by 20% =1,440

200 + 15% means fifteen percent of the thing on the left — the reading on every receipt and every calculator, rather than the arithmetically literal one.

Kitchen measures

12 cups to teaspoons =576 teaspoons
1 tsp + 4 tbsp + 6 cups =301 tsp
8 oz to cups =1 cup
1½ cups in ml =354.88 ml
350 F to C =176.67 °C
1 1/2 cups + 2 tbsp =1.625 cups

The spoons are US customary, so 16 tablespoons and 48 teaspoons make a cup — the numbers on the measuring spoons in your drawer, not the metric ones a standards body would defend.

Money, at today's rate

$24 USD to CAD =32.88 CAD
€50 to USD =54.35 USD
0.5 BTC in USD =live
£120 + £45 in EUR =live
30 usd to cad =live
$40 to JPY =rates unavailable

ECB reference rates for fiat, CoinGecko for crypto. Neither is told what the note says — only which symbols to price — and nothing is fetched until a line names a currency. A failed fetch says so rather than quietly using yesterday's number.

Variables

guests : 5a definition
guests * 3 =15
total : 1200a definition
total * 0.15 =180
day rate : 850spaces allowed
day rate * 12 =10,200

A colon, deliberately — so x = 5 stays prose. A definition applies to the lines below it, exactly as it reads, and total guests is one variable rather than two multiplied.

07 History & connections

A time machine that is just files — and a diff, so going back is something you read first.

Local-first apps usually give up the one thing hosted apps do well: what did this say last Tuesday. slate's answer isn't a server. The version a save is about to replace is written into .slate/history/ — inside your vault, skipped by the file tree, travelling with the folder like everything else.

  • Press ⌃⌥Z and the versions of this note appear, newest first, described the way you'd say them out loud — just now, 4 minutes ago, yesterday.
  • The list answers “when”; the panel answers “what.” Arrow through the times and a line diff shows what would come back and what would go, folded where nothing changed. Restoring stops being a keystroke taken on trust.
  • Only the past is stored. The current version is the note itself, so the list never contains a duplicate of the present — and a snapshot is taken at most once every two minutes, however hard you're typing.
  • You set the depth, in a note. history: 30 in slate.md keeps thirty per note; false turns it off entirely. Deleted notes wait in .trash/ on the same terms.
  • Synced vaults get the other kind too. Earlier versions of this note pulls revisions the server holds — still ciphertext to it, still decrypted only here.
Past versions
field-notes/2026-08-28.md
⌃⌥Z
filter 14 versions history
just now+2 −1
14 minutes ago+3 −1
2 hours ago+1
yesterday+9 −4
3 days ago+12
2026-08-19+40
28 Aug, 09:41 +3−1
 # Thursday
6 unchanged lines
- [ ] Convert the icons
+- [ ] Convert the XBM icons to path data
+- [ ] Write up [[the CSP rule]]
 
+Filed under #field
↵ restore this version↑↓ compare esc leave the note alone
SAVED 14 versions · .slate/history slate 0.2.0
Lines, not characters. A note is edited in paragraphs, and a line diff is the one that still reads correctly in a column this narrow.

Connections, in a pane of their own

Open Connections beside a note and you get three lists: the links going out, the backlinks coming in, and — the useful one — unlinked mentions, every note that says this note's name or one of its aliases without linking it. One keystroke turns a mention into a [[link]], rewriting the other file where it stands.

Every name a note answers to

Put aliases: [MOC, index] in a note's frontmatter and it answers to all of them — in the palette, in a [[link]], and in the unlinked mention scan. Rename the note later and inbound links are rewritten; the aliases keep working, because they were never the filename.

08 Also in the box

Six more things that earned their place.

Each of these is small, and each is a file — which is the test everything has to pass before it ships.

01

Nine desks

Each workspace holds its own pane layout — a split for writing, a split for research, a terminal beside a note. ⌃⌥1⌃⌥9 to switch, ⌃⌥N to name one. Empty desks stay hidden behind a single + rather than advertising capacity you aren't using.

02

The settings note

There is no preferences panel. slate.md in your vault is the settings screen — theme, vim mode, history depth, trash days, where daily notes live, which folder seeds templates — all frontmatter, all documented in the note itself, all travelling with the vault.

03

Templates, per folder

Notes in templates/ seed new ones: {{title}}, {{date:+1w}} and numbered tab stops like {{1:who was there}} that you tab between. Say templates.meetings: Meeting and every new note in meetings/ starts from it — one line of frontmatter, no rule engine.

04

The daily note, and the log key

⌘⌥D opens today's note, creating it if it's new. ⌘⇧↵ takes the line you're on — anywhere in the vault — and appends it to today, timestamped. Every unticked box in the vault, meanwhile, is one list away in the palette.

05

Cards from a .base

A folder of records — vinyl, books, films — drawn as a grid of covers, sized and filtered by a small YAML file sitting in the folder beside the notes. It is a saved view, not a hosted database: it diffs, syncs and versions like any other file, and Obsidian reads the same one.

06

Vim mode, if you want it

vim: true in the settings note and the editor takes modal keybindings — loaded only when it's on, so nobody who doesn't use it pays for it. The pane directions are vim's either way: ⌃⌥ plus HJKL.

09 AI, on your terms

Bring your own agent. Or don't — with none picked, every AI command is simply absent.

slate ships no model, no key, and no account for one. Point it at Ollama on localhost, connect OpenRouter without an API key at all, or give it any OpenAI-compatible URL.

  • Nothing is final. The console never touches your note until you press the key that lands the result. A suggested title arrives as a proposal, not a file that renamed itself.
  • You can see what you're about to send. The left pane fills in as you type, labelled with its scope and a token estimate — before the request, not after.
  • A conversation is a note. ⌘⌥C splits a pane and writes chats/2026-08-26 0952.md. The transcript is the file: searchable, [[linkable]], editable mid-thread.
  • Prompts are notes. Drop .md files in prompts/ with frontmatter saying what goes in and where it comes out, and you have added an AI feature without a release.
  • Ollama needs nothing at all. Running locally, the statusline says instead of — proof that nothing left the machine.
  • Keys live in sessionStorage, never in the vault, because the vault is plain text headed for git. Closing the browser forgets them, deliberately.
AI console
field-notes/2026-08-28.md
⌘⌥K
ask, or pick an action none ▾   opus-5 ▾
scope · none⇡ 0
Nothing from the vault goes with this one — no note, no selection, no search. ⇥ to send the note instead.
Ask anythingnone → insert below
Rewriteselection → replace
Suggest linkslinked → insert below
Suggest tagsnote → apply
Weekly digestvault → note
↵ run⇥ scope⌘↵ land below ⇧esc back to the list
SAVED ✦ opus-5 ⌂ localslate 0.2.0
One popup, not eight. Built-ins and your own prompt notes in one fuzzy-matched list, each row saying where its answer will land before you run it.

10 Sync & the clipper

The server holds ciphertext it cannot open. That is the entire design.

End-to-end encrypted sync

A vault password — never sent — unwraps the key that encrypts every file before upload. Filenames included. Sync is per-vault and selective: exclude a folder, skip attachments, leave plugins behind. Earlier synced revisions of any note come back from the palette.

The trade is stated plainly: nobody can reset that password for you, because nobody else ever had it.

The clipper holds no credential

The obvious build signs the extension in with your account. We didn't: a session grants delete and update on every file, so a compromised extension could destroy ciphertext it could never read. Instead the insert routes through a server-side function, and the extension keeps only a vault id and a public key.

Clips arrive on the next sync, timestamped when they were captured, and drain into your daily note.