DOCUMENTATION

Reader.md

A native macOS rebuild of the markdown viewer, built in SwiftUI and AppKit. The whole shell — toolbar, sidebar, file search, outline, folder management, file watching, and SF Symbol icons — is native. The markdown content pane is a WKWebViewthat renders through bundled JS engines, because Mermaid diagrams and LaTeX math have no native equivalent.


Install

Direct download RECOMMENDED

Grab Reader.md.dmg from the latest release, open it, and drag Reader.md to Applications. The app is ad-hoc signed but not notarized, so the first launch needs one right-click → Open.

First launch: macOS shows “Apple cannot check it for malicious software.” Clear it once with right-click → OpenOpen, or runxattr -dr com.apple.quarantine "/path/to/Reader.md.app".

Homebrew

Because the repo isn't named homebrew-*, tap it with its explicit URL once, trust the cask, then install:

# tap, trust, then install
brew tap jnahian/reader.md https://github.com/jnahian/reader.md
brew trust --cask jnahian/reader.md/reader.md
brew install --cask reader-md

Already installed and Gatekeeper still complains? Clear the quarantine attribute:

xattr -dr com.apple.quarantine "/Applications/Reader.md.app"

Upgrades come from the app's own Sparkle updater, so brew upgradeleaves the installed build alone. To uninstall, including preferences and caches:

brew uninstall --cask reader-md        # remove the app
brew uninstall --zap --cask reader-md  # also wipe ~/Library data

Features

Open anything
A single .md file (⌘O or double-click in Finder), whole folders, or a mix. Set Reader.md as your default markdown handler.
Multi-folder browser
Add any number of roots (multi-select or drag folders onto the window). Each is a collapsible section with hover-to-reveal actions; roots reorder by drag.
Remote SSH folders
Add a folder from a VPS: Reader.md rsyncs it read-only into a local cache. Auto-syncs on launch, manual re-sync, edit-in-place, and a cloud badge with sync/error state. Reuses your ~/.ssh config — no credentials stored.
Quick open & find
⌘P fuzzy file switcher across all roots, ⌘F live tree filter, and ⇧⌘F native in-page find with match highlighting (⌘G / ⇧⌘G for next/prev).
Outline
Collapsible right pane (⇧⌘B) with a sliding accent rail marker and scrollspy.
Typography
Font size (⌘+ / ⌘− / ⌘0) and a narrow / wide / full-width reading column (⇧⌘\), both persisted.
Rendering
Syntax highlighting, Mermaid, and LaTeX math via bundled JS engines. YAML frontmatter renders as a clean key/value table. Code copy buttons, image click-to-zoom lightbox, and hover heading anchors.
Reading themes
Standard, Editorial, Terminal, and GitHub — each with its own typography, accent, and syntax highlighting. Resume where you stopped in long documents.
Liquid Glass chrome
On macOS 26 (Tahoe) the toolbar, sidebar, outline, find bar, and quick-open palette read as Liquid Glass; on 13–15 they fall back to translucent NSVisualEffectView material. Collapsible + resizable sidebar (⌘B, width persisted).
Live reload & export
The open file re-renders (scroll preserved) and the tree refreshes on disk changes. Export to PDF (⌘E), manual reload (⌘R), dark mode, and Sparkle auto-update.

Keyboard shortcuts

Open file⌘O
Quick open⌘P
Add folder⇧⌘A
Add remote folder⌥⌘A
Filter files⌘F
Find in page⇧⌘F
Find next / previous⌘G / ⇧⌘G
Back / forward⌘[ / ⌘]
Toggle sidebar⌘B
Toggle outline⇧⌘B
Text bigger / smaller / reset⌘+ / ⌘− / ⌘0
Column width⇧⌘\
Export PDF⌘E
Reload⌘R

Command line

Homebrew puts reader on your PATH automatically. From the DMG, useFile → Install reader Command Line Tool….

reader open a markdown file
reader add a folder to the sidebar
reader . add the current directory
reader remote me@vps:/srv/docs add a remote (SSH) folder
reader ls list configured folders
reader rm remove a folder
git diff | reader - open piped markdown

reader drives the app rather than replacing it: each command hands a readermd:// URL to Reader.md. It behaves in scripts — a bad path or malformed command exits 1 with the reason on stderr; no arguments (or--help) prints usage and exits 0.


Architecture

SwiftUI shell

The window's native toolbar over ContentView — a resizable/collapsible sidebar, the content pane, and a collapsible outline; overlays host the find bar and quick-open palette.

AppState

An ObservableObject (@MainActor) holding roots, selection, theme, search, outline, typography, layout, history, and find/export triggers; persists to UserDefaults.

RemoteSync

A remote folder is rsync'd read-only into a stable local cache dir that registers as an ordinary root. Credentials come from your ~/.ssh config/keys — none are stored in-app.

MarkdownWebView

An NSViewRepresentable around WKWebView. Swift pushes markdown / theme / font settings; JS posts the outline, active heading, word count, scroll progress, and link clicks back. Bundled marked, highlight.js, KaTeX, and Mermaid — no network.

GlassPanel / FolderWatcher

Chrome surfaces use Apple's Liquid Glass on macOS 26, with an NSVisualEffectView fallback on 13–15. An FSEvents subtree watcher drives debounced live reload.


Build & run

Quick, for development

swift run ReaderMd

Double-clickable app

./make-app.sh
open "build/Reader.md.app"

make-app.sh builds a release binary, assembles the bundle with resources, converts the icon to .icns, writesInfo.plist, ad-hoc code-signs, and producesbuild/Reader.md.zip for sharing. Or open the SwiftPM package in Xcode, select the ReaderMd scheme, and Run.


Requirements

RUNTIME

macOS 13+. Liquid Glass appears on macOS 26 (Tahoe); earlier versions get theNSVisualEffectView fallback automatically.

BUILD

Xcode 26 (or Swift 6.2+ with the macOS 26 SDK) to compile theglassEffect symbols. The deployment target stays at macOS 13.

The app is not sandboxed, so it reads user-selected folders directly. All rendering assets are local — the only network access is Sparkle's auto-update check and, for remote folders, rsync/ssh to hosts you add. Sync is read-only and pull-based; Reader.md never writes back to the remote.