Your first week with outl
Your first week with outl
This is a tutorial, not a reference. We’re going to take a real week’s worth of notes, and at each step I’ll point at the outl feature that handles it. By the end you’ll know enough to live in outl daily.
If you want the dense version, jump to Getting started and the TUI manual. Otherwise, keep reading.
Day 0 — Install and open
git clone https://github.com/avelino/outl.git
cd outl
cargo build --release
cp target/release/outl ~/.local/bin/ # or wherever your PATH leads
Pick a directory for your notes. Doesn’t matter where:
outl init ~/notes
outl --path ~/notes
Today’s journal opens. The screen looks like this:
┌Pages────────┬─outl · default-dark · ws:notes pages:0 blocks:1 ──────────┐
│ │ Journal · Monday, 2026-05-25 │
│ ├───────────────────────────────────────────────────────────┤
│ │ │ - ▏ │
│ │ │
│ │ │
│ │ │
│ ├──── NORMAL i edit o new h/l cursor … q quit ────────┤
└─────────────┴───────────────────────────────────────────────────────────┘
You’re in Normal mode. The cursor is on the empty first block. Time to type.
Day 1 — First thoughts
Press i to enter Insert mode. The header changes to [INSERT].
Type:
read kleppmann's tree CRDT paper today
Press Esc. You’re back in Normal. Press o to make a new block
below:
- read kleppmann's tree CRDT paper today
- the move-with-cycle case is the interesting one
- I wonder how Yrs handles char-level concurrent edits
Notice: each Esc or Enter from Insert mode wrote your .md to
disk and reconciled it. You can cat ~/notes/journals/2026-05-25.md
right now in another shell and see it.
.md is clean — no id::, no UUIDs:
$ cat ~/notes/journals/2026-05-25.md
- read kleppmann's tree CRDT paper today
- the move-with-cycle case is the interesting one
- I wonder how Yrs handles char-level concurrent edits
The IDs live in .2026-05-25.outl (dotfile). You’ll basically
never look at it.
Day 2 — Linking
Today you have a meeting with someone named Avelino. Press ] to
navigate to tomorrow’s journal — wait, that’s tomorrow. Press [
to go back. Press t to go to today.
Press o for a new block, i to type, then:
met with [[Avelino]]
The moment you start typing [[Av an autocomplete popup appears.
It’s empty because you don’t have a page for Avelino yet. Type
elino]] to close the brackets, press Esc.
Move the cursor onto the link (the cyan Avelino). Press Enter.
Boom: outl created pages/avelino.md with title:: Avelino at the
top, and put you on the new page. Type the meeting notes here. When
you’re done, press q then outl --path ~/notes again — or just
press [ to go back to today’s journal.
The link in your journal still points at the page. Open today again:
t. The block with [[Avelino]] now renders the link cyan-underlined
because the target exists.
Day 3 — Tags
You realize you want to group reading lists. Add a block:
read MIT 6.824 lecture 4 #lecture #distsys
#tags work the same as [[refs]] — they resolve to pages
(pages/lecture.md, pages/distsys.md), but the syntax is one token
without brackets.
Open one: cursor over #distsys, press Enter. outl creates the
page and lands you on it. Add a block:
list of papers and lectures grouped under this tag
Press B. The right pane opens: Backlinks. It shows every block
in the workspace that references distsys. So far, just the line in
today’s journal.
Press B again to hide. Press q to go back, then t to land on
today.
Day 4 — Hierarchy
You want to nest some bullets. In Normal mode, hover the block:
read MIT 6.824 lecture 4 #lecture #distsys
Press i, position cursor at the end, then Enter (or Esc + o)
to make a new block, type:
key concept: vector clocks
Press Tab to indent — it becomes a child of the lecture block.
Press Esc, o, type:
contrast with HLC (what outl uses)
Tab again. Now you have:
- read MIT 6.824 lecture 4 #lecture #distsys
- key concept: vector clocks
- contrast with HLC (what outl uses)
You can see the indent guides (│) on the left of the nested blocks.
That’s the outline rendering. Indents work to any depth.
Day 5 — Editing prose with markdown
Add a block, press i, type:
**important:** the merge algorithm is *provably* convergent. see `apply_op`.
Press Esc. The block now renders with markdown applied: important
in bold, provably in italic, apply_op in code green. The
asterisks and backticks disappear in display.
Move to that block again (j / k). Press i. The asterisks
come back — outl shows the raw source while you’re editing so the
cursor columns line up with bytes. Press Esc and they vanish again.
Links work too: [outl](https://outl.app) becomes a blue underlined
outl when you’re not on the block, raw text when you are.
Day 6 — Finding stuff
Your workspace now has a journal entry per day, three named pages
(Avelino, lecture, distsys), and a bunch of blocks. Finding
things:
Ctrl+P— quick switcher. Fuzzy match by title or filename. Typedistanddistsysjumps to the top./— workspace-wide search. Type a fragment of any block. Hits show page label + snippet; Enter jumps you to the block. After the popup closes,nandNwalk through the rest of the matches.:— command palette.:open Avelinoopens by title.:todayjumps to today’s journal.:theme nordswaps the theme.:qquits.
Try them. Press ? if you forget a key — the help popup lists
everything.
Day 7 — Power moves
A few things that compound:
u/Ctrl+R— undo / redo. Bounded at 200 steps. Cursor position is restored too.K/J(orAlt+↑/↓) — move the current block (with its subtree) up or down among its siblings.yy— yank the current block (and its subtree).ppastes after,Ppastes before. Works in Visual mode too: pressV, extend withj/k, theny.Ctrl+Enter— cycle the block’s TODO/DONE/none prefix. In Insert mode it cycles inline without moving your cursor relative to the text.Ctrl+L— re-read the workspace from disk. Useful when another editor changed a.mdbehind your back.Ctrl+S— force save. (Edits auto-save on every commit, but this is for muscle memory.)
You’re now using outl roughly the way it’s meant to be used.
Coming from Logseq or Roam?
You don’t have to retype anything:
# Logseq graph directory:
outl import logseq ~/path/to/logseq-graph ~/notes
# Roam JSON backup:
outl import roam ~/Downloads/avelino-backup.json ~/notes
The importer strips id:: lines (Logseq), resolves ((uid)) block
refs to [[Page Title]] links, converts Roam’s {{[[TODO]]}} to
outl’s TODO prefix, and slugifies filenames so [[Meu Projeto]]
lands at pages/meu-projeto.md (with title:: Meu Projeto).
Anything that can’t be resolved stays in the file as
((unresolved:UID)) so you can grep and fix it manually.
What’s next
- TUI manual (docs/tui.md) — full keymap, every overlay, every command, persistence behavior.
- Theming (docs/theming.md) — six presets, how to add your own.
- Sync, done right (docs/sync.md) — what makes the CRDT interesting. Phase 2 will ship the actual P2P sync.
- Roadmap (docs/roadmap.md) — what’s coming.
If something feels off, open an issue. If you wrote a patch, the contributing guide tells you what reviewers look at.