awl

Guide

How the pieces fit together.

This page documents how awl's pieces fit together. The command palette (⌘P) already lists every command by name; this page covers the model underneath.


Where your words live

The first launch opens a document, not an empty editor. With nothing to resume and no configured writing folder, awl opens its authored Welcome through the recoverable scratch store. It does not create ~/notes or place a file in a user folder. Its edits survive relaunch.

The first new document asks for a writing folder, then opens the ordinary unnamed document there. Keep tutorial… uses the same folder choice and saves the edited Welcome as Markdown.

Where it lives firstawl's recoverable scratch store, not a user folder
Configured folderdefault_folder is intentional: Welcome is an ordinary welcome.md there
Shown again?No. awl records the fact once, in $XDG_DATA_HOME/awl/welcomed (or ~/.local/share/awl/welcomed)
To be welcomed againDelete that marker file and the scratch document, then launch with nothing to resume
In the browserThe same document is seeded into the tab's storage on a first load, alongside tour.md, prose.md and japanese.md

The chords the document teaches are substituted into it as it is written, from the same command catalog the palette reads, so it names your platform's own bindings rather than a hand-typed guess.

A scratch buffer, always open. After that first launch, launch awl with no file and you land on a writing surface — no save dialog, no "untitled-1.md". It stashes itself to disk on the same rhythm as everything else: idle, window blur, buffer switch, quit ($XDG_DATA_HOME/awl/scratch.md, or ~/.local/share/awl/scratch.md if XDG_DATA_HOME isn't set — on the web build, localStorage). Relaunch bare and the scratch buffer is where you left it, including parts you never explicitly saved.

A fresh document (⌘N) works the same way, in the folder you're already in. ⌘N opens a new, unnamed document in the active folder — wherever you last opened a file or switched projects, never a separate jump. Nothing writes to disk until you type something. An explicitly configured default_folder is used as that initial folder; otherwise awl asks before the first real file is created.

Autosave runs on four triggers: idle (about a second after you stop typing), window blur, buffer switch, quit. Writes are atomic — a temp file, then a rename.

Nothing awl writes ever replaces a change made outside it. awl remembers the exact bytes it last saw in each open file, so a rewrite that keeps the same timestamp and the same length is still noticed. It re-checks when you return to the window, when you switch or open a file, and before every write.

what awl findswhat happens
the file is unchangedthe write goes through
the file changed, and you have no unsaved editsawl reloads it, keeping your cursor and scroll
the file changed and you have unsaved editsboth are kept — see below

When both changed, you choose. awl keeps your text as the one document you are editing and stops writing to the file, so neither version can be lost. A changed elsewhere line sits beside the filename in the page margin for as long as the change is unresolved, and your unsaved text is copied to awl's own data folder — so it survives a crash, and comes back when you reopen the file. Three commands settle it:

commandwhat it does
Review the changeshows both versions, one at a time, changing nothing
Save your versionre-checks the file, then writes your text over it
Use disk versionreplaces your text with the file's, as one edit ⌘Z takes back

Review the change opens a reading surface with three views — Differences, Your version, and Version on disk — and Esc returns you to editing with nothing settled. It is a read: neither version changes until you run one of the other two.

Saving, switching files, renaming, moving and Finish file all wait until you have chosen. ⌘S does not force-write over an external change; Save your version is the explicit way to keep yours.

A small dot (•) in the window title marks an unsaved buffer, clearing the instant it's written. The stats HUD (Option-⌘I) shows a SAVED row too — "just now", "3m ago", "unsaved changes."

Local history keeps more than the current text. Every save of a file not under git records a snapshot, pruned by an aged retention ladder: everything from the last ~15 minutes, then one per writing session, then one per day, then one per week — never a flat FIFO cutoff. ⌘⇧H opens the timeline for the current file; Enter on any entry restores it as one ordinary undoable edit. "Keep version" (⌘P) pins a snapshot the retention ladder will never prune. A file under git skips awl's own history entirely — git log is that file's timeline.

A corrupted store never eats your data. Session state, usage stats, recent-projects, the history log, the scratch stash — if any of these is unreadable (garbled, not just missing) when awl tries to load it, the bad file is copied aside first (<name>.corrupt-<timestamp>) before awl falls back to a clean default. Nothing is silently discarded. (config.toml is the one exception — a syntax error there keeps your last-known-good settings and shows a notice, since your editor buffer and undo history already hold your intended text.)

Naming a fresh document

A fresh document (⌘N) starts unnamed, like the scratch buffer. Save it — or keep typing and let autosave catch up — and awl slugifies the first line into a filename and writes it in the active folder, ONCE. Changing the first line afterward never renames the file again; it's an ordinary document from that first save on, exactly like one you opened from disk.

Three generic file verbs live in the palette for any document:

  • Rename note… — pick a new name.
  • Duplicate note — an immediate copy, no dialog.
  • Move… — file it elsewhere under (or out of) the active folder.

None carry a default chord — ⌘P, type "rename", Enter.

Keys

Every command has up to two bindings — slot 1 is native (⌘ on macOS, Ctrl on Linux) and is the one awl teaches; slot 2 is Emacs, a second layer that never goes away. Both fire. The palette (⌘P) shows both next to each command's name.

Linux gets the same commands under Ctrl. Where a native Ctrl chord collides with a bare-control Emacs default (Ctrl-S save vs. Emacs C-s search), the native one wins and the Emacs default steps aside — still one [keys] line away. Set keymap = "emacs" in the config to bring back the whole displaced cluster at once, instead of naming chords one at a time. The Omarchy/Hyprland recipe (that compositor forwards Super+C/X/V as Ctrl+C/X/V for the system clipboard): keymap = "emacs" plus [keys] copy = "C-c", cut = "C-x", paste = "C-v" keeps those three chords native under the emacs preset.

Rebind anything. [keys] in the config maps a command's slugified name to a chord, or up to two. Example — restoring the Option-letter word motions the platform rule retired by default (macOS reserves Option-letters for accented characters):

[keys]
forward_word  = ["M-Right", "M-f"]
backward_word = ["M-Left", "M-b"]

Or capture the key directly: ⌘P → "Keybindings…" opens a picker over every command; Enter starts a capture, and the next key or chord becomes the new binding, written into your config.

The hold-⌘ peek. Hold the arming modifier alone for a beat (⌘ on Mac, Ctrl on Linux) and a card of frequently-used shortcuts appears. Release the hold and the card is gone — no click, no dismiss.

The pointer gets a bounded bridge. Select text with the mouse in a Markdown buffer — drag, double-click a word, triple-click a line — and a small row of buttons appears beside the selection: bold, italic, highlight, code, strikethrough, heading, link. Each one fires the same command its chord does, and lights up when the selection already carries that format. Any key press, or losing the selection, dismisses it. A keyboard selection never summons it, and it never becomes a persistent toolbar. popover = false turns it off, and the settings row that does the same is "Format popover".

Generated from the live command catalog — never hand-edited (see the law test in src/guide.rs). Every catalog command's resolved default chord, mac glyphs beside Linux words:

CommandmacOSLinux
Go to…⌘OCtrl+O
Open file…
Open folder…
Spell suggestions…⌘;Ctrl+;
Version history…⌘⇧HCtrl+Shift+H
Compare with version…
Clean unused assets…
Keep version…
Last file⌃TabCtrl+Tab
New document⌘NCtrl+N
Keep tutorial…
Move…
Rename note…
Duplicate note
Finish file⌘WCtrl+W
Follow linkC-c C-o
Switch theme…⌘TCtrl+T
Caret style…
Dictionary…
Toggle spellcheck
Toggle caret style
Toggle page mode
Toggle writing nits
Widen page
Narrow page
Reset page width
Toggle debug
Toggle outline⌘⇧OCtrl+Shift+O
Fold section⌘⇧E · C-c C-fCtrl+Shift+E
Collapse other sections⌘⇧M · C-c C-tCtrl+Shift+M
Toggle typewriter scroll
Toggle menu bar
About
Credits
Lifetime stats
Writing streaks
Line endings…
Align table
Tag document language
Insert Date⌘⇧D · C-c .Ctrl+Shift+D
Report a Problem
Download file
Check for Updates
Blockquote
Bullet list
Numbered list
Task list⌘⇧LCtrl+Shift+L
Heading
Cycle heading
Code block
Bold⌘BCtrl+B
Italic⌘ICtrl+I
Inline code⌘ECtrl+E
Highlight
Strikethrough
Export as Word…
Export as HTML…
Export as PDF…
Insert link…⌘K
Save⌘SCtrl+S
Quit⌘QCtrl+Q
Search forward⌘F · C-sCtrl+F
Search backward⌘⇧F · C-rCtrl+Shift+F
Find and replace…⌘RCtrl+R
Undo⌘Z · C-/Ctrl+Z · C-/
Redo⌘⇧ZCtrl+Shift+Z
Copy⌘CCtrl+C
Cut⌘X · C-wCtrl+X
Paste⌘V · C-yCtrl+V · C-y
Select all⌘ACtrl+A
Zoom in⌘=Ctrl+=
Zoom out⌘-Ctrl+-
Reset zoom⌘0Ctrl+0
Forward word⌥RightAlt+Right
Backward word⌥LeftAlt+Left
Line start⌘Left · C-aHome
Line end⌘Right · C-eEnd
Document start⌘UpCtrl+Home
Document end⌘DownCtrl+End
Forward charC-f
Backward charC-b
Next lineC-n
Previous lineC-p
Delete word forward
Delete word backward
Settings…⌘,Ctrl+,
Keybindings…

Looks

20 worlds, one chord away. ⌘T (Ctrl-T on Linux) opens the theme picker — each world pairs its own display face with its own ink ladder. Wagtail is the exception: awl's one monochrome world, drawn in black, white, and nothing between.

Two page widths, one for prose, one for code. The writing column measures 70 characters by default for prose and 100 for code (rustfmt's own convention) — independent settings; widening one never touches the other. Drag the column's edge, or use "Widen page" / "Narrow page" / "Reset page width" in the palette.

WYSIWYG, revealed by caret or selection. Markdown markup — a heading's #, **bold**, `code`, ==highlight==, ~~strikethrough~~, a fenced code block's fence lines — renders concealed except on the line your caret is on, or any line your selection touches, where it shows in full for editing. A fenced block reveals whole: its fence lines show while the caret sits anywhere inside it. The file on disk is always plain markdown; only the render is rich. wysiwyg = false disables the conceal entirely.

Reduce Motion is a real accessibility preference, not a cosmetic toggle. Absent config means auto: awl reads the OS-level "Reduce Motion" setting where one is reachable (macOS, the web build) and follows it. Set reduce_motion = true by hand on Linux, where there's no reliable cross-desktop signal yet.

Settings, and the config file behind them

"Settings…" is a summoned workspace, not an overlay. It takes the viewport: a category rail — All, Editor, Appearance, Writing, Files, Keybindings, Advanced — beside the rows it governs. Up/Down moves the category, Enter or Right transfers focus into the settings, Left comes back to the rail — except on a row whose value is a slider, where Left and Right adjust it and the footer says so — Backspace on an empty search field comes back as well, Tab moves focus between the two either way, and Esc leaves for the editor from wherever you are — exactly where you left it. On a window too narrow to hold both, the workspace shows one region at a time and the same keys move between them. Every change applies live; a sticky one is written to the config in the same step.

The settings are a plain text file, and you can edit it directly. The Advanced category's "Edit config as text" row opens config.toml into the buffer (writing the commented starter template first, if none exists). Edit it like any other document, then save — the keymap, folders, and every sticky preference re-apply live, no restart. A config with a syntax error keeps prior values in place and shows a notice.

An absent config is just today's defaults. Once you touch it, it remembers: theme, zoom, page widths, caret style, dictionary, and a dozen other toggles persist across launches the moment you change them live, and every key is hand-editable too.

Awl in the browser

The web build is the same editor compiled to wasm32-unknown-unknown, running in a <canvas> with no native filesystem underneath it.

Desktop (macOS / Linux)Browser
StorageReal files on disklocalStorage, capped around 5 MB — roughly eight to ten novels of plain text; scoped to this browser profile, gone if site data is cleared
Preferences, [keys]~/.config/awl/config.tomlA config.toml over localStorage, same format, persists across reloads
CopyTo the OS clipboardMirrors out to the OS clipboard (best-effort, async)
PasteFrom the OS clipboardFrom awl's own kill ring only — an external copy doesn't appear until you've copied something from awl at least once
Getting a file outAlready on disk"Download file" (⌘P) — saves the active buffer as a plain-text download

Hidden on web: Version history…, Compare with version…, Clean unused assets…, Keep version…, Finish file, Lifetime stats, Writing streaks, Quit, Check for Updates — daemon, session-restore, and local-version-history machinery with nothing to attach to in a browser tab.

A couple of native chords belong to the browser itself (new tab, new window, and similar). New document and Switch theme… resolve to a working alternate chord on web automatically; every command is also reachable by name through the palette.

The desktop build has no storage cap, real OS clipboard paste, and the commands above. The releases page carries the Linux x86_64 download; macOS builds from source until a signed build is ready.