A fast, local, Logseq-compatible outliner.
Reads and writes the same markdown graph as Logseq β swap between the two on the same files.
Tine is a desktop outliner built to look and feel like Logseq while being
much faster. It operates directly on the standard Logseq graph layout β
journals/, pages/, assets/, and logseq/config.edn β so you can point it at the graph you
already use and keep editing in either app (one at a time). Files are written back in
Logseq-compatible markdown, so there's no import/export step and no lock-in.
Why build it? Logseq's UI is Electron + DataScript with heavy re-rendering, and it gets sluggish on large graphs. Tine is a ground-up rewrite: a small native shell (Tauri/WebKitGTK), a pure-Rust core for parsing and indexing, and a fine-grained reactive frontend (SolidJS) that never diffs a virtual DOM. The editor keeps the live block tree in the frontend, so keystrokes never round-trip to Rust, and whole-graph reads (search, backlinks, queries) hit an in-memory cache instead of re-parsing.
Status: a usable daily-driver for outlining, linking, tasks, journals, search, queries, and PDF annotation. Linux is the primary, best-tested platform; macOS and Windows builds are produced too but are newer. Not yet 1.0 β see Roadmap.
Grab a prebuilt installer from the Releases page. The builds aren't code-signed yet, so your OS may warn the first time β here's how to get past it:
- Linux β the AppImage runs on any distro with no install:
chmod +x Tine_*.AppImage, then run it. Or use the.deb(Debian/Ubuntu) or.rpm(Fedora/openSUSE). - macOS β open the
.dmg; on first launch macOS says "unidentified developer", so right-click the app β Open (just once) and it opens normally after that. - Windows β run the
.exe; if SmartScreen appears, click More info β Run anyway.
(Want to hack on Tine instead? Build from source β see Build & run.)
These are the things that started as "I wish Logseq did this" β Tine's reasons to exist beyond raw speed. (Where a comparison is made, it's against current Logseq desktop core, no plugins.)
- β‘ Native speed. Pure-Rust core + SolidJS fine-grained reactivity (no virtual-DOM diffing) + a tiny Tauri/WebKitGTK runtime instead of Electron. Typing stays in the frontend tree; reads hit an in-memory index.
- ποΈ Built-in tabs. Middle-click any bullet, page title, query result, or switcher row to open
it in a background tab; pin (persisted), drag-reorder,
Mod+Wto close. Logseq core has no tabs (only a right sidebar or a whole separate window). - β―οΈ Browser-style back/forward, bound to
Alt+Left/Alt+Rightby default (per-tab history; works mid-edit). (Logseq has back/forward too, but defaults toCtrl/Cmd+[and].) - π― Focus mode + dim-inactive-blocks (
t f/t b): hide the chrome and fade everything but the block you're working on, with Logseq-style layeredEsc(editing β block-select β exit focus). No Logseq-core equivalent. - β‘ Global quick-capture β bind
tine --captureto a desktop hotkey and a small always-on-top box pops from any app, with the full editor (autocomplete, slash commands, the date picker, nested blocks), and files a bullet to today's journal. Logseq's quick-add only works when the app is already focused. - π Carry unfinished tasks forward to today (presets for the last 7 / 30 / 365 days or a configurable N), optionally keeping ancestor context.
- π A real data-safety story (see below) β conflict detection instead of silent overwrites, launch snapshots with one-click restore, and delete-to-trash. Built to live safely on a graph you also edit from Logseq mobile over Syncthing.
Outliner
- Click-to-edit blocks; the click lands the caret exactly where you clicked.
Enter/Tab/Shift+Tab/Backspace/ arrows with correct Logseq semantics and caret preservation (no reflow on indent/outdent); arrow nav respects visual wrapped rows. - Collapse/expand, zoom into a block (with breadcrumb), drag-to-reorder, move up/down
(
Alt+Shift+β/β), multi-block selection β move / indent / cut / copy. - Multi-line blocks, syntax-highlighted code blocks, markdown tables; paste an indented outline β real block tree; paste clipboard images β graph assets.
- Media β paste/import images, video, and audio (
/upload); stored aswith aname_yyyymmdd_hhmmssfilename (keeps the origin + a sortable insert time). Drag the corner grip to resize an image (stored as a width % in Logseq's{:width β¦}brace, so it round-trips). Video/audio play inline where the codec is supported, else fall back to a click-to-open chip that launches the OS default player. Orphaned-media cleanup (Settings β Backups): scan forassets/files no block references and move them to the recoverable trash β deleting a block never deletes its media, so this is how unused files get reclaimed. - Inline formatting (
Mod+B/I, strike, ==highlight==, link) with a floating selection toolbar, plus Emacs-style word/line kill motions. - Callouts/admonitions β both Obsidian-style
> [!note] β¦and org#+BEGIN_NOTE β¦ #+END_NOTEblocks render as colored callouts (QUOTEstays a plain blockquote) β and a live/calcblock that evaluates arithmetic as you type (+ - * / ^ %, parentheses,name = exprvariables across lines, a running result).
Linking, references & queries
[[page]],#tags,#[[multi word]],((block ref))β including the labeled form[text](((id)))β and{{embed}}β all clickable, with autocomplete on[[,#,((, and/. The((popup full-text-searches blocks and inserts a durable reference (writes a stableid::first). The[[/#Enter default is configurable (Settings β Journals & tasks β Link autocomplete default): create-a-new-page (default, like Logseq) or link-the-first-match.- Linked & unlinked references on every page (live/editable), with co-reference filtering and hover previews.
- Per-block reference count: a referenced block shows a small count badge β click it to reveal the blocks that reference it (grouped by page), or shift-click to open the block in the sidebar.
{{query}}engine (inline or whole-block): boolean and/or/not,(task β¦),(priority β¦),(property β¦),(page-property β¦),(page-tags β¦),(scheduled),(deadline),(journal),(namespace β¦),(between START END)with a field selector,(sort-by β¦). Results render as a list or a sortable table; an interactive visual query builder (chip/clause bar) builds them without writing the DSL.- A scoped compatibility path for Logseq's advanced (Datalog) queries: recognized clauses
(
task,between,property,page-property,priority, page-refs, booleanor/and/not, and:today/:current-page-style inputs) map onto the same engine, and any unsupported part is flagged in the result rather than silently dropped or wrongly answered.
Tasks, journals & dates
TODO/DOING/DONE/NOW/LATER/WAITING/CANCELED, two configurable workflows, priorities, cycle withMod+Enter.- In-block markdown lists & checklists β a
+/*/ordered list inside one bullet's content renders as a styled list (distinct from outline bullets), with tickable[ ]/[x]checkboxes that are not TODO/agenda tasks. Uses+(OG's in-content marker), so a checklist round-trips to OG and Logseq mobile. (-stays the outline bullet, exactly like OG.) SCHEDULED:/DEADLINE:via a calendar date picker (/scheduled,/deadline), including recurring tasks (+1w/.+1w/++1w) where completing a repeater advances the date.- Multi-day journal feed (one continuous editable list); today's journal created lazily on
first edit; move blocks across days; an agenda of open scheduled/deadline items (DONE and
CANCELED are hidden, like OG) in a configurable look-back/-ahead window; journal templates; a
calendar with content markers whose first day
of week follows your
config.edn :start-of-week(any of the seven days, settable in-app).
PDF annotation
- Open PDFs in a resizable, zoomable pane (instant zoom, HiDPI, per-page virtualization); in-PDF
Ctrl+Ffind with a page jump box. - Select text β colored highlights, or drag a rectangle (area mode /
Ctrl-drag) to clip an area (image) highlight β both stored Logseq-compatibly (assets/<key>.edn+hls__pages, area crops as PNG assets). Each highlight becomes a clean bullet you can nest notes under; writes merge with disk so an externally-added highlight or your top-level notes are never dropped, and recoloring a highlight updates its note-page badge to match.
Search & navigation
Ctrl+Kquick switcher: page titles + full-text content hits (visible text only β no false hits on hidden properties/uuids), with block breadcrumbs and middle-click β background tab.- Command palette (
Mod+Shift+P), favorites, recent pages, a collapsible namespace tree in the sidebar, the{{namespace X}}macro (a bold "Namespace" header + nested descendant tree), an automatic "Hierarchy" section (breadcrumb paths of descendant pages) on any namespaced page, and read-only "aka" alias chips on pages reachable by another name. - Page icons β a page's
icon::emoji shows next to its title and in the namespace tree. Emoji render as bundled Twemoji SVG images (not a font), so they show in every engine β including WebKitGTK, which paints color-emoji webfonts blank β and work offline. - Page rename (double-click a title) rewrites every
[[ref]]/#tagacross the graph in one transaction (see data-safety, below).
Works with your existing setup
- Edit safely alongside Logseq mobile over Syncthing. A filesystem watcher β inotify by default (zero idle wakeups), with a polling fallback for filesystems where inotify misses edits, switchable in Settings β reconciles changes synced in from other devices, and Tine never silently overwrites a file that changed on disk β it surfaces a conflict instead. Saves preserve each file's exact formatting (tabs vs spaces, comments, compact EDN) and skip byte-identical rewrites, so they don't create sync diff churn.
- Page rename is transactional β the page move and every
[[ref]]/#tagrewrite across the graph commit all-or-nothing, re-checking each file just before writing and rolling back on conflict, so a rename can't half-apply. - Custom journal date formats β reads
:journal/file-name-formatand:journal/page-title-formatand recognizes/creates journal files in your format (e.g.dd-MM-yyyy,yyyy-MM-dd,yyyyMMdd), falling back to the defaults so old/foreign files still resolve. The display-title format is pickable in Settings β Journals & tasks β Journal date format (file names are left as-is). - Duplicate-day reconcile β if two files ever resolve to the same day (e.g. a
2026_06_26.orgplus a title-namedFriday, 26-06-2026.orgleft over from a date-format change), Tine keeps both rather than silently dropping one, and Settings β Backups β Duplicate journal days lets you reach each file individually: Open it (editable, saves back to itself), Merge a stray into the canonical day, Rename it to a normal page, or Trash the redundant one. - Org-mode graphs β opens, renders, and edits
.orgpages and journals (headlines as blocks, org inline syntax*bold*/italic/_underline_~code~[[target][desc]], TODO markers,#+BEGIN_SRC/QUOTEblocks). Mixed.md+.orggraphs work; the File format setting (Settings β Journals & tasks,:preferred-format) chooses what new pages/journals use. A.orgfile is only ever rewritten when Tine can reproduce it byte-for-byte β anything it can't round-trip loads read-only, so it can never corrupt an org graph. - Launch snapshots (configurable keep-count) with a restore UI that takes a safety snapshot
first; page delete moves to a recoverable trash;
atomic_write+ fsync. - Open/switch graphs from the app (native folder picker) or via
TINE_GRAPH.
Customization & output
- Fully remappable keyboard shortcuts β in the Settings modal or via
config.edn :shortcuts. - Light/dark themes, accent color, custom CSS, wide mode (
t w) and document mode (t d). - One-click static HTML export (
public:: truepages), with math typeset by KaTeX; "copy/export as" for a block subtree or page as Markdown; a slash menu for headings, code, calculator, quote, callouts, divider, embed, query (raw or visual builder), template, asset upload, and dates.
| Layer | Tech | Notes |
|---|---|---|
| Shell | Tauri 2 (Rust) | OS webview (WebKitGTK on Linux) β tiny runtime vs Electron |
| Frontend | SolidJS + TypeScript + Vite | fine-grained reactivity, no virtual-DOM churn |
| Core | crates/tine-core (pure Rust) |
parse/serialize, model, indexing, queries, refs, dates, PDF/EDN, HTML publish |
| Rendering | pdf.js, KaTeX, highlight.js | PDF, math, code |
The Rust core is GUI-free and unit-tested in isolation; the Tauri layer is a thin set of ~41 IPC
commands over it. The frontend owns the live editing tree (normalized store) and pushes debounced,
format-preserving saves; whole-graph reads hit an in-memory page cache (RwLock<Arc<Graph>> β read
commands clone the Arc and release the lock immediately) keyed by a graph generation counter.
crates/tine-core/ Rust core: parse/serialize, model, config, dates, refs, query, pdf, edn, publish
src-tauri/ Tauri app β IPC commands + windows (main + quick-capture)
src/ SolidJS frontend (components, store, render pipeline, keybindings)
scripts/ env.sh (toolchain paths), screenshot generators
docs/ Logo, images, feature notes
samples/ Demo graph used by tests/screenshots
source scripts/env.sh # toolchain env (CARGO_HOME/RUSTUP_HOME, lib paths)
npm install # first time
# Build the release binary (NOT plain `cargo build` β that produces a dev-mode
# binary that can't connect to the bundled frontend):
npx tauri build --no-bundle
# Run it against your graph:
TINE_GRAPH=/path/to/your/graph ./target/release/tine- Point
TINE_GRAPHat the samejournals/+pages/+logseq/config.edntree you use with Logseq. Run one app at a time on a given graph. - GPU compositing (smooth scrolling) is on by default. On the rare GPU/compositor combo where
WebKitGTK's DMABUF renderer aborts (the window fails to appear, or you see
EGL_BAD_PARAMETERon the console), setTINE_GPU=0to fall back to software rendering β slower, but it always starts. If Tine detects it's painting on the CPU it now says so with a banner. - Prefer the raw binary over an AppImage on Linux β an AppImage's bundled graphics libraries can
clash with the host GPU and silently drop you to (slow) software rendering. The
.deb/.rpmpackages use your system's drivers and don't have this problem.
If Tine won't start cleanly (e.g. the window never appears), run it with debug logging on. It writes a timestamped trace to a file β the environment (renderer, session type, AppImage, graph), every startup milestone, any panic (with backtrace), and the frontend's own boot/errors β so one file is usually enough to diagnose it:
TINE_DEBUG=1 tine # or: tine --debug
TINE_DEBUG=1 ./Tine-*.AppImage # AppImageTine prints the log path on startup; it defaults to /tmp/tine-debug.log (override with
TINE_DEBUG_LOG=/path). Reproduce the problem, then send that file. The log records no note content
β only startup diagnostics.
Quick capture β at the top of the journal feed, a page-title field + a body composer: fill the
title to capture a new page, leave it empty to append to today, then Ctrl-Shift-Enter.
Global quick-capture: bind your desktop environment's keyboard settings to run
tine --capture (a second launch is routed to the running instance via single-instance).
npm run dev # frontend only, in a browser, against an in-memory mock backend
npm run app # full Tauri dev window (alias for: tauri dev)
node scripts/screenshot.mjs # regenerate screenshots from the mock backendsource scripts/env.sh
cargo test -p tine-core # Rust: parse/serialize round-trip, model, queries, search cache
npm test # Frontend: Vitest (editor ops, outline, autocomplete, markers, β¦)Round-trip parsing is validated against a real Logseq graph (0 structural diffs beyond accepted
canonicalization); tine-check is a privacy-safe profiler that proves byte-faithful serialization
without reading note content.
Planned / under evaluation: graph view, configurable typographic auto-replace, and broader coverage of advanced Datalog queries (a scoped subset works today β see above).
Out of scope (by design): whiteboards, flashcards, the plugin system, built-in git, and a native mobile app β Tine coexists with Logseq mobile over your own sync instead of replacing it.
Tine is an independent reimplementation, not a fork β the codebase is original Rust + SolidJS and contains no Logseq source. It does target Logseq's on-disk format and adapts parts of Logseq's outliner CSS (variables and bullet/indent rules), so it is a derivative work for licensing purposes and is released under the same license.
Logseq is Β© its authors, licensed AGPL-3.0. Tine is not affiliated with or endorsed by Logseq. Thanks to the Logseq project for the format and the design it pioneered.
Copyright (C) 2026 Martin KouteckΓ½.
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE for details.
Built ground-up as a faster, file-compatible alternative to Logseq. Not affiliated with Logseq.








