Local-first outliner. Markdown is the source of truth. Sync that doesn't corrupt your tree when two devices edit offline.
Inspired by Roam Research and Logseq.
Tree CRDT sync (Kleppmann et al. 2022), per-device append-only op log, IDs in a sidecar so the .md you see is the .md you wrote.
- Why outl? → outl.app/docs/why-outl.html
- Sync, done right: → outl.app/docs/sync.html
- CRDT walkthrough: → outl.app/docs/crdt.html
# macOS / Linux via Homebrew (beta channel — every push to main)
brew tap avelino/outl https://github.com/avelino/outl
brew trust avelino/outl # one-time, third-party tap
brew install outl-beta # TUI/CLI/MCP
brew install --cask outl-desktop-beta # GUIiOS beta on TestFlight: join here. Point the TUI at the same iCloud Drive container (<container>/Documents/) and both clients share a workspace.
- From source / channels: → getting started, homebrew
outl init ~/notes # scaffold a workspace
outl --workspace ~/notes # opens the TUI on today's journalPress ? for keymap, : for the command palette, Ctrl+P to fuzzy-jump.
outl import logseq ~/path/to/logseq-graph ~/notes
outl import roam ~/Downloads/backup.json ~/notesThe importer strips id:: lines, resolves ((uid)) block refs to page links, slugifies filenames, seeds the sidecars. Anything it can't resolve stays as ((unresolved:UID)) for manual triage.
The engineering decisions behind outl on avelino.run:
- File sync isn't trivial — why concurrent file moves are a distributed-systems problem that Dropbox and Google Drive still get wrong.
- From paper to outliner — the gap between "the CRDT converges" and "the app ships": projections, content-addressable reconciliation, surviving iCloud's lazy materialisation.
MIT.