Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Tether MD

FreeNot checked

Enables anchored comments in Markdown files that AI agents can propose changes for, with human approval before application, all managed via an MCP server.

GitHubEmbed

About

Enables anchored comments in Markdown files that AI agents can propose changes for, with human approval before application, all managed via an MCP server.

README

Tether MD

You comment. The agent proposes. You decide.

CI npm license: MIT

The Tether MD loop: comment on a phrase, the agent proposes a diff, Accept applies it, export is byte-identical

Comment across the draft, as fact or interpretation. The agent works through every comment in one pass; you accept or reject each change. Export stays byte-identical.


Most AI writing surfaces either rewrite your document under you (chat canvases, "apply" buttons) or lock review into a platform (Google Docs, Word, Notion). Markdown in git has no standard suggest mode: a way to leave a comment on a phrase, have an AI act on it, and approve or reject each change yourself.

Tether MD is that layer: anchored comments for Markdown that AI agents act on, but never apply. It is a file format rather than a platform.

  • Comments live in the file. One invisible HTML-comment marker per comment, plus a machine-readable block at the end. No database, no sidecar, no service; the raw file renders clean on GitHub, in VS Code preview, and through pandoc.
  • Anchors survive editing. Quote selectors with fuzzy re-anchoring follow the text through edits, flag uncertain matches as needs-review, or orphan with an error.
  • Agents propose; humans apply. Your comments are anchored instructions. An agent attaches proposals; Accept applies one and clears the comment, Reject discards it. Paragraph moves follow the same rule: mark where text should go, and nothing moves until you press Accept Move.
  • Clean export is tested in CI. One projection function strips the comment layer; the result is byte-for-byte your prose.

Install

Three pieces. The CLI is the foundation; the other two are optional and independent.

  1. CLI + MCP server — npm i -g tether-md (Node 20+). Gives you the tether command and tether mcp.
  2. VS Code extension — download tether-md.vsix from Releases, then Extensions panel → → Install from VSIX → reload the window. (Or from a clone: npm install && npm run build && npm run package -w tether-md-vscode.)
  3. Agent compatibility, per project — run tether init in the project root. It writes .mcp.json (project-scoped MCP server) and the AGENTS.md contract note; tether init --skill also installs the Claude Code skill. Details in Hook up your agent.

Quickstart

npm i -g tether-md
printf 'A draft with some exact phrase in it.\n' > draft.md
tether comment add draft.md --quote "some exact phrase" --body "tighten this" --write
tether status draft.md                       # comments, proposals, anchor health
tether comment suggest draft.md <id> --to "a tighter version" --write   # the agent's move (or yours)
tether comment diff draft.md <id>            # preview:  - current / + proposed
tether comment accept draft.md <id> --write  # apply it and clear the comment
tether export draft.md                       # the authored prose, byte-identical

Every mutating command prints its result by default, only edits in place with --write (atomically), and takes --json; comment list and error envelopes are JSON already. Exit codes are stable:

code meaning
0 ok
1 usage error
2 malformed store block
3 IO error
4 check failed (status --check)

Try it on a real document in 30 seconds: examples/ ships a worked walkthrough, including the one-line proof of the export guarantee (tether export reviewed.md | diff - draft.md prints nothing: byte-identical).

Hook up your agent

One command, in your project:

tether init            # .mcp.json (project-scoped MCP server) + AGENTS.md contract note
tether init --skill    # also installs the Claude Code skill into .claude/skills

Claude Code discovers .mcp.json on its own the next time the project opens, and AGENTS.md carries the contract for agents that bring their own file tools. Both writes are idempotent and merge into existing files. To wire the MCP server by hand instead, any MCP-capable agent works (Claude Code, Cursor, Codex CLI, and others):

claude mcp add tether -- tether mcp

The MCP server exposes tether_list, tether_status, tether_diff, tether_suggest, tether_comment (flag-backs), and tether_export. It deliberately omits accept, reject, and edit, and its server instructions tell every connected agent to stay on that surface. Within it, the trust boundary is structural, not prompt etiquette.

One caveat that matters: most coding agents (Claude Code, Cursor, and friends) also carry their own file tools, and no file format can gate those. An agent that has never been told the contract will treat a Tether file like any other markdown and edit it in place. So tell it: run tether init, install the skill below, or add this to your project's AGENTS.md or CLAUDE.md:

