Editor

Shortcuts

Shortcuts

Every keyboard shortcut outl ships with, across every client, in one table per concern.

Source of truth

The desktop and TUI both pull their chord catalog from crates/outl-shortcuts (src/defaults.rs::default_bindings()). The mobile app doesn’t expose a keyboard surface (touch + on-screen keyboard); the rows below leave its column blank when there’s nothing to bind.

One catalog, two adapters. The TUI converts crossterm::KeyEvent → Chord, the desktop converts browser KeyboardEvent → Chord. Both then call the same outl_shortcuts::lookup(mode, chord) → Action. A chord change in defaults.rs lights up on both clients on the next build.

If a row below disagrees with what you observe in the app, the code is right and this doc is stale — file an issue or fix the row.

How to read the tables

  • Chrome / Global chords fire in every mode.
  • Normal / Insert / Visual / Overlay mirror the vim modes. The desktop subscribes to Normal/Visual only while editor.vim_mode = true (see docs/config.md); chrome and Insert chords are always live.
  • Cmd is the macOS modifier; Ctrl is the same chord on Linux / Windows / TUI. We list one form per row to keep the table readable.
  • A chord in the form q q is a vim-style two-key sequence: press the first, then the second within ~1 s.

Chrome (Global) — works in any mode

ActionTUIDesktopMobile
Quick switcher (fuzzy pages + journals)Ctrl+PCmd/Ctrl+Ptap toolbar
Open today’s journalt / HomeCmd/Ctrl+Jtoolbar
Toggle TODO / DONE on focused or selected block (T for task)Ctrl+T / Ctrl+EnterCmd/Ctrl+T / Cmd/Ctrl+Entertap checkbox
Run code block under cursor / inside focused block (X for execute)g x chord / :runCmd/Ctrl+Xtap “Run” button
Previous journal day[Cmd/Ctrl+[swipe right
Next journal day]Cmd/Ctrl+]swipe left
Toggle sidebarCtrl+ECmd/Ctrl+Shift+E(single pane)
Toggle backlinks panelCtrl+BCmd/Ctrl+Shift+Binline below outline
Open settingsvia :settingsCmd/Ctrl+,gear icon
Toggle help overlay?Cmd/Ctrl+/help button
Quitq q (chord) / Ctrl+CCmd/Ctrl+Q (OS)

Why Cmd+J and not Cmd+T for today’s journal? Every outliner ecosystem uses T for task / TODO — TUI’s Ctrl+T, Logseq’s Cmd+T, the universal Markdown checkbox shortcut. Re-training that muscle memory would be hostile. J for journal is unambiguous and lines up with the TUI’s g j chord.

Defaults the user often asks about. Both clients ship with sidebar and backlinks panel HIDDEN (show_sidebar: false, show_backlinks: false). Editor-hero on first launch — the user opts the panels in with the chord. This matches Bear / Ulysses on the desktop and outl-tui’s historical behaviour.

ChordWhy not
Cmd+BReserved for bold in Insert mode — every popular markdown editor (Notion, Obsidian, Discord, Slack, Typora) treats it that way. Hijacking would be hostile.
Cmd+\macOS 1Password global autofill. Stealing it breaks every 1Password user.

So Cmd+Shift+E (VS Code’s “Show Explorer”) and Cmd+Shift+B are the canonical chrome chords on the desktop, and the TUI mirrors the spirit with Ctrl+E / Ctrl+B (most terminals collapse Ctrl+Shift+letter into Ctrl+letter, so both forms work identically).


Inline markdown — Insert mode (textarea focused)

Wrap the current selection (or insert the delimiter pair around the caret). Mirrors the convention every markdown editor on the planet ships.

