Fast, native Markdown notes with links, tags and backlinks
  • Rust 98.8%
  • Shell 1.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Jack 55d62572a6
All checks were successful
CI / deny (push) Successful in 2m25s
CI / test (push) Successful in 4m50s
Release / release (push) Successful in 6m2s
Merge pull request 'hardening/sync-safety' (#4) from hardening/sync-safety into main
Reviewed-on: #4
2026-10-12 20:41:29 -04:00
.forgejo/workflows L-404: weekly advisory check and deep property run; more cases in CI 2026-10-12 14:46:11 -04:00
.github/workflows L-404: weekly advisory check and deep property run; more cases in CI 2026-10-12 14:46:11 -04:00
assets/icon Add app icon, README, packaging and CI 2026-10-01 00:32:02 -04:00
docs Release 0.3.0: version bump and changelog 2026-10-12 20:36:13 -04:00
packaging Release pipeline: verify tag matches Cargo.toml, gate releases on clippy and tests 2026-10-03 01:22:21 -04:00
proptest-regressions L-501: Markdown links to notes are links 2026-10-12 14:53:57 -04:00
scripts Ready for 0.1.0 2026-10-02 22:58:33 -04:00
src Tab strip: give the close button its own slightly different background 2026-10-12 20:29:16 -04:00
.gitignore Add app icon, README, packaging and CI 2026-10-01 00:32:02 -04:00
build.rs L-005: add rustfmt.toml and reformat the tree (formatting only) 2026-10-12 02:16:21 -04:00
Cargo.lock Release 0.3.0: version bump and changelog 2026-10-12 20:36:13 -04:00
Cargo.toml Release 0.3.0: version bump and changelog 2026-10-12 20:36:13 -04:00
CHANGELOG.md Release 0.3.0: version bump and changelog 2026-10-12 20:36:13 -04:00
clippy.toml Prepare 0.2.0: version, changelog, README, deny unwrap() outside tests 2026-10-03 00:24:57 -04:00
deny.toml fix: drop version key from cargo-deny license exception 2026-10-02 14:49:49 -04:00
LICENSE Prepare 0.1.0 release: license, changelog, checksums, CLI flags 2026-10-01 02:22:17 -04:00
Makefile Makefile 2026-10-01 10:17:17 -04:00
README.md L-506: outline tab and preview that follows the editor's scroll 2026-10-12 15:34:33 -04:00
rustfmt.toml L-005: add rustfmt.toml and reformat the tree (formatting only) 2026-10-12 02:16:21 -04:00

robsidian icon

robsidian

A fast, native Markdown notes app in the spirit of Obsidian. Your notes are plain .md files in a folder (a "vault"), connected with [[wikilinks]], tags and backlinks. It is written in Rust with egui: no Electron, no web view, one small executable that starts instantly.

Features

Writing

  • Plain-text editor with Markdown highlighting, tabs (drag to reorder), and a live preview pane that follows the editor as you scroll or type.
  • An Outline tab in the sidebar lists the note's headings; click one to jump to it.
  • Lists that behave: Enter continues a list, Tab and Shift+Tab indent, an empty item outdents, - [ ] checkboxes tick with Ctrl+Space.
  • Wrapped list items hang under their text, in the editor and the preview.
  • In the preview, - [ ] task boxes can be clicked to tick them (the note is edited and saved like any change), callouts (> [!note] Title) show their title in bold, and raw HTML shows its text (<br> breaks the line, comments stay hidden) instead of disappearing.
  • Tables: shown in the preview with columns sized to their content. In the editor, Tab and Shift+Tab move between cells (Tab at the end adds a row), Enter moves down a row, and the table is re-aligned as you go. Ctrl+Alt+T formats the table at the cursor.
  • Multiple cursors (Ctrl+Alt+Up/Down), find and replace in a note, and vault-wide search and replace.
  • Each note keeps its own undo history. Notes you edit are saved with exactly one trailing newline.
  • The note's name is shown as an editable header; change it to rename the file.
  • Bash-style Tab completion for [[links]] and #tags, one path level at a time. The list of matches also opens while you type a link (click one to complete it; Esc closes it for that link).

Linking

  • [[Note]], [[folder/Note]], [[Note#Heading|alias]]; links resolve relative to the note's folder.
  • Backlinks, and aliases: in a note's properties as alternative names for links.
  • Markdown links work too: [text](Note.md), [text](../folder/My%20Note.md#heading). They count as backlinks, and they follow renames and moves of the note they point at and of the note holding them.
  • Renaming or moving a note (F2, or drag it in the file tree) rewrites every link that pointed at it.

Organising

  • Inline #tags and tags: in properties, shown nested in a Tags pane. Rename a tag everywhere from its context menu.
  • Frontmatter properties are shown and edited in a panel; your YAML formatting is preserved.
  • Daily notes, a quick switcher with recent notes, and a collapsible file tree.

Media

  • Images and embeds in the preview: ![[pic.png|300]], ![alt](path.png), ![[Note]], and ![[Note#Heading]].
  • Paste an image from the clipboard, or drop files onto the editor: they are saved as attachments in a folder you choose and linked automatically.

Safety

  • Ordinary note and metadata saves use atomic replacement, so a failed save does not leave a partially written file. This is not an fsync or power-loss durability guarantee. If a save fails, the text stays in the editor with a banner and nothing that would lose it can proceed, including quitting.
  • If a note changes externally while it has local edits, robsidian stops automatic saving and requires an explicit choice to overwrite the external file or reload it and discard local edits. The check narrows ordinary races but cannot provide an OS-level compare-and-swap guarantee.
  • Vault-wide replace, tag rename, rename/move and delete can be undone (Ctrl+Alt+Z). Files you edited since are never overwritten by an undo. Failed multi-file operations report whether rollback or recovery also failed, so any remaining work is visible rather than claimed as successful.
  • Notes are only ever ordinary files; deleting goes to the vault's .trash, the system trash, or is permanent, as you choose.

Make it yours

  • Settings window (Ctrl+,): theme, fonts (including your own font file), colours, layout, daily note and attachment locations, excluded folders, and every keyboard shortcut is rebindable.

Install

Download the package for your system from the Releases page.

  • Linux: unpack the .tar.gz, run ./install.sh (installs to ~/.local, no root needed; add --uninstall to remove). Or just run the robsidian binary.
  • Windows: unzip and run robsidian.exe. Windows SmartScreen may warn about an unrecognised app because the build is not code-signed.
  • macOS: unzip and move robsidian.app to Applications. It is not code-signed or notarised, so the first time, right-click it and choose Open.

Each release also has a SHA256SUMS file; check a download with sha256sum -c SHA256SUMS (Linux) or shasum -a 256 -c SHA256SUMS (macOS). The Linux package from the GitHub release is built on Ubuntu 22.04 on purpose, so it needs glibc 2.35 or newer and runs on most current distributions. A package built by the Forgejo workflow uses the glibc of that runner's image. robsidian --version prints the version.

Start it with a folder to open that vault directly:

robsidian ~/Notes

Otherwise use "Open vault..." on the welcome screen, or type a folder path there. A path that does not exist yet can be created as a new vault, with a short welcome note to start from. Vaults you have opened are listed on the welcome screen, and the last one is reopened next time.

Keyboard shortcuts

These are the defaults; all of them can be changed in Settings. On macOS read Ctrl as Cmd.

Shortcut Action
Ctrl+O Quick switcher (recent notes first)
Ctrl+N New note
Ctrl+Shift+D Open today's daily note
Ctrl+E Toggle the preview pane
Ctrl+W Close tab
Ctrl+Tab, Ctrl+Shift+Tab Next, previous tab (Ctrl+1 to 9 jump to a tab)
Ctrl+F, Ctrl+H Find, find and replace in the note (F3, Shift+F3 for next, previous)
Ctrl+Shift+F, Ctrl+Shift+H Search, search and replace in the vault
Ctrl+Space Tick or untick a checkbox
Ctrl+Alt+T Format the table at the cursor (Tab, Shift+Tab and Enter navigate cells)
Ctrl+Alt+Up, Ctrl+Alt+Down Add a cursor above or below
Ctrl+= , Ctrl+- , Ctrl+0 Larger, smaller, reset note font
Ctrl+Shift+I Paste an image from the clipboard
F2 Rename the current note in the file tree
Ctrl+Alt+Z Undo the last vault-wide change
Ctrl+, Settings

In the editor, Ctrl+click on a [[link]] or #tag follows it, and middle-click or Ctrl+Shift+click opens a link in a new tab. Shift+Enter inserts a plain newline.

Where things are stored

  • Your notes are .md files; nothing is locked in. Images and other attachments are ordinary files.
  • <vault>/.notebook/settings.json holds the per-vault settings (daily notes, new-note location, attachments, excluded folders, trash behaviour). It travels with the vault.
  • App-wide settings are in settings.json under your config directory (~/.config/robsidian on Linux, ~/Library/Application Support/robsidian on macOS, %APPDATA%\robsidian on Windows). Your open tabs and recent notes are kept there too, in workspaces/, so two devices that share a vault through a sync tool each keep their own and never conflict. (Earlier versions kept them in <vault>/.notebook/workspace.json; it is read once and then no longer used, and you can delete it.) All of these are plain JSON and safe to edit; a file that fails to parse is copied to .bak rather than overwritten.

Using a vault with Syncthing (or Dropbox, Nextcloud, ...)

A vault is an ordinary folder, so any file sync tool works. What robsidian does about it:

  • Changes from other devices appear on their own. A sync run that delivers many files is applied as one batch, so the app stays responsive. A note you have open and have not edited is reloaded; if you have unsaved edits, you are asked whether to keep yours or take the other one. Nothing is overwritten silently, and a note that appears at a name you were about to create or move to is never replaced.
  • Sync tool bookkeeping is ignored. Anything starting with a dot (.git, .stfolder, .stversions, .trash, .syncthing.*.tmp), ~syncthing~* temporary files, and robsidian's own temporary files are not notes and are not indexed. Leftover temporary files from an interrupted save are removed after an hour, when a vault opens.
  • Conflict copies are shown, not hidden. When two devices change the same note, the sync tool keeps both, naming one Note.sync-conflict-<date>-<device>.md. It is an ordinary note, listed in the file tree in the warning colour. Compare the two, keep what you want, delete the other.
  • Accented names match on every system. macOS stores é in file names as e plus an accent, other systems as one character. Links, aliases and attachments are compared in a normalised form, so [[Café]] finds the note whichever way the file arrived. File names are never changed.
  • Open tabs belong to the device. They are stored in the app's config directory, not in the vault, so two machines never fight over them.
  • Per-vault settings follow the vault. <vault>/.notebook/settings.json (daily notes, attachments, excluded folders) is synced like a note.

Good practice: let one device at a time edit a given note, and add .trash/ to your sync tool's ignore list if deleted notes should not reappear on other devices (or keep it synced as a shared safety net, your choice). Notes over 32 MiB, and files that are not UTF-8, are skipped and listed in a notice in the window.

Build from source

You need a Rust toolchain. The helper script installs one inside the repository (nothing global):

scripts/setup_toolchain.sh        # or use your own rustup; see --help for options
source scripts/setupenv.sh        # puts the local toolchain on PATH
cargo run --release -- ~/Notes

scripts/setupenv.sh also sets display variables for WSLg; if you are not on WSL, skip it and use cargo directly.

On Linux the app loads graphics and windowing libraries at run time. If it fails to start, install them, for example on Debian or Ubuntu:

sudo apt install libxkbcommon-x11-0 libwayland-client0 libgl1 libegl1 libx11-6 libxcursor1 libxrandr2 libxi6

The folder picker needs an xdg-desktop-portal backend; without one, type the vault path instead.

Notes on platforms

  • Screen readers: the interface exposes an accessibility tree (AccessKit: UI Automation on Windows, NSAccessibility on macOS, AT-SPI on Linux). It has not been tested with a screen reader yet, so reports are welcome.

  • Fonts: the built-in fonts do not cover Chinese, Japanese or Korean. At start-up robsidian looks for a common system font that does (Noto Sans CJK, WenQuanYi, Droid Sans Fallback on Linux; Microsoft YaHei, Yu Gothic, Malgun Gothic, Meiryo on Windows; PingFang, Hiragino on macOS) and uses it for those characters only. If your text still shows boxes, pick a font file in Settings, Appearance.

  • Developed and tested mainly on Linux (including WSL2 with WSLg). The Windows and macOS builds are produced by CI but have had less hands-on testing.

  • Title bar: Windows and macOS use the system's by default; Linux uses a built-in one (many compositors, including WSLg's, draw none). Change it in Settings, Window. Moving a borderless window was choppy on some Windows setups, which is why the system bar is the default there.

  • Pasting images: the clipboard is read through the system clipboard, then wl-paste, xclip, and, on WSL, PowerShell. Press Ctrl+Shift+I to see why a paste found nothing.

Development

cargo test --all-targets
cargo clippy --all-targets -- -D warnings

CI runs both on every push and pull request. Workflows for GitHub live in .github/workflows/ (Linux, macOS and Windows on every push and pull request, plus a weekly advisory and deep property-test run); workflows for Forgejo and Gitea live in .forgejo/workflows/, which Forgejo prefers when present. Pushing a tag such as v0.1.0 builds the release packages and attaches them to a release. On Forgejo the Windows package is cross-compiled from Linux with MinGW (x86_64-pc-windows-gnu); macOS packages need a macOS runner (GitHub).

To build the Windows executable yourself on Debian or Ubuntu:

sudo apt install gcc-mingw-w64-x86-64 binutils-mingw-w64-x86-64
rustup target add x86_64-pc-windows-gnu
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc \
  cargo build --release --target x86_64-pc-windows-gnu

Source layout (src/):

Path Responsibility
app/ The egui application: layout, tabs, panels, dialogs, input handling, background work
vault/ The vault: mod.rs scan and reload, index.rs links/backlinks/tags/attachments, links.rs wikilink text, mutate.rs create/save/move/trash/replace, undo.rs, state.rs file identity and conditional saves, names.rs name rules
session.rs, recovery.rs, worker.rs Open notes and their save/conflict state, crash recovery, background search
fsutil.rs, paths.rs Atomic file writes, config locations
editor.rs, preview.rs Editor highlighting; rendering Markdown, images and embeds
lists.rs, tables.rs, multicursor.rs, complete.rs List and table editing, extra cursors, Tab completion
frontmatter.rs, tags.rs, embed.rs, find.rs, prose.rs Properties, tags, embed and attachment logic, search, prose-only text scanning
settings.rs, keys.rs, appearance.rs Settings files, rebindable shortcuts, theme and fonts
clipboard.rs, workspace.rs, config.rs Clipboard images, per-vault state, app state

Most logic lives in small modules with unit tests that need no display.

License

MIT. See LICENSE. Release notes are in CHANGELOG.md.