A beautiful, reliable, private Markdown reader for Android.
pilcrowmd.com — screenshots, changelog, privacy policy
The web is full of Markdown — LLM answers, READMEs, notes, technical docs — and most Android apps render it in a WebView wrapped in ads and trackers. PilcrowMD takes the opposite approach.
PilcrowMD renders Markdown natively — no WebView, no JavaScript runtime, no network calls to read your files. The result is fast, typographically careful rendering of full GitHub-Flavored Markdown (tables, code, math, task lists, frontmatter) with a reading experience that looks designed rather than dumped.
- Beautiful. Serif body type, real syntax highlighting, rendered LaTeX, and a calm dark theme (with a warm-cream light theme) built from an exact design-token system.
- Reliable. Atomic saves that never truncate your file, round-trip fidelity that preserves your line endings and frontmatter (a file with mixed line endings is written back uniformly in its dominant style), and a renderer that degrades gracefully instead of crashing on syntax it doesn't support.
- Private. Files are read through Android's Storage Access Framework and stay on your device. No accounts, no analytics, no ads, no network in the reading path. Free software under the GPL.
- Full GitHub-Flavored Markdown — headings, emphasis, lists, task lists, blockquotes, tables, fenced code, thematic breaks, links and images.
- Native syntax highlighting for fenced code blocks, with a one-tap copy button.
- LaTeX math — inline (
$…$or$$…$$) and block$$…$$, rendered as crisp native bitmaps (no WebView). Single-$parsing is currency-aware, so$5 and $10stays plain text. - Reader + source editor — toggle between a polished reader and a real code editor with Markdown highlighting, a line-number gutter, and soft wrap.
- In-document search with match highlighting and next/previous navigation.
- Table of contents drawer generated from your headings, with tap-to-jump.
- YAML frontmatter rendered as a tidy metadata card.
- Export to PDF — paginated, print-styled, matching what you see on screen.
- Two themes — a default dark theme and a warm-cream light theme.
- Per-file memory — reopens your last file at the position you left it; keeps a recents list.
- Adjustable type — independent font scaling for reader and editor.
- Graceful by design — diagrams and unsupported syntax degrade to readable code blocks rather than breaking the page (Mermaid can optionally render via the cloud, off by default).
- Offline & ad-free — minimum Android 8.0, no required network permission for reading.
| Syntax-highlighted code & tables | Math & diagrams | Home & recents | Settings |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
A warm-cream light theme is also built in — see the light reader.
PilcrowMD is a single-activity Jetpack Compose app following Clean Architecture + MVVM with unidirectional data flow and strict layer boundaries:
- UI (Compose) is passive and state-driven — no business logic, colors only from design tokens.
- State (
MarkdownViewModel) exposes UI state asStateFlowand orchestrates everything; it never does I/O or parsing directly. - Domain holds pure-Kotlin parsing and search use cases — testable with no emulator.
- Data hides file I/O and persistence behind interfaces (
FileRepositoryover the Storage Access Framework;StorageManagerover Jetpack DataStore).
Dependencies are wired through a single hand-written composition root (a manual AppContainer), and
Markdown is rendered to native views with Markwon — never a
WebView. The four Essential Safeguards (no data loss, round-trip fidelity, crash-free rendering,
design-token fidelity) are enforced in code and protected by tests.
→ Full details in docs/ARCHITECTURE.md.
Requirements: JDK 21, Android SDK with API 36, and minSdk 26 (Android 8.0) for the target
device. The Gradle wrapper pins the build tooling — no global Gradle install needed.
git clone https://github.com/pilcrowmd/pilcrow.git
cd pilcrow
# Build the debug APK
./gradlew clean assembleDebug
# Install to a connected device / emulator
./gradlew installDebugThe debug APK is written to app/build/outputs/apk/debug/.
Build from
cleanfor any result you intend to trust. PilcrowMD pins Kotlin to 2.3.10 to match the metadata version of its editor dependency (Soraeditor-bom:0.24.5). That toolchain carries a known incremental-compiler quirk: it can cache a stale state and report phantomUnresolved referenceerrors on code that compiles cleanly from scratch — a false negative (green turned red), never a false pass. A from-scratch build is therefore the source of truth, and CI runscleanfirst so it never trusts a poisoned cache.
Quality is enforced on every push and pull request by CI, which runs the full gate from a clean build:
./gradlew clean
./gradlew assembleDebug ktlintCheck detekt testDebugUnitTest verifyRoborazziDebug bundleRelease lintRelease --rerun-tasks- Unit tests cover the critical paths, including the
Essential Safeguards: crash-safe save with process-death recovery from a durable write-ahead log
(
LocalFileRepositoryAtomicSaveTest), LF/CRLF round-trip fidelity (MarkdownViewModelLineEndingTest), and large-file crash resistance (MarkwonRendererLargeFileTest, ~5,000 lines). - Visual-regression goldens via Roborazzi — every Markdown sample × 3 font scales × 2 themes, plus the Welcome, search, and GitHub-teaser screens, rendered under Robolectric and pinned to a fixed device config. Any layout or typography drift fails the build.
- Static analysis & style — ktlint and detekt, both baselined and run in the gate.
- License diligence — all third-party dependencies and bundled fonts are tracked in LICENSES.md and surfaced in-app, and verified compatible with GPL-3.0-or-later as a combined work.
| Area | Choice |
|---|---|
| Language | Kotlin 2.3 |
| UI | Jetpack Compose (Material 3) |
| Architecture | Clean Architecture + MVVM + UDF, manual DI |
| Async | Coroutines & Flow |
| Markdown rendering | Markwon (native, no WebView) |
| Syntax highlighting | Prism4j |
| Math | JLatexMath (via Markwon) |
| Code editor | Sora Editor |
| Persistence | Jetpack DataStore (Preferences) |
| File access | Storage Access Framework |
| Testing | JUnit, Robolectric, Roborazzi, MockK |
| Fonts | Source Serif 4 & JetBrains Mono (OFL) |
PilcrowMD v1 is intentionally focused — read and edit Markdown beautifully and safely, offline. Directions under consideration for future releases:
- Document collections / multi-file libraries.
- Additional export targets and richer print options.
- Optional offline diagram rendering.
- Wider syntax coverage (footnotes, definition lists).
Nothing here is a commitment; the v1 safeguards and native-only constraint always come first.
Bug reports, feature ideas, and feedback are very welcome — please open an issue. External code contributions are on hold while we finalize our Contributor License Agreement (CLA); see CONTRIBUTING.md for details and the workflow, and our Code of Conduct. Security issues should follow SECURITY.md rather than a public issue.
PilcrowMD is free software, licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later). Copyright © 2026 pleree.
It comes with no warranty. See LICENSE for the full text or https://www.gnu.org/licenses/. The copyleft license is deliberate: it keeps PilcrowMD and its derivatives free and open, and prevents closed-source or ad-laden clones.
The app's own license is distinct from the licenses of its third-party dependencies and bundled assets, which are documented in LICENSES.md and surfaced in-app under Settings → About → Open source licenses.
PilcrowMD stands on excellent open-source work:
- Markwon and Prism4j — native Markdown rendering and syntax highlighting.
- Sora Editor — the native code editor.
- JLatexMath — math typesetting.
- Roborazzi — screenshot testing.
- Source Serif 4 and JetBrains Mono — the typefaces, under the SIL Open Font License.