Markdown files here may contain tether-md comments: invisible <!--tether:...-->
markers plus a store block at EOF. Never edit these files directly; never touch
the markers or the store block. Read the threads with `tether comment list`,
propose rewrites with `tether comment suggest <file> <id> --to "..." --write`,
flag concerns with `tether comment add <file> --quote "..." --body "..."
--author agent --write`. Accept, reject, and export belong to the human.

For Claude Code there is also a full skill, skills/tether-edit/SKILL.md. It teaches the contract end to end: read the document, read the comments, propose per instruction, flag back anything that can't be grounded, hand control back. The agent never applies, resolves, or exports.

The working loop becomes: comment on phrases, tell the agent to "address my comments", then review each suggestion in your editor and accept or reject it.

In VS Code

Install per Install above, open any markdown file, and everything below works on it. Comments render as native inline threads; nothing needs configuring.

keys / surface what it does
select prose, ⌘⌥C (Ctrl+Alt+C) comment on the selection: type the note, pick fact or interpretation
gutter + same, mouse-first (one + per logical line; for a second comment on the same soft-wrapped paragraph, select and use the keybinding)
caret in a paragraph, ⌘⌥M (Ctrl+Alt+M) pick the paragraph up to move (no selection needed); then click where it should go — the click snaps to the nearest paragraph boundary
⌘⌥M again while a move is armed destination list with a live "move here" preview in the editor
Esc cancel an armed move (any edit also cancels it)
thread buttons Accept / Reject on an agent's suggestion; Accept Move / Reject on a move; Delete on a plain comment
right-click menu Tether: Add Comment from Selection, Tether: Move Paragraph
command palette Tether: Export Clean Document — writes <name>.clean.md beside the file

A marked move is just a comment with a destination: the excerpt gets a ① badge, the destination a ⇣① badge, and nothing actually moves until you press Accept Move on its thread. Moves show up in tether comment list (a moveTo field) and tether comment accept applies them, so the CLI and the editor stay interchangeable.

If anchoring ever degrades, you hear about it: fuzzy re-anchors get a dashed warning underline and a diagnostic, and Accept refuses until re-confirmed; orphans land in the Problems panel with a one-click fix.

The editor and the agent never talk to each other. Both only touch the file, so you can watch proposals arrive in your open editor.

What the file actually looks like

The pattern is always the same. The app starts as a text editor and becomes a
database. <!--tether:c=01KWQ2QFDFTHXWAF7RJS1ZNSSX-->Databases survive until the
next funding round.

<!--tether:store
{"id":"01KWQ2QFDFTHXWAF7RJS1ZNSSX","v":1,"trust":"fact","author":"human","body":"sharpen this",...}
tether:store-->

One caret marker per comment (a ULID, which can never form the -- sequence HTML comments forbid), and all data in one JSONL store block at the end of the file, escaped to stay grammar-legal. Renderers hide HTML comments, so the raw file previews clean on GitHub, in VS Code preview, and through pandoc. The grammar, the projection algorithm, the selector model, and the re-anchoring confidence bands are specified in docs/spec/wire-format-and-projection.md. The spec is the product; the TypeScript here is the reference implementation.

What happens when you edit the text

A comment points at a phrase, and you keep editing the document. Each time the file is read, every comment is re-matched to the current text and gets a confidence score between 0 and 1. The score decides one of three outcomes:

outcome when what you see
anchored the phrase still matches (score ≥ 0.75) the comment follows its text
needs-review the phrase changed enough to blur the match (0.50–0.75) a dashed warning underline and a diagnostic; Accept refuses until you re-confirm
orphaned the phrase is effectively gone (below 0.50) a loud error; tether status --check exits 4, so CI can catch it

A weak match downgrades to needs-review or orphans loudly; it does not silently attach to the wrong words.

A comment follows its text through edits, gets flagged when its phrase is reworded, and orphans loudly when the phrase is deleted

Matching tries the exact phrase first, disambiguates duplicates by their surrounding context, and only then falls back to fuzzy matching, which is where the score comes from (details in the spec). One extra safeguard on top: accepting a proposal requires the anchored text to still read exactly as it did when the proposal was made, so a stale suggestion can never splice onto changed wording.

