Google Docs-style comments for Obsidian.
Select text, leave a comment, and collaborate with highlights, a sidebar panel, and resolution tracking -- all stored invisibly in standard markdown.
- Inline comments -- add comments on selected text in editor mode
- Threaded replies -- each top-level comment stores child replies in a
childrenlist; expanded threads show an inline reply field - Editor highlights -- colored background for commented ranges with inline icon widgets and stronger emphasis for the selected thread
- Sidebar panel -- click any card to jump/select, view collapsed/expanded threads, and reply inline
- Reading mode -- optional best-effort highlighting in reading view
- Document → panel sync -- clicking highlighted text selects/focuses the matching thread in the panel
- Author permissions -- only the original author can edit/delete their comment or reply; replies cannot be resolved or replied to
- Configurable -- author name (or git
user.namefallback), highlight colors, reading mode toggle - Portable -- comments are stored as HTML comment markers, invisible to any renderer outside Obsidian
- CriticMarkup interop -- convert active notes (or files via CLI) to/from CriticMarkup with sidecar metadata for round-tripping author/timestamp/reply data
- Git config lookup -- if Author name is blank in plugin settings, Marginalia
runs
git config --get user.name(thengit config --global --get user.name) to choose a default author label. - No network calls -- the plugin does not send comment data or note content over the network.
- Storage -- comments are embedded directly in your markdown note as HTML comment markers.
Comments are stored as paired markers in the note source:
<!-- marginalia-start: a1b2c3d4 -->annotated text<!-- marginalia: {"v":1,"id":"a1b2c3d4","text":"Is this accurate?","author":"Eric","ts":1708300000,"resolved":false,"children":[{"id":"r9k2m1z8","text":"I agree","author":"Riley","ts":1708300300}]} -->Markers are standard HTML comments, so they're invisible in any markdown
renderer that doesn't understand them. The --> sequence in JSON payloads is
escaped to prevent breaking the outer comment boundary.
From Obsidian Community Plugins (pending approval)
Search for "Marginalia" in Settings > Community plugins.
Run from anywhere — no download needed. Omit the path to be prompted, or
use . when already in your vault directory.
curl -fsSL https://raw.githubusercontent.com/ealt/marginalia/main/scripts/install-marginalia.sh | bash -s -- /path/to/YourVaultExamples:
... | bash— prompts for vault path... | bash -s -- .— install into current directory (if you’re in the vault)... | bash -s -- ~/Documents/MyVault --force— overwrite without prompting
If you already have the repo cloned:
bash scripts/install-marginalia.sh /path/to/YourVault
# or
npm run install:plugin -- /path/to/YourVault- Download
main.js,manifest.json, andstyles.cssfrom the latest release - Create
.obsidian/plugins/marginalia/in your vault - Copy the three files into that directory
- Enable the plugin in Settings > Community plugins
See CONTRIBUTING.md for full setup and workflow details.
npm install
npm run dev # watch mode
npm run build # production bundle
npm run check # type-check
npm run test # unit tests
npm run interop:export -- path/to/note.md # convert Marginalia -> CriticMarkup
npm run interop:import -- path/to/note.md # convert CriticMarkup -> MarginaliaMarginalia includes bidirectional conversion between plugin markers and CriticMarkup.
Export active note to CriticMarkupImport active note from CriticMarkup
npm run interop:export -- path/to/note.md
npm run interop:import -- path/to/note.mdBoth commands use a sibling sidecar file (note.critmeta.json) to preserve
Marginalia-only metadata (id, author, ts, resolved, children) and map
records back during import.
Export shape:
{==annotated text==}{>>parent comment<<}{>>first child<<}{>>second child<<}Standalone CriticMarkup comments are also imported:
{>>comment without highlight<<}Those become zero-length Marginalia anchors and export back as standalone CriticMarkup comment tokens.
In markdown renderers without CriticMarkup support, CriticMarkup tokens are
shown as literal text ({==...==}, {>>...<<}, etc.).
Build with npm run build, then copy manifest.json, main.js, and
styles.css to your vault's .obsidian/plugins/marginalia/ directory and
enable the plugin.
| Workflow | Trigger | Steps |
|---|---|---|
| CI | Push / PR | Install, type-check, test, build |
| Release | Manual dispatch | Tag, build, publish GitHub release |
Release flow: npm run version-bump patch (or minor / major) > commit >
push > run workflow in GitHub Actions.