Markdown CollabReview Markdown with Claude Code, in VS Code. Comments anchor to the text and live inside
the The loopComment → send → Claude edits and replies → accept → resolve.
Flip it: right-click a Try it in one minute
You get a scratch document that arrives mid-review: two threads (one already answered), two pending suggestions, and a short list of things to click. No skill install, no Claude session, no configuration. Delete the file when you're done. Quick start
Three surfaces
How to use, day to dayAdding a commentOpen the Inline Comments view ( Any selection works — even a single word. Only empty or whitespace-only selections are ignored. Sending the batch to ClaudeOnce you've left one or more unresolved comments, click Send N to Claude at the top of the comments sidebar (the count updates live). The button is disabled when nothing is unresolved. Reviewing repliesClaude addresses each comment, edits the doc in place, and appends a reply with what it changed. The reply lands as a thread reply in VS Code. Toggle the thread to Resolved when satisfied; reply with more questions if not. Asking Claude to review (Claude-initiated threads)The flow above is human-to-Claude: you leave comments, Claude addresses them. v0.29 added the reverse direction — Markdown Collab: Ask Claude to Review This Doc (right-click a The extension prompts for an optional focus directive — a free-form sentence telling Claude what to look for, e.g. "check API examples for correctness" or "find marketing-y tone." Leave it blank for a general review. The last five focus directives you've used are offered in a quick-pick so you don't retype the common ones. Claude reads the doc and opens one inline-comment thread per substantive concern it finds. There's no cap on thread count — if 30 things warrant a thread, Claude leaves 30. The sidebar grows two affordances when Claude-initiated threads exist:
A thread counts as "reviewed" once you reply or resolve it; the indicator clears automatically. The detection uses the existing inline-thread JSON — no schema change, no migration needed. Files larger than 50 KB prompt a soft confirm before sending (Claude's review can use significant context on big docs). In review mode the skill never edits prose — every concern goes in a thread for you to gate. Expect "Reviewed Standing conventionsSome things are true of every review: the product's name, the house tone, the code-example rule, the thing you've decided not to care about. Retyping those into the focus prompt each time — or watching Claude re-raise them — is the tax this removes. Markdown Collab: Edit Review Conventions creates
Reviewing changes since the last passOnce Claude has reviewed a file, Markdown Collab: Review Changes Since Last Pass
(right-click a The bookkeeping is inline like everything else: when Claude finishes a pass it records a
Reviewing a whole folderReal doc work is rarely one file, so the same command takes a folder or a multi-select: right-click a folder in the explorer → Markdown Collab: Ask Claude to Review These Docs, or select several One focus prompt covers the whole selection, and the 50 KB soft confirm applies to the summed size. Threads land per file; the Markdown Review tree shows the per-file counts, and Next Unread from Claude (the → button in that view's title bar) walks the unread threads across all the files in order, wrapping at the end. Comments that survive doc editsComments are anchored to a text selection, not a line number. When Claude rewrites a passage that has a comment, the skill instructs it to update the anchor text to match — so comments survive revisions. If a rewrite removes the anchored passage entirely, the thread's markers go with it and the thread surfaces as unanchored in the Inline Comments view — re-anchor it by selecting fresh text and leaving the note again. The live editor (WYSIWYG + AI co-editing)Prefer editing rendered Markdown directly? Right-click a It's built for one human + Claude on the same machine — not multi-user network sync:
The comment panel matches the inline view: collapse threads, an always-on reply box, resolve, delete a single comment or a whole thread, and send one thread (or the whole file) to Claude. Reviewing pull requests / merge requestsRun Markdown Collab: Review PR / MR to review the Markdown files changed in a GitHub Pull Request or GitLab Merge Request. It uses your existing
Requires the Choosing a send modeThe Send to Claude button delivers the comment payload one of five ways. Pick one once via
Don't know which to pick? Don't. Leave
The detected mode is remembered like a manual choice, and the toast names the escape hatch: Markdown Collab: Reset Send Mode clears it if you want to switch later. If the MCP channel turns out to be stale (its endpoint file outlived the server), the send falls back to the event log and un-remembers the choice, so the next click asks you properly instead of failing the same way twice. Send mode details
|
| Command | Purpose |
|---|---|
Markdown Collab: Install Claude Skill |
Write ~/.claude/skills/vs-markdown-collab/SKILL.md and the bundled helpers (mdc.mjs, mdc-tail.mjs, mdc-channel.mjs). |
Markdown Collab: Initialize AGENTS.md |
Append a convention block to <workspace>/AGENTS.md (for non–Claude-Code agents). |
Markdown Collab: Open Inline Comments View |
Open the rendered view with an inline-threads sidebar. Comments are stored inside the .md file. The right-click action on .md files. |
Markdown Collab: Open Live Editor |
Open the WYSIWYG live editor with the comment panel — you and Claude co-edit the same .md (single human + Claude, no relay). |
Markdown Collab: Review PR / MR |
Review the Markdown files changed in a GitHub PR or GitLab MR via the gh / glab CLI. |
Markdown Collab: Ask Claude to Review This Doc |
Ask Claude to act as the reviewer (v0.29+). Prompts for an optional focus directive, then sends a Review Mode payload through the configured send mode. Claude opens one thread per concern; you triage in the sidebar. |
Markdown Collab: Ask Claude to Review These Docs |
Same, over a folder or a multi-select of .md files — one review pass across all of them, including cross-document consistency (v0.34.55+). Right-click a folder in the explorer. |
Markdown Collab: Next Unread from Claude |
Jump to the next thread Claude opened that you haven't answered, walking across every file in the Markdown Review tree. Also the → button in that view's title bar. |
Markdown Collab: Send Unresolved Comments to Claude |
Same as the Send to Claude button — usable from palette. |
Markdown Collab: Start Claude Review Terminal |
Spawn a fresh integrated terminal and launch claude. |
Markdown Collab: Copy Claude Prompt |
Copy a short "address the comments on this file" prompt to clipboard. |
Markdown Collab: Reset Send Mode |
Clear the remembered ask choice for the current workspace. |
Markdown Collab: Remove All Resolved Comments |
Delete every resolved thread from the file at once, markers and all. Open threads and pending suggestions are left alone. Modal confirm; one undo step. Also a Remove N resolved button in both comment panels, shown only when there is something to remove. |
Markdown Collab: Show Logs |
Open the Markdown Collab output channel. Set its level to Trace (gear icon in the Output panel) to see per-send and per-tool-call detail. |
Markdown Collab: Report a Problem (collect diagnostics) |
Build an environment report — versions, send mode, skill and tool-server status, per-document review state — into a scratch document, ready to paste into an issue. Contains no tokens. |
Settings
| Setting | Default | Purpose |
|---|---|---|
markdownCollab.showLineNumbers |
false |
Show the source line number beside each block in the inline comments view and the live editor. Numbers are lines in the .md file itself — frontmatter and the stored threads block are accounted for, so they match what you'd type into "Go to Line". |
markdownCollab.sendMode |
ask |
One of ask, terminal, mcp, channel, mcp-channel, clipboard. See Choosing a send mode. |
Storage layout
Inline view (default). Threads live inside the .md file itself. Anchored spans are wrapped in paired HTML comments and threads are serialized as <!--mc:t {JSON}--> lines inside a fenced region at the end of the file:
The <!--mc:a:k7q3p-->quick brown fox<!--mc:/a:k7q3p--> jumps…
<!--mc:threads:begin-->
<!--mc:t {"id":"k7q3p","quote":"quick brown fox","status":"open","comments":[{"id":"c1","author":"ronica","ts":"2026-05-13T12:00:00Z","body":"too cliched"}]}-->
<!--mc:threads:end-->
The markers are invisible in any rendered preview (they're HTML comments). Commit the .md file as-is — review state ships with the document.
The only files Markdown Collab writes under .markdown-collab/ are runtime state for the channel send modes. Add them to .gitignore:
<workspace>/
└── .markdown-collab/
├── .events.jsonl ← channel-mode event log (gitignore)
├── .events.acked.jsonl ← addressed-event ids (gitignore)
├── .channel.json ← mcp-channel endpoint descriptor (gitignore)
├── .mcp-server.json ← review tool server address + session token (gitignore)
└── conventions.md ← standing review conventions (COMMIT this one)
.markdown-collab/
!.markdown-collab/conventions.md
Everything under .markdown-collab/ is runtime state except conventions.md, which is
project prose your team should share — hence the negation above.
Troubleshooting
Start here for anything. Run Markdown Collab: Report a Problem (collect diagnostics) — it answers the first six questions of any diagnosis in one paste (versions, send mode, whether the skill is installed and current, whether the tool server is up, whether a Claude terminal is visible, and what review state each open document holds). Then open Markdown Collab: Show Logs, set the level to Trace, and reproduce: every send, terminal resolution, MCP tool call, tool refusal, and gh/glab invocation is logged with its outcome. Both are safe to share — the session token and anything else credential-shaped is redacted before it is written.
Click did nothing, no toast. Your markdownCollab.sendMode is set to a stale value (e.g., ipc from before 0.11). v0.12.1+ falls back to ask and warns; if you're on something older, change the setting to terminal.
Channel mode: tailer started, but lines don't arrive at Claude.
- Make sure you're on v0.13.1+ (uses
fs.writeSyncto flush per line). - Make sure Claude actually subscribed via
Monitor/BashOutput.TaskOutput block=truewaits for completion and will hang forever — wrong tool. - If your harness has only
TaskOutput, switch toterminalmode. Channel mode requires a streaming primitive.
mcp-channel: "Channels are not currently available." One of: Claude Code <v2.1.80, logged in with API key / Bedrock / Vertex (not claude.ai), or your org has channelsEnabled: false. Diagnose with claude /status and claude --version. Otherwise, use terminal.
A thread shows up as unanchored. The anchored passage was deleted or rewritten beyond recognition, so its markers are gone. Re-anchor it by selecting fresh text in the Inline Comments view and leaving the note again.
Development
npm install
npm run compile
npm test
Three suites, all run in CI and again on every tag:
npm test # Vitest — pure helpers, format engine, prompts
npm run test:integration # a real Extension Host: TextDocuments, WorkspaceEdits, undo
npm run test:webview # the shipped webview bundles in Chromium, driven by a real pointer
The VS Code API surface is stubbed in src/test/vscode-stub.ts for tests of pure helpers.
Press F5 to launch an Extension Development Host for the handful of things no harness
reaches (explorer context menus, the skill install flow, a live Claude session).
To produce a .vsix for distribution:
npx @vscode/vsce package
Releasing
Bump the version in package.json, prepend a ## X.Y.Z — <date> block to CHANGELOG.md,
commit, then tag vX.Y.Z and push the tag. Run node scripts/release-checklist.mjs first —
it prints where the tag will publish and fails on anything a script can decide.
The release commit message picks the destination:
| Marker in the commit | What the tag does |
|---|---|
[skip-publish] |
GitHub Release with the .vsix. Nothing goes public. |
[pre-release] |
Publishes publicly to the VS Code Marketplace and Open VSX pre-release channels. Users who opted into pre-releases get it as an auto-update; everyone else stays on stable. |
| (neither) | Publishes publicly as a stable release to both marketplaces. |
A marketplace version must be plain x.y.z, so the channel can't be encoded in the tag
name — it lives in the commit message, the same way [skip-publish] already did.
The workflow refuses to publish unless the tag matches package.json, the CHANGELOG has a
non-empty section for that version, all three test suites pass, and verify-package is
happy with the built .vsix.
Out of scope (v1)
- Real-time multi-user (multi-human) collaboration. The live editor is single human + Claude; "collab" here means human ↔ AI, not multiple people editing at once.