{
  "markdown": "# Obelisk\n\nInline comments and GitHub-style suggested edits for [Obsidian](https://obsidian.md).\n\nSelect a passage, leave a comment on it, and optionally propose a replacement\nthat can be applied with one click. Comments are stored in the note's own\nfrontmatter, so they travel with the file through sync, git, export and\nrename.\n\n> An *obelus* (†) was the mark ancient editors drew in the margin of a\n> manuscript to say: this passage is disputed.\n\n## Status\n\nEarly. Anchoring, decoration, the sidebar, suggested edits and the agent\nintegration are implemented. The plugin is in the Obsidian community plugin\ndirectory, and the CLI and the MCP server are on npm as `obelisk-mcp`. None of\nit has been exercised against a large vault.\n\n## Install\n\nSearch for **Obelisk** in *Settings → Community plugins → Browse*, install it,\nand enable it. Updates come from the same panel.\n\nThe plugin can also be added via the *Add to Obsidian* button in its\n[directory listing](https://community.obsidian.md/plugins/obelisk).\n\n## Features\n\n- **Comment on any passage.** Select text, right-click, *Add comment*.\n- **Markdown everywhere.** Comments and replies are ordinary markdown, with a\n  Write/Preview pair while you type. Links, lists, callouts, embeds and math\n  render in the sidebar exactly as they would in a note.\n- **Suggested edits.** A proposal is a fenced ` ```suggestion ` block *inside*\n  the comment, the way GitHub does it. It renders as a diff against the quoted\n  passage with an Apply button, so one comment can explain itself and propose a\n  change, and a reply can offer a counter-proposal. Applying is refused if the\n  underlying text has changed since. It also resolves the comment, and *Reopen*\n  is there if the comment asked something the edit did not answer.\n- **Sidebar.** All of a note's comments in document order, or newest first from\n  the sort toggle. Click one to scroll the editor to it. Chips filter to open\n  comments, to comments carrying a suggestion, or to one agent's review pass.\n  Resolved comments stay in the list, grayed rather than hidden, since they are\n  still highlighted in the note.\n- **In-text highlighting.** Commented passages are highlighted, with a †\n  marker that opens the comment in the sidebar.\n- **Stored in frontmatter.** Plain YAML under an `obelisk` key. Readable,\n  diffable, portable.\n- **Survives editing.** A comment is anchored to the text it quotes, so it\n  keeps up with edits anywhere else in the note, including ones made outside\n  Obsidian. Edit or delete the quoted passage itself and the comment detaches:\n  flagged in the sidebar, highlighting nothing, never moved onto a different\n  passage and never dropped. Restore the text and it reattaches. Resolved\n  comments are exempt from the flag, because a resolved comment usually\n  detaches when the edit it asked for is made.\n- **The editor you already use.** Comments are written in Obsidian's own\n  markdown editor, so Cmd+B, list continuation, `[[` autocompletion and live\n  preview work in a comment exactly as they do in a note.\n- **Threaded replies.** On any comment, stored alongside it, and markdown all\n  the way down.\n- **Editable.** Rewrite a comment or a reply in the same composer that wrote\n  it, suggestion button and all, from the card's *Edit* button or by\n  right-clicking the passage. Edited bodies are marked as such. The anchor is\n  left alone, so changing what you said never changes what you said it about.\n- **Deletable.** A whole comment from the card's *Delete*, or a single reply\n  from the trash icon in its header, so striking one remark out of a thread\n  does not take the conversation with it. Both offer an undo rather than a\n  confirmation dialog.\n- **Open to agents.** A command-line tool and an MCP server read and write the\n  same comments from outside Obsidian, so a model can review a note into the\n  sidebar, or answer the comments left for it. Its comments are\n  badged, and a whole review pass is one chip in the header with a *dismiss\n  all* on it. See below.\n\n## Data format\n\n```yaml\n---\nobelisk:\n  - id: cq7fk2m9x\n    author: zach\n    created: 2026-08-29T14:02:11.000Z\n    body: |-\n      This paragraph does two things at once.\n\n      ```suggestion\n      The horse bolted.\n      ```\n    anchor:\n      from: { line: 12, col: 0 }\n      to: { line: 12, col: 47 }\n      quote: The horse, which had been standing there, bolted.\n---\n```\n\nA comment is one piece of markdown. A proposed edit is a ` ```suggestion `\nfenced block inside it, whose content replaces exactly the anchored range when\napplied, so one comment can hold prose, a link and a proposal at once.\n\nThe `quote` is what a comment is anchored by. The line/column range records\nwhere the passage was when the comment was written. It orders the sidebar and\nbreaks ties when a quote appears twice, and is never rewritten. Lines are\ncounted from the first line *after* the frontmatter block, so adding a comment\nnever invalidates the others.\n\nA comment written by a model carries one more key, `origin`, holding the model\nand an id shared by every comment in that review pass. Its absence means a\nperson wrote it, so nothing already in a vault needs migrating.\n\n## Agents\n\nThe same comments, from outside Obsidian. A model reviews a note and its\nremarks appear in the sidebar of the note you already have open. Or you leave\ncomments asking for things and a model reads them, makes the edits, and\nresolves them.\n\n```bash\nnpm install -g obelisk-mcp            # puts `obelisk` and `obelisk-mcp` on PATH\n\nobelisk list note.md\nobelisk comment note.md --quote \"The horse, which had been standing there, bolted.\" \\\n  --body \"Two clauses fighting over one sentence.\" --run r7k2mq\n```\n\nFor an agent that speaks MCP, register the server with it:\n\n```bash\nclaude mcp add obelisk --scope user -- npx -y obelisk-mcp\n```\n\nOne registration covers every vault: the tools work on whichever vault the\nagent is running in, and an absolute path reaches a note in one it is not. The\nserver is listed in the official MCP registry as `io.github.zachhannum/obelisk`\nfor a client that installs from there.\n\n**The agent starts it.** It speaks MCP over stdio: the agent spawns a process\nwhen a session opens and kills it when the session ends, so there is no port\nand no daemon. One process per session is also what makes a session's comments\nshare one run chip in the sidebar. A session keeps the process it spawned, so a\nnew version of the package arrives at the next one. To take it sooner,\nreconnect from `/mcp`.\n\nTo check the registration, `claude mcp list`, or `/mcp` inside a session. To\ncheck the server itself with no agent in the way:\n\n```bash\nprintf '%s\\n' \\\n  '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"smoke\",\"version\":\"0\"}}}' \\\n  '{\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}' \\\n  '{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\"}' \\\n  | npx -y obelisk-mcp\n```\n\nThat prints the handshake and then the four tools. A server that fails this\nfails the same way for an agent.\n\nFor an agent that does not speak MCP, paste\n[`docs/agents-fragment.md`](docs/agents-fragment.md) into the vault's\n`AGENTS.md` or `CLAUDE.md`.\n\nThe one rule worth knowing: **the quote is the anchor.** A line number is never\none. A model asked for a line produces a plausible wrong number, which attaches\na comment to the wrong paragraph without looking like an error, so\n`--near-line` only picks between identical quotes and takes a number copied out\nof `obelisk list`. `--quote` has to appear in the note character for character,\nand if it does not, or appears twice, nothing is written and the reason is\nprinted. `obelisk list` prints the body numbered so the exact text is there to\ncopy.\n\nWrites are frontmatter-only and leave the body byte-identical, so they are safe\nwhile the note is open in Obsidian. A write also re-reads the file first and\nrefuses if it changed underneath.\n\n## Development\n\n```bash\nnpm install\nnpm run dev      # watch build, plugin only\nnpm run build    # typecheck, then main.js plus dist/cli.mjs and dist/mcp.mjs\n```\n\n`src/core/` is the half that does not import Obsidian: the model, the anchor\narithmetic, the YAML and the four verbs. The plugin, the CLI and the MCP server\nare three front ends over it.\n\n`site/` is the documentation site, an Astro project of its own with its own\n`npm install`. It is not part of `npm run build`.\n\nSymlink the repo into a test vault to try it:\n\n```bash\nln -s \"$PWD\" /path/to/vault/.obsidian/plugins/obelisk\n```\n\n## License\n\nMIT\n",
  "bytes": 8556,
  "sha": "d6a191f551499dbb232a06f1ed18581d6f3fcdeab0ba39cb921e7643a2103e35",
  "repo_slug": "zachhannum/obelisk",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_zachhannum_obelisk_2fb0841b/readme"
}