posts/2026-10-20 — less +F
VOMD: A Tiny, Fast View-Only Markdown Viewer for the Linux Desktop
I read a lot of Markdown.
READMEs, changelogs, notes, docs that ship inside a tarball. Most of the time I don't want to edit any of it. I just want to look at it, the way it would look on GitHub, and then close the window.
On my desktop that turned out to be weirdly awkward. Double-clicking a .md file either opened it as plain text, or launched something much bigger than the job: an editor with a preview pane, or a browser and an extension. Both work. Neither feels like "open this file and show it to me."
So I wrote VOMD, short for View-Only Markdown: a tiny, fast Markdown viewer for the Linux desktop.
Project Links
The problem: reading should be cheaper than editing
What I wanted was simple to describe:
- Double-click a
.mdfile - It appears, rendered the way GitHub shows it
- It appears now, not after a splash screen
That last part was the real requirement. If a viewer takes longer to open than it takes me to read the first paragraph, I'll go back to cat.
The approach: no web engine, no toolkit
The usual way to render Markdown is to turn it into HTML and hand it to a browser engine. That gets you a lot for free, and it also gets you a browser engine.
I went the other way and set myself a few hard constraints:
- One binary. The release build is a single 3.9 MB file.
- Fonts built in. Inter for text, JetBrains Mono for code, and Lucide for the icons are embedded, so it looks the same everywhere.
- No web engine and no GUI toolkit. VOMD parses with
pulldown-cmark, opens its window withwinit, shapes text withswash, and draws into a plain software buffer withsoftbuffer. Everything you see, it lays out and paints itself. - No network unless you ask. More on that below.
It's written in Rust, and the release profile is tuned for size (opt-level = "z", fat LTO, stripped). The result is that a document opens in well under a tenth of a second.
What it does
VOMD is view-only on purpose, but "view" covers more ground than I expected once I started using it daily.
Markdown coverage
It handles CommonMark and GitHub Flavored Markdown: tables, task lists, strikethrough, footnotes, alerts (> [!NOTE] and friends), and autolinks. YAML front matter is hidden, which matters for me because half my notes have it. Math and Mermaid show as text and code.
Raw HTML is never run. Tags are stripped and their text is kept, and a few tags (<b>, <img>, <a>, <br>, and similar) are rendered the way GitHub renders them.
Looks
Light and dark themes follow the system, and T cycles system, light, and dark. Zoom runs from 50% to 300% (Ctrl + = / - / 0, or Ctrl + wheel). HiDPI scaling follows the system scale factor.
Links and navigation
#anchors scroll within the document. Relative .md links open in the same window, and Back (Backspace, Alt+←) returns. Web links open in your browser. [ and ] jump between headings, and j/k, g/G work if your fingers expect them to.
Images
Local PNG and JPEG images are decoded lazily, so a long document full of screenshots doesn't pay for images you haven't scrolled to. Remote images stay as placeholders until you press I for that document.
Selecting and copying
You can drag to select, double-click a word, triple-click a paragraph, or Ctrl+A for everything. Ctrl+C copies it as plain text: list items keep their - , quoted lines keep their > , and table cells are tab-separated. On X11 and Wayland, a mouse selection is also the primary selection, so middle-click paste works.
Code blocks get a copy button in the upper right corner when the pointer is over them, like on GitHub. It copies the code as written, without the language tag and without a trailing line break, and shows a check mark for two seconds.
Live reload and large files
When the window gets focus, a document that changed on disk is shown again at the same place. So I keep VOMD open next to my editor, save, click over, and I'm looking at the new version without losing my scroll position.
A 5 MB document opens in under 100 ms. Files over 10 MB still render, with a notice.
Install
The current release is 1.2.0, and every release is x86-64 Linux.
Arch Linux
The packages aren't on the AUR yet, so for now you build one from a clone with makepkg:
git clone https://github.com/allenguarnes/vomd
cd vomd/packaging/aur/vomd-bin
makepkg -sivomd-bin installs the release binary, which is the small one and runs on any x86-64 CPU. If you'd rather build from source, use packaging/aur/vomd instead. It follows your makepkg.conf, so on CachyOS (with its -C opt-level=3 -C target-cpu=native flags) you get a larger, faster binary that only runs on the CPU it was built on.
Debian and Ubuntu
Each release has a .deb for Debian 12 or newer and Ubuntu 24.04 or newer:
sudo apt install ./vomd_*_amd64.debAppImage
There's also an AppImage for any x86-64 distribution with glibc 2.36 or newer. It doesn't bundle libraries; it loads the system's Wayland or X11 ones at startup:
chmod +x vomd-*-x86_64.AppImage
./vomd-*-x86_64.AppImage README.mdIt needs FUSE to mount itself. Without it, run it with --appimage-extract-and-run.
Release tarball
The tarball has the binary, the desktop file, and the icon:
tar xf vomd-*-x86_64-linux.tar.gz
cd vomd-*-x86_64-linux
install -Dm755 vomd ~/.local/bin/vomd
install -Dm644 vomd.desktop ~/.local/share/applications/vomd.desktop
install -Dm644 vomd.svg ~/.local/share/icons/hicolor/scalable/apps/vomd.svg
xdg-mime default vomd.desktop text/markdownThat last line is the one that makes double-clicking a .md file open VOMD.
From source
You need a stable Rust toolchain:
cargo build --release
# The smallest build: no images, no clipboard, system fonts only
cargo build --release --no-default-featuresThe Cargo features are images, remote-images, embed-fonts, and clipboard, all on by default.
Settings
Settings live in ~/.config/vomd/settings.ini (strictly, $XDG_CONFIG_HOME/vomd/settings.ini). The file is optional, it's plain key = value lines, and it's applied as soon as the window gets focus. The toolbar's gear button creates it with every key listed and commented out.
A few keys I actually touch:
# system, light, dark
theme = system
# 50 to 300
zoom = 100
# 10 to 32
font_size = 16
# 40 to 200 characters
line_width = 80
# true lets the text span the window (line_width is ignored)
wide = false
# ask, never, always
remote_images = ask
# default (built in), or an installed family such as Noto Sans
font_sans = defaultTheme, zoom, toolbar, wide layout, and window size are saved automatically when you change them, so most people will never open the file.
Privacy
This was a constraint I cared about from the start: a viewer should not phone anywhere just because you opened a file.
VOMD makes no network requests of its own. Remote (http/https) images show as placeholders until you press I (or click the toolbar's image button) for that document. Only then are they fetched, using the system curl, at most 4 at a time, each limited to 12 MiB and 15 seconds, and kept in memory only.
The default is remote_images = ask. You can set it to never to remove the option entirely, or always to load them for every document, but be aware that always lets any document you open contact the servers its images live on.
Limitations
Being honest about what it doesn't do yet:
- Linux only for now. The code compiles for Windows and macOS, but those are untested and unsupported.
- No table of contents panel yet. It's planned.
- No screen-reader support. AccessKit would add too much to the binary for now.
- SVG, GIF, and WebP images show as placeholders. EXIF orientation isn't applied either.
- No keyboard selection. Selecting is mouse-driven;
Ctrl+AandCtrl+Care the keyboard's way to copy, and the code-block copy button can't be reached from the keyboard. - Drag-and-drop works on X11 only, because winit doesn't support it on Wayland. On Wayland, open files with
Ctrl+Oor the toolbar's folder button.
Closing thoughts
VOMD is a small tool with a narrow job. It doesn't edit, it doesn't sync, and it doesn't try to be a notes app. It opens Markdown fast and gets out of the way.
It's MIT licensed, and the embedded fonts and icons keep their own licenses (Inter and JetBrains Mono under the SIL OFL 1.1, Lucide under ISC).
If you try it and something renders wrong, open an issue on GitHub with the Markdown that broke it. That's the most useful bug report a viewer can get.