ActionTUIDesktopMobile
Bold (**…**)type **Cmd/Ctrl+Btoolbar B
Italic (_…_)type _Cmd/Ctrl+Itoolbar I
Inline code (`…`)type `Cmd/Ctrl+Etoolbar <>
Strikethrough (~~…~~)type ~~Cmd/Ctrl+Shift+Xtoolbar S
Link ([label](url))type [Cmd/Ctrl+Ktoolbar 🔗

outl ships _…_ as the canonical italic. The parser still accepts *…* for compatibility, but .md projections emit underscores.


Outline navigation — Normal mode

The desktop honours Normal/Visual only while editor.vim_mode = true. The TUI is vim-style by definition.

ActionTUIDesktop (vim on)Mobile
Selection downj / j / tap block
Selection upk / k / tap block
Enter Insert at end of blockiitap block
Enter Insert at start of blockIItap at start
Open [[ref]] / #tag / ((blk-…)) under cursorEnterEntertap
New block below + Insertootoolbar +
New block above + InsertOO
Indent blockTabTabdrag right
Outdent blockShift+TabShift+Tabdrag left
Move block upKKdrag
Move block downJJdrag
Delete block (chord)d dd dswipe left
Fold / unfold (toggle collapsed)cctap bullet
Last block (jump)GG
First block (chord)g gg g
Undouu / Cmd+Ztoolbar
RedoCtrl+RCtrl+R / Cmd+Shift+Ztoolbar
Yank block ref → clipboard (chord)y ry r
Enter Visualvv
Open command palette::
Open slash menu///

Cursor inside a block (Normal)

ActionTUIDesktop (vim on)
Char left / righth / l (or arrows)h / l
Word right / leftw / bw / b
Start / end of block text0 / $ (or Home/End)0 / $

Insert mode (text editing)

ActionTUIDesktopMobile
Commit + exit InsertEscEsc / blurblur
Newline inside the block (multi-line text)Shift+EnterEnterEnter
Commit + new block belowEnterCmd/Ctrl+Shift+EnterEnter
Indent (stay in Insert)TabTabdrag
Outdent (stay in Insert)Shift+TabShift+Tabdrag
Delete block on emptyBackspace on emptyBackspace on empty
Auto-pair ( [ { [[ ((yesyesyes
Ref autocomplete[[ triggers picker[[ triggers picker[[ triggers picker
Tag autocomplete# triggers picker# triggers picker
Block ref autocomplete(( triggers picker(( triggers picker
Slash command autocomplete//
Toggle TODO/DONE on currentCtrl+T / Ctrl+EnterCmd/Ctrl+T / Cmd/Ctrl+Entertap checkbox / long-press menu
Run code blockg x chordCmd/Ctrl+Xtap “Run”

Visual mode (range)

TUI + desktop (vim on); mobile has no Visual equivalent yet.

ActionTUIDesktop
Extend selection downj / j /
Extend selection upk / k /
Yank rangeyy
Delete rangedd
Leave VisualEscEsc

Overlays (picker, palette, settings, help)

ActionTUIDesktop
Highlight next / Tab / Ctrl+J
Highlight previous / Shift+Tab / Ctrl+K
ConfirmEnterEnter
Close overlayEscEsc

The picker (Cmd+P / Ctrl+P) fuzzy-matches pages and journals together; type a date in ISO (2026-06-04) or natural (today, yesterday) to jump.


Where each chord lives in the code

LayerFileWhat it owns
Canonical catalogcrates/outl-shortcuts/src/defaults.rsEvery (mode, chord, action, description) row.
Action enumcrates/outl-shortcuts/src/action.rsThe named operation each chord resolves to.
TUI input adaptercrates/outl-tui/src/input/*.rscrossterm::KeyEvent → Chord.
Desktop input adaptercrates/outl-desktop/src/lib/shortcuts.tsKeyboardEvent → Chord.
Desktop dispatchercrates/outl-desktop/src/lib/action-handlers.tsAction → Tauri command.
Mobile toolbar / gesturescrates/outl-mobile/src/components/Per-component on-screen handlers.

A chord change is a single line in defaults.rs plus, if the action is new, a row in action.rs and a handler in each client. See crates/outl-shortcuts/CLAUDE.md for the full add-a-binding checklist.


Help overlay vs. this doc

In the TUI, press ? (Normal mode) to see the live chord table baked into the binary — it’s generated from the same default_bindings() table this doc describes. In the desktop, Cmd+/ opens the same overlay. If you need to look something up while typing, the in-app overlay is faster than this page.

This doc exists so a contributor (or a user shopping for outl) can see every shortcut without launching the app.