The three invariants

Everything above reduces to three properties, tested on every commit:

  1. Re-anchor or orphan. After any edit, every comment re-anchors above the confidence floor or orphans loudly. Weak matches are never silent.
  2. Zero perturbation. Adding or removing a comment never changes the exported prose or any other comment's anchor.
  3. Export identity. tether export is byte-for-byte the authored prose.

How it compares

comments in the file survive edits AI propose, human accept works with any agent clean export guarantee
Tether MD yes fuzzy, loud orphans native threads / CLI CLI + MCP + skill byte-identical, in CI
Google Docs / Word / Notion no (platform DB) yes their AI only no export differs from source
GitHub PR suggestions no (PR thread) no (stale on rebase) in the PR UI PR-bound bots n/a (reviews a diff, not the doc)
CriticMarkup yes (visible syntax) inline, no drift detection no native flow format only processor-dependent
Cursor / chat canvases no (session diff) until the session ends no
Roughdraft yes (CriticMarkup) inline, no drift detection in its local web UI yes (CLI) not spec'd or CI-tested

The bet: suggest mode should be a property of the document, not of an app. That is also why the wire format is specified independently of this implementation; ports are welcome.

Why not CriticMarkup? Its syntax is visible noise in any CriticMarkup-unaware renderer (GitHub included), and its comments bind only by adjacency: nothing detects when the prose they were about is rewritten. Tether's markers hide in rendered views and re-anchor by quoted text. Why not PR review? Suggestions there attach to diff lines in a forge's database, need a remote and a pull request, and go stale on rebase; here the document itself carries the review, offline, in any repo state.

Monorepo

Package What
tether-md The tether CLI and MCP server (tether mcp): the stable, file-only contract surface.
@tether-md/kernel The pure projection kernel: P(raw) → clean, offset maps, anchoring, store codec. No IO.
tether-md-vscode The VS Code extension (native Comments API).
skills/ The agent contract (Claude Code skill).
docs/ The wire-format spec, architecture decision records, milestone history.
git clone https://github.com/tether-md/tether-md && cd tether-md
npm install && npm run build && npm test

Limitations

  • Editor UI is VS Code-only today. The kernel is editor-agnostic; Obsidian and nvim ports are the most-wanted contributions.
  • The propose-not-apply contract is structural on the MCP surface, but an agent with its own file tools follows it only once it has the skill or the AGENTS.md note above. An untold agent edits the file like any other markdown.
  • Store blocks are LF-only by grammar. CRLF hard-fails loudly rather than mis-parsing; the repo's .gitattributes protects checkouts, and tolerant reads are tracked.
  • Paragraph moves are LF-only and paragraph-granular (paragraphs are blank-line separated). Seams that touch CRLF or whitespace-only blank lines, and destinations whose text repeats verbatim elsewhere, are refused loudly rather than guessed at.
  • A file with a pending move is written as a v: 2 record: tether-md 0.1.x refuses the whole file until the move is accepted or rejected (deliberate — an older version could otherwise half-apply it). Accepting or rejecting all moves returns the file to v: 1.
  • One store block per file; concurrent writers race at the file level. Treat the raw file like source code (git merges the store poorly).
  • A comment anchored inside a code region relocates its marker to just before that region. Two pathological shapes are rejected with clear errors.

Roadmap

  • Verification gate (the origin of this project): fact-grounding and claim-strength checks whose findings arrive as anchored comments.
  • CriticMarkup import/export, conformance test vectors for ports, an Obsidian plugin, a browser build of the kernel.

Contributing

The spec comes first, the three invariants are non-negotiable, and correctness bugs get priority over everything else. See CONTRIBUTING.md.

License

MIT

from github.com/tether-md/tether-md

Installing Tether MD

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/tether-md/tether-md

FAQ

Is Tether MD MCP free?

Yes, Tether MD MCP is free — one-click install via Unyly at no cost.

Does Tether MD need an API key?

No, Tether MD runs without API keys or environment variables.

Is Tether MD hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Tether MD in Claude Desktop, Claude Code or Cursor?

Open Tether MD on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Tether MD with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All ai MCPs