Native Markdown reader for macOS.
Double-click a .md file and it opens rendered, reloads itself while you
edit, and previews in the Finder with the space bar. Comment on a phrase and the
note goes into the file itself. Nothing leaves the machine.
Comment on anything. The note goes into the .md file.
Note
Imark opens reading, and reading is what it is for. The switch in the toolbar turns it into an editor for the file you already have open — see Editing — and comments go into the document itself, as HTML comments, so they travel with it.
- Editing, when you ask for it — one switch in the toolbar, and the page becomes the file: line numbers, Markdown in colour, a bar beside every line you have changed,
⌘Sto write it. Reading is the state it opens in - Comments in the file — select, comment, edit or delete, and the note lives in the document as an HTML comment, so it survives being emailed, committed, or opened in anything else.
⌘Zundoes any of it - Quick Look previews — the space bar in the Finder renders the document, not raw text, using the same engine as the app
- Live reload — saving in your editor updates the view in under 300ms, keeping your scroll position, and it survives the delete-and-rename that editors call an atomic save
- Foldable outline — headings in the sidebar, with sections you can collapse; past twenty entries it opens folded, so a changelog is one row per version
- Outline rail — a tick per heading down the edge of every document, tapering around the pointer, with a card that names the section before you commit to going there
- Wiki-links —
[[note]]resolves against the folder and opens in the same window, with back and forward history - The folder and the recents — every
.mdbeside the open document, plus the last five you opened from anywhere else - Everything GitHub-flavoured — tables, task lists, footnotes, front matter as a header card you can put away from the View menu, syntax highlighting, Mermaid diagrams, KaTeX maths
- Actions on a selection — comment on it, translate it on device, or search the web for it in your default browser
- Find with a counter —
⌘Fhighlights every hit and tells you which one you are on - Tabs — several documents in one window, with everything macOS gives a tabbed app:
⌘⇧[and⌘⇧], drag a tab out, Merge All Windows - Offline where it counts — documents render with every request blocked by a content security policy, KaTeX fonts embedded, remote images refused on purpose
| Document window | Quick Look preview |
|---|---|
![]() |
![]() |
Both are rendering testdata/showcase.md. For the full
sweep — every construction, every kind of comment, and enough headings that the
outline folds itself — open testdata/everything.md.
Space bar in the Finder. No app to open first.
The rail: one tick per heading, in the window and in the Finder's preview panel alike. Click to jump, or press and drag to scrub.
brew install --cask migsilva89/imark/imarkOr download the latest release and drag Imark.app into /Applications. The disk image is signed and notarised, so it opens without a Gatekeeper warning.
macOS 14 or later. Imark tells you when a newer version exists — once per release, and only if you leave the check on in Settings.
To make it the default for .md: launch it with no document open and click Make Imark the default for .md, or use the same item in the Imark menu. Once it is the default, both quietly disappear.
The toolbar has one switch: an eye and a pencil. The eye is the app you know — nothing on screen offers to change the file. The pencil replaces the page with the document as text, in a plain editor: line numbers, Markdown in colour, a bar in the gutter beside every line that differs from the file on disk, and the system's own find bar with its counter and its replace field.
⌘S writes it. Until you do, live reload stands still — following the file
is the reason this app exists and also the one thing that could erase what you
typed, so while there is anything unsaved the window stops watching. The close
button carries the system's edited dot, Revert throws the buffer away and reads
the file again, and closing the window or opening another document asks first.
A save cannot land on somebody else's work: it goes through the same check every
comment does, and if the file moved since Imark read it the save is refused and
says so. ⌘Z afterwards puts the document back the way it was.
Open in… stays in the toolbar while you edit, with Cursor, VS Code, Zed, Sublime — and Claude and ChatGPT — so the moment a change is bigger than a line, the file goes to something built for it. Imark runs nothing on your machine and asks nothing of your accounts; when you come back, the reader is where you left it, and the notes are still in the file.
Select a phrase, press the speech bubble, write, press ↵. The quoted words get
underlined, a dot appears in the margin, and clicking either opens the note. Pick
one of five colours while writing it, or change it later. The card carries Edit
and Delete, and ⌘Z undoes any of it — writing, editing or deleting.
The note is stored inside the .md file, as an HTML comment:
Rows move in batches of 500, and the deadline is generous but achievable.
<!-- imark quote="generous but achievable" by="john" at="2026-08-02T14:31Z"
Achievable with which team? This needs a number, not an adjective.
-->Which means it travels with the document instead of living in a database only this app can read:
| Where | What you see |
|---|---|
| Imark | the words underlined, a dot in the margin, the note on click |
| Cursor, VS Code, Vim | the block above, verbatim, right under the paragraph |
| GitHub, any renderer | nothing — HTML comments are invisible |
grep, cat |
the note, with the quote it refers to beside it |
The quote= is what makes the note legible in raw text: someone opening the file
in Vim can see what it refers to without counting lines. If the quoted words are
later edited away the note goes orphan — still visible, still attached to its
block, marked as having lost its anchor. There is no fuzzy matching, because a
note in the wrong place is worse than a note without an exact one.
Four ways to get at them, because they answer different questions. The count in
the status bar opens the list — every note at once, out of the document.
⌘⇧C opens them all in place, each under its own block. ⌘' and ⌘⇧'
step through one at a time. And a rail down the left edge marks where
they are, so three clustered in one section is visible at a glance.
File › Export Comments as Text… writes a copy — not the document — with every note turned into a blockquote, for the review the other person has to read on GitHub:
Rows move in batches of 500, and the deadline is generous but achievable.
> **john, 2 Aug 2026** on *“generous but achievable”*
>
> Achievable with which team? This needs a number, not an adjective.A plan from a coding agent is markdown. So is a diff, once it is wrapped in a fenced block. Because comments live in the file, an agent can hand you a document, you can annotate it in Imark, and the agent can read your notes back out — with no server, no port and nothing installed on the other side. The file is the whole bridge.
Send Back, and the agent reads your notes back.
A document under review gets two buttons in the toolbar, Approve and Send Back, and pressing either one ends the wait on the other side. Closing the window without pressing one asks first, because something is waiting for an answer and closing is not an answer.
The buttons appear on a document an agent asked to have reviewed, and nowhere
else: the agent leaves a small file in ~/.imark/pending naming the document
before opening it, and Imark writes the decision beside that file. Every other
.md opens exactly as it always did.
plugin/ is a Claude Code plugin that does this:
/imark:imark-review PLAN.md # review a markdown document
/imark:imark-notes PLAN.md # notes you already left
Launched with no document, Imark offers to set itself up for the coding agents
on your machine — one skill, written into each one's skills folder. The alert
names every file before writing it, and undoing it is deleting those. Claude Code
and Codex read the same SKILL.md; only Claude Code also takes the two loose
commands.
Those files are copies, so a new version of Imark brings them forward on its first launch and says which ones it rewrote. A copy you edited yourself is never overwritten — Imark only replaces a file that still matches something it shipped, and tells you the rest were left alone.
| Where | What, and when |
|---|---|
The .md you are reading |
when you save an edit or a comment. Written to a temporary file beside it and moved into place; it refuses to save at all if the document changed on disk since Imark read it |
~/.imark/pending |
while an agent is waiting on a review: which document, and what you decided. Deleted when the agent reads it |
~/Library/Preferences/pt.miguelsilva.imark.plist |
your settings — theme, text size, width, the update check |
~/.claude/skills, ~/.codex/skills, … |
only if you accept the offer to set up your coding agents, and only the files the alert names. A new version rewrites those same files once, on its first launch, unless you edited them |
| The network | one request a day to api.github.com asking whether a newer version exists. A version number travels, nothing of yours does, and Settings turns it off |
Important
Editing and comments are the two ways Imark writes to your documents. Both
refuse to save if the file changed on disk since Imark read it. ⌘Z puts the
last change back, and ⇧⌘Z redoes your typing while editing. If Imark ever
damages a file, open an issue
before anything else — that is the one bug worth interrupting whatever else is
happening.
⌘O |
Open | ⌘F |
Find, prefilled with the selection |
⌘W |
Close window | ⌘G / ⌘⇧G |
Next / previous hit |
⌘\ |
Toggle sidebar | ← / → |
Fold / unfold outline section |
⌘[ / ⌘] |
Back / forward | ⌘R |
Reload |
⌘+ / ⌘- / ⌘0 |
Text size | ⌘⇧R |
Reveal in Finder |
⌘P |
Print or export PDF | ⌘⇧C |
Show all comments |
⌘' / ⌘⇧' |
Next / previous comment | ⌘Z |
Undo the last change |
⌘E |
Reading or editing | ⌘S |
Save the file |
⌘X / ⌘C / ⌘V |
Cut, copy, paste | ⇧⌘Z |
Redo your typing |
⌘/ |
This table, in the app |
⌘/ opens the same list inside the app, built by reading the menu bar rather
than from a copy of this table — which is also how it stays right on keyboards
where macOS remaps the keys. On a Portuguese layout, Back and Forward are ⌘Ç
and ⌘~, not ⌘[ and ⌘].
Requires Xcode 16 or later and Node 20.
git clone https://github.com/migsilva89/imark.git
cd imark
cd renderer && npm ci && cd ..
./build.shThat builds the JavaScript bundle, compiles the Swift, assembles Imark.app and
installs it to /Applications. npm ci is not optional: the rendered output is
generated, not committed, and build.sh refuses to assemble an app with a blank
window.
./build.sh |
build and install |
./build.sh --debug |
fast compile, for iterating |
./build.sh --no-install |
leave it in dist/ |
IMARK_INSTALL_DIR=~/Applications ./build.sh |
install elsewhere |
Swift 6 with AppKit and no external Swift dependencies, around a WKWebView that
only ever renders; markdown-it, highlight.js, Mermaid and KaTeX are bundled
offline with esbuild. CONTRIBUTING.md has the layout of the
repository, the test suites and how to run them.
It does not use the network. WebKit refuses to start its WebContent process
inside a sandboxed app extension without com.apple.security.network.client,
even when every byte is served from a local scheme. The panel stays blank without
it, with no error and no log entry.
While reading: the last change to the document — a note written, edited or deleted — up to ten deep. Each one is a snapshot of the whole file taken before the change.
While editing: the typing, like any editor, with ⇧⌘Z to put it back. The two
never mix, because putting a whole document back is not what ⌘Z means with a
caret on screen.
Either way it only covers changes Imark made; edits from your own editor are your editor's to undo.
The second note gets an nth="2" so it anchors to the right occurrence. Notes on
the same paragraph stack down the margin rather than landing on top of each
other.
Imark is a personal project, maintained by one person. Issues get answered and
pull requests are welcome —
CONTRIBUTING.md says what is out of scope before you spend a
weekend on it — but there is no support promise and no release schedule. For
anything that looks like a security problem, SECURITY.md says
where to send it instead of the issue tracker.
Everything Imark bundles is permissive — MIT, ISC, BSD, Unlicense — with no
copyleft anywhere in the tree. Several require their copyright notice to travel
with the binary, so THIRD-PARTY.md is generated from what
esbuild actually put in the bundle, on every build, and the same list ships
inside the app: Imark › About Imark shows it.
Imark itself is MIT — use it, change it, redistribute it, just keep the copyright notice.






