Skip to content

Latest commit

 

History

584 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

outl

outl

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.

Install

# macOS / Linux via Homebrew (beta channel — every push to main)
brew tap outlmd/outl https://github.com/outlmd/outl
brew trust outlmd/outl # one-time, third-party tap
brew install outl-beta # TUI/CLI/MCP
brew install --cask outl-desktop-beta # GUI

iOS beta on TestFlight: join here. Point the TUI at the same iCloud Drive container (<container>/Documents/) and both clients share a workspace.

Android: a signed arm64 APK (outl-android-arm64.apk) rides every release. Sideload-only for now — not on Play, and each release is signed with a fresh key, so a new build means uninstalling the old one first (#171).

Quick start

outl init ~/notes              # scaffold a workspace
outl --workspace ~/notes       # opens the TUI on today's journal

Press ? for keymap, : for the command palette, Ctrl+P to fuzzy-jump.

Optional: an always-on peer

You don't need a server. Pair your laptop and your phone and they sync directly, P2P. That's the normal setup.

But P2P converges only when two devices can reach each other, and a laptop shut at 18:00 never overlaps a phone edited at 22:00. If that's you, a third device that never sleeps closes the gap — on hardware you own.

docker compose build
outl peer pair --name laptop                                  # on a device that HAS your notes
docker compose run --rm outl peer pair --ticket <ticket>      # the server joins
docker compose up -d

Not a server your notes sync through — no account, no upload, nobody else's infrastructure holding your graph. Just one more peer that happens to be awake all the time, holding a full replica of the op log. Turn it off and your other devices carry on talking to each other. Self-hosting guide.

Coming from Logseq or Roam?

outl import logseq ~/path/to/logseq-graph ~/notes
outl import roam ~/Downloads/backup.json ~/notes

The importers (Roam, Logseq, Obsidian — or auto to detect) resolve ((uid)) block refs and {{embed}}s into real outl block references, keep folded state, and translate each dialect. Everything touched is counted in the import report — run with --dry-run first to measure fidelity against your backup. Anything unresolvable stays as ((unresolved:UID)) for manual triage.

Contributing

Background reading

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.

License

MIT.

About

Local-first outliner. Markdown is the source of truth. Sync that doesn't corrupt your tree when two devices edit offline

Topics

Resources

Contributing

Security policy

Stars

172 stars

Watchers

7 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages