- Rust 98.8%
- Shell 1.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| .github/workflows | ||
| assets/icon | ||
| docs | ||
| packaging | ||
| proptest-regressions | ||
| scripts | ||
| src | ||
| .gitignore | ||
| build.rs | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| clippy.toml | ||
| deny.toml | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| rustfmt.toml | ||
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
#tagsandtags: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]],,![[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
fsyncor 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--uninstallto remove). Or just run therobsidianbinary. - 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.appto 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
.mdfiles; nothing is locked in. Images and other attachments are ordinary files. <vault>/.notebook/settings.jsonholds 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.jsonunder your config directory (~/.config/robsidianon Linux,~/Library/Application Support/robsidianon macOS,%APPDATA%\robsidianon Windows). Your open tabs and recent notes are kept there too, inworkspaces/, 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.bakrather 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 aseplus 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.