Leon Pawelzik4k downloadsGoogle Docs-style comments for Markdown notes. Quote-anchored threads in a fenced block at the end of the file, so your prose stays untouched and AI assistants can read and write them too.
Quote-anchored comments and edit suggestions for Obsidian notes. Review threads live in a single block at the end of the file. Your prose stays untouched until you accept a suggestion, and AI assistants can read, write, and act on them with nothing but file access.

[[wikilinks]] open the target note, Cmd/Ctrl-click or middle-click opens it in a new pane, and hovering shows Obsidian's Page PreviewTandem Comments is in the Obsidian community plugin directory: in Obsidian, open Settings → Community plugins → Browse, search for Tandem Comments, then Install and Enable.
Manual install: download main.js, manifest.json, and styles.css from the latest release into <vault>/.obsidian/plugins/tandem-comments/ and enable it in Settings → Community plugins.
Comments are stored in a fenced code block at the end of the file. The text above it is never modified by commenting: no inline markers, no HTML spans, no IDs in your prose. Tandem Comments keeps the block at the very end, even if you type below it or add footnotes after it.
Your note text. We should cut prices hard in Q3.
```tandem-comments
// Schema: { "<id>": { anchor:{exact,prefix,suffix,pos?}, status:open|resolved, thread:[{author,ts,text}], suggestion?:{replacement,author,ts,result?} } }
// Anchor = quote from the prose. To locate: search for "exact", disambiguate via prefix/suffix.
// Addressing comments: handle every open id. After acting, append a reply {author: your name, ts, text} to its thread, and if you edited the quoted text, update its anchor to the new wording.
{
"a1f3": {
"anchor": { "exact": "cut prices hard", "prefix": "We should ", "suffix": " in Q3", "pos": 26 },
"status": "open",
"thread": [
{ "author": "Leon", "ts": "2026-06-10T10:24:00Z", "text": "Too aggressive?" }
]
}
}
```
Each comment is anchored by a quote (W3C TextQuoteSelector): the exact text plus a little surrounding context, with a character offset as tie-breaker.
| Command | What it does |
|---|---|
| Add comment | Start a comment on the current selection |
| Suggest edit | Propose a replacement for the current selection |
| Open comment sidebar | Show the review threads of the active note |
| Toggle resolved threads | Show or hide resolved threads in the sidebar |
| Remove resolved threads from file | Clean up threads kept as history |
| Export review threads of active file | Write all threads to a review note |
All commands can be bound to hotkeys in Settings → Hotkeys.
Suggestions use the same quote anchors and discussion threads as comments. The original prose is not changed until you press Accept:
{
"7c2e": {
"anchor": {
"exact": "cut prices hard",
"prefix": "We should ",
"suffix": " in Q3.",
"pos": 26
},
"status": "open",
"suggestion": {
"replacement": "reduce prices significantly",
"author": "Claude",
"ts": "2026-07-23T12:00:00Z"
},
"thread": [
{
"author": "Claude",
"ts": "2026-07-23T12:00:00Z",
"text": "Keeps the recommendation strong without sounding abrupt."
}
]
}
}
Accepting replaces only the uniquely matched quoted passage. If the passage is missing or matches more than one location, Tandem Comments refuses to apply the change until you re-anchor it. Other uniquely resolved open anchors are rebased through the edit in the same transaction; ambiguous anchors are left unchanged rather than silently bound to one duplicate. The prose edit and suggestion update share one editor transaction, so a single Undo restores both.
Because comments are plain JSON inside the note, an assistant needs no plugin, API, or MCP server. Reading and writing the file is enough. Ask it to review a note and it can answer in your comment threads or propose exact replacements as suggestions. You stay in control of when the prose changes.
This shines on long-form writing, where you usually want subtle, surgical changes, not an AI rewrite of the whole piece. Comments pin your feedback to exact passages, and the assistant edits only what you pointed at:
The morning market in Hoi An wakes before the tourists do. Vendors stack
mangosteen into careful pyramids while the river light is still gray.
…2,000 more words…
You leave comments where the draft needs work ("weaker verb here?" on one sentence, "this paragraph drags, tighten it" on another), then hand off:
❯ claude "turn my comments in hoi-an-draft.md into edit suggestions, keep the prose unchanged"
Claude proposes replacements for those two passages and explains each change in its thread. The prose stays byte-for-byte identical until you review the suggestions in Obsidian and accept the ones you want.
Or let the assistant work through the comments directly:
❯ codex "address the review comments in hoi-an-draft.md"
It edits only the passages you commented on and replies in every open thread with what it changed, or asks when a comment needs information it does not have. Anchors follow the new wording, so the highlights stay attached, and the threads stay open until you resolve them in Obsidian. Threads it could not act on, such as a comment whose quoted text no longer exists, get a reply instead of being dropped.
The comment block itself carries short format hints (see How it works), so an assistant that has never seen the plugin can still reply in the right place. The skill adds the full rules and makes long notes with many threads reliable.
To teach your coding agent the format, open Settings → Tandem Comments → Advanced & integrations and use Export for Claude Code (writes ~/.claude/skills/obsidian-tandem-comments/) or Export for Codex (writes ~/.agents/skills/obsidian-tandem-comments/). The skill covers the format, anchoring, edit suggestions and how to work through every open thread without skipping any. Export again after updating the plugin to get the latest version. Skill export is available in the desktop app; the comment format itself works the same on mobile.
Settings are grouped into four sections and apply live:
{{filename}}, {{date}}), export folderInline comment markers break plain-text workflows: they show up in exports, confuse other tools, and make diffs noisy. Tandem Comments keeps annotations out of your prose entirely. The file remains a normal Markdown document that happens to carry its review thread with it.
Comment bodies are rendered with Obsidian's Markdown renderer and inherit its supported syntax, sanitization, and plugin post-processor behavior. Tandem Comments does not add a separate post-render HTML sanitizer.
The real sanitizer cannot run under the test harness (Node/Vitest has no Obsidian runtime). The following smoke-test matrix was verified manually with Obsidian 1.12.4:
| Comment input | Observed result |
|---|---|
**bold**, _italic_ |
Renders bold / italic |
[link](https://example.com) |
Renders a clickable, safe link |
| Paragraph, blank line, paragraph | Two paragraphs with compact spacing |
<script>alert(1)</script> |
Not executed; script neutralized |
<img src=x onerror=alert(1)> |
No alert; onerror stripped |
[x](javascript:alert(1)) |
Click does nothing; scheme neutralized |
<a href="vbscript:…">, data: URL |
Neutralized |
If Tandem Comments is useful to you, a ⭐ on GitHub helps other people find it. Bug reports and ideas are welcome as issues.