Annoteca

by Charles Kelsoe
5
4
3
2
1
Score: 51/100

Description

Obsidian plugin for categorized inline feedback comments in long-form markdown. Threaded conversations, anchored highlights, a public API for other plugins, readable by humans and AI assistants.

Reviews

No reviews yet.

Stats

2
stars
1,287
downloads
0
forks
122
days
8
days
8
days
79
total PRs
1
open PRs
3
closed PRs
75
merged PRs
17
total issues
1
open issues
16
closed issues
166
commits

Latest Version

8 days ago

Changelog

Everything from the 1.20.0 betas, listed in full below, plus two fixes: Debug mode now logs, and the reply box in the side panel follows Send comment on Enter.

Added

  • Click the "Original text" of an addressed comment in the Thread tab to jump to that comment in the note. It also works from the keyboard (Tab to it, then Enter or Space). Selecting text in the block to copy it does not jump. (#82)
  • Focus mode in the Thread tab. Press Focus on an expanded comment and the tab shows only that comment, with its full conversation, reply box and actions, so a long thread does not run into the others. Show all brings the list back with the comment still selected. The focus stays put while you switch notes, follows the note through a rename, and keeps showing the comment after you resolve it. Clicking a different comment's marker in the editor leaves focus. (#83)
  • Open in tab opens one comment in a tab of its own in the main area, titled with its category and id, showing only that comment's conversation with the reply box and every action. Opening the same comment again brings its tab forward instead of adding another. The tab comes back after a restart and follows its note through a rename. Comments without an id cannot have a tab. (#83)
  • Range comments. A comment made on a selection now also marks where the selection ends, with a closing marker <!-- /annoteca <id> --> after the passage. The comment then covers exactly that text, however long, across lines and paragraphs: the underline, the highlight and the jump flash cover exactly that span, and Reject restores exactly that span instead of only the rest of the marker's line. Reject refuses, and says why, when the text it would overwrite holds another comment, which it would otherwise delete. Deleting a comment, "Resolve and remove" and "Delete all resolved comments" remove its closing marker with it. Comments made at the cursor, and every existing comment, keep marking only where their passage starts and work exactly as before. A selection that starts or ends inside a code block, inline code or the note properties gets no closing marker, and a notice says why. Older versions of Annoteca read a closing marker as an ordinary hidden HTML comment. (#84)
  • A comment made with a closing marker says so in its own marker ([range=closed], or "range": "closed" with end-of-file storage). The orphan check reports a closing marker that went missing, for example one an edit dropped along with the old text, and closing markers that pair with nothing: one whose comment is gone, one above its own comment, two with the same id, or one whose comment was copied.
  • The exported AI skill teaches closing markers and the [range=closed] line (skill version 10), so re-export it: an assistant on the old skill does not know to keep the closing marker at the end of a passage it rewrites.
  • The Pandoc filter strips closing markers from published output.
  • API: anchorsFor reports a range comment as exactly the text between its markers.
  • API (version 4): promote takes an optional closeRange per request. With it set, Annoteca also writes a closing marker at the end of the range, so the comment covers exactly that text, and each created comment reports closed, saying whether one was written. Without the option nothing changes, and an older Annoteca ignores it.
  • Jumping to a comment briefly highlights it, so you can see where you landed. For an addressed comment the highlight covers the edited text after the marker; otherwise it covers the commented passage, or the marker when there is none. With reduced motion turned on in your system, the highlight shows as a steady tint instead of a fade. (#82)
  • Add comment for current sentence, in the command palette and the right-click menu. Click inside a sentence and run it: Annoteca selects that sentence and opens the comment form, and the comment covers exactly the sentence. A sentence ends at ., !, ? or … followed by a space, keeps its closing quotes, and never runs past its paragraph. Each list item, heading and quote is its own block, and their markup stays outside the sentence. Common abbreviations, initials and decimals do not end a sentence. A table row is not a sentence, since a comment marker inside a row would break the table; select the text yourself there. (#84)
  • The Outline tab is now a tree. Headings nest under their parent headings, and List items adds the note's list items under them, nested as the note nests them. Each line shows a badge for the comments on it, and each heading shows its open and resolved counts rolled up from everything below it, so a collapsed branch still shows its work. Only with comments hides the lines that have none. Click a row to jump to it and see its comments, with buttons to open the thread, go to the text, or open the comment in its own tab. The button on each row comments on exactly that line, leaving out list, task and heading markup. The tree works from the keyboard: Enter selects a row, and the left and right arrows fold and unfold. (#84)
  • API (version 5): compose(path, range) lets another plugin ask you to comment on exact text in a note. Annoteca opens the note, selects that text and opens its own comment form, so the comment is yours, with a closing marker. Nothing is written until you save. It is the hook a companion view, such as a mind map, needs for a "comment on this" action.

Fixed

  • Debug mode did nothing. The setting and its log destination have been in the settings tab since the first version, but nothing read them, so turning it on logged nothing. It now records how long Annoteca takes to index each note, how long a comment write waits behind earlier writes and how long it takes, how long the frontmatter summary waits and takes to write, and when Obsidian's metadata cache picks the summary up, which is when a Bases view can see it. Each entry is one line of JSON, sent to the developer console or to debug.log in the plugin folder. The file keeps roughly the newest 1 MB, and Copy debug log copies it so you can paste it into an issue.
  • The reply box in the Thread tab and in a comment's own tab ignored Send comment on Enter, so Enter always started a new line there. It now follows the setting, like the comment form and the reply box in the note.
  • Clicking a card in the Thread tab moved the cursor to its comment but left the editor highlight on the comment selected before. The highlight now follows the card you click.
  • On a note saved with Windows line endings, the Outline tab could count a comment under the wrong heading.
  • The Outline tab could show the previous version of a note, or "No headings" for a new one, until something else refreshed it. It now updates when Obsidian finishes reading the note.
  • Clicking a comment's text in an open card in the Thread tab now jumps to the comment in the note, the same as the original text of an addressed comment. Clicking a link in the text still follows the link, and selecting text to copy it does not jump. (#82)
  • Opening a comment from a note in a pop-out window opened the comment panel in the main window, on whatever note the main window had open, so it often showed the wrong comment. A pop-out window has no side panel, so the comment now opens in a tab beside the note in the pop-out, and the popover's button there reads Open beside note. This covers clicking a marker, the popover's buttons, the reading-view indicator, the right-click menu, Reply to comment here, and next and previous comment. One tab follows you from comment to comment instead of a new tab opening for each. A comment without a unique ID cannot have a tab, so a notice says to open the note in the main window instead. Clicking a comment in the side panel still selects it there.

VirusTotal

README file from

Github

Annoteca

CI Release GitHub Downloads Obsidian License Latest Release

Categorized inline feedback comments for long-form markdown documents. Comments live in the file as plain HTML markers, so they are readable by humans, by grep, and by any AI assistant. Works on desktop and mobile.

Requires Obsidian 1.13.0 or later.

Annoteca is built for revision work on long documents: book manuscripts, theses, technical docs, sermon and lecture prep. You leave typed feedback at the exact passage it concerns ("tighten this", "needs a source", "doesn't sound like me"), reply in threads, and resolve items as the draft improves. The comments travel with the file, survive without the plugin, and can be stripped cleanly at export time.

Features

  • Categorized comments: every comment carries a category that says what kind of feedback it is. Seven defaults ship for general revision work (Tone, Clarify, Cut, Expand, Tighten, Source needed, Uncategorized); presets add sets for scholarly writing, fiction, code review, and project planning. Categories are fully editable, each with its own icon, color, underline urgency tier and optional default text, and you can save your own preset lists. A category's default text is saved when you insert a comment with the body left empty, so a Cut can simply say "Remove this."
  • Anchored to the text: comment a selection and the commented words get a category-tinted underline in the editor; new markers sit at the start of the passage they concern, and a closing marker after it records exactly where it ends. Comment at the cursor and a small marker icon shows the location. Underline style and thickness are configurable. Opening a comment highlights its passage in the editor, and jumping to a comment no longer yanks your reading position. A jump briefly flashes the passage it lands on, and clicking an addressed comment's original text in the hub jumps to it.
  • Threaded conversations: replies live inside the same marker, in order, each signed with an author tag and date. A per-reply author picker lets several collaborators each sign their own reply, and you can give each author a color so a multi-party thread is easy to scan. A conversation about a sentence stays attached to that sentence, even when the paragraph moves. A marker with replies shows how many, so a one-line note and a long back-and-forth are told apart at a glance.
  • AI revision flow: when an assistant rewrites a passage in response to a comment, it marks the comment addressed and keeps the original text verbatim inside the marker. The comment stays in your queue with an accept, revise, or reject choice: accept resolves it, revise reopens it for more work, and reject restores the original prose automatically. You always see what changed and stay in control.
  • Comment hub: a right-sidebar panel with three tabs: Thread (the conversation view), Outline (a tree of the note's headings and, optionally, its list items, with comment counts rolled up per heading; click to jump, or comment on a line), and Starred (bookmarked comments). The Thread tab scopes to the current file, a folder with or without subfolders, the whole vault, a frontmatter property value, or a tag, and the scope can be pinned. Focus on one comment to see only its conversation until you choose Show all, or open it in a tab of its own.
  • Reading view indicators: markers are invisible in reading view by design, so Annoteca can show a note-level banner with open and resolved totals, a badge on each section that has comments, both, or nothing. Click an indicator to open the hub on that comment.
  • Resolve your way: resolving keeps the comment in the file as a dimmed record by default, and resolved comments can be reopened with one click. Prefer clean files? Use "Resolve and remove", turn on delete-on-resolve, or sweep a file with "Delete all resolved comments".
  • Hover popup: hover a marker to read the thread and reply, resolve, or jump to the hub without leaving the editor.
  • Comments read as Markdown: bodies, replies, and notes render as formatted Markdown in the popup and the hub, so links, emphasis, code, and lists look the way they were written rather than showing their source. [[Wikilinks]] resolve against the note the comment lives in. There is a setting to turn it off, and the one-line body shown beside a marker in the editor stays plain text either way so it cannot reflow the document.
  • Read the whole document's comments at once: "Toggle inline comment bodies" prints each comment beside the passage it is about, so a chapter's feedback reads in a single pass instead of one hover at a time. Bodies are trimmed to a single line and disappear again on the next press.
  • Import what you already have: commands convert Obsidian %%comments%% and plain HTML comments into Annoteca markers, with a backup confirmation first.
  • AI-ready by design: the file is the API: any assistant that can read and edit markdown can read and write Annoteca comments. An "Export AI skill" command writes a skill file into your vault that teaches the assistant the format and your category vocabulary. The exported skill is versioned, so the plugin tells you when it has gone out of date after an update and should be re-exported.
  • Bases-ready summary (optional): turn on a setting and Annoteca keeps a small summary of each note's review state in the note's frontmatter: the number of open comments, and optionally the oldest open date and the categories in play. An Obsidian Base can then filter and sort your notes by review status, for example every note with open comments across a project, as a work queue. Off by default; the comments stay in the note and your existing frontmatter is preserved.

How it works

A comment is an HTML comment with a typed prefix, placed at the text it concerns:

The pricing model needs revisiting before Q3. <!-- annoteca/clarify: which products? -->

Threads, metadata, and resolution live inside the same marker:

The Q3 forecast assumes a hiring freeze through December.
<!-- annoteca/tone: too blunt for the board deck
[id=a3b9c2x7]
[date=2026-05-23]
[anchor=assumes a hiring freeze through December]
[reply ai 2026-05-23]: Consider "reflects current headcount planning through December."
[reply charles 2026-05-24]: Better. Softening it.
[resolved charles 2026-05-25]: reworded the assumption
-->

A comment on a selection also marks where the selection ends, with a closing marker that carries the comment's id. The comment then covers exactly that text, however long, across lines and paragraphs:

<!-- annoteca/tighten: wordy
[id=a3b9c2x7]
[range=closed]
--> The Q3 forecast assumes a hiring freeze through December.<!-- /annoteca a3b9c2x7 -->

The underline and highlight cover exactly that passage, and Reject restores exactly that passage. The [range=closed] line records that the comment was made with a closing marker, so if an edit later drops the closing marker, the orphan check reports it. A comment made at the cursor, and every comment from an earlier version, marks only where its passage starts, and works as it always has. A selection that starts or ends inside a code block, inline code, or the note properties gets no closing marker, since HTML would show there.

When an assistant addresses a comment by rewriting the passage, it records the change on an [addressed ...] line and keeps the original text verbatim in a fenced block inside the marker, so a Reject can restore it:

<!-- annoteca/clarify: hedging
[id=6raa4103]
[anchor=it landed as a shock]
[addressed claude 2026-06-20]: removed the hedging; original preserved inside the marker
-->
The discovery reframed the passage entirely.

Why HTML comments?

  • Nothing breaks without the plugin. The file stays a normal markdown document. Markers never render in reading view or exports, and other tools pass them through untouched.
  • Standard tools work. grep -rn 'annoteca/' finds every comment in a vault. annoteca/tone finds every tone comment.
  • Position is free. The marker is part of the text, so cut, paste, and reorder operations move the comment with its paragraph. No coordinates to repair.
  • Clean publishing. A Pandoc Lua filter (in the repository's docs/ folder) strips markers at export time and converts index-entry comments into LaTeX \index{} commands.

The review workflow

  1. Select a passage and run Add comment for selection (or Add comment here at a bare cursor) from the command palette or the right-click menu. To comment on one sentence, click inside it and run Add comment for current sentence: Annoteca selects the sentence for you.
  2. Pick a category, write the feedback. The composer opens as a modal or as a side panel, your choice.
  3. Reply from the hover popup, the hub's Thread tab, or by typing a [reply ...] line directly in the file.
  4. When an assistant has addressed a comment, the hover popup offers Accept, Revise, or Reject (reject restores the original text). Otherwise resolve when done and reopen if it comes back, or use "Resolve and remove" to drop the marker instead of keeping it as history.
  5. Navigate with "Next comment" / "Previous comment", which follow your current scope across files. The active comment is highlighted in the editor, and opening the panel keeps your place in the document.

Diagnostics commands cover the edge cases: find orphaned comments whose surrounding prose was deleted, clear orphaned stars whose comment no longer exists anywhere in the vault, detect markers that drifted, validate malformed markers, and back up or restore plugin settings.

Annoteca also warns you when a note has a broken comment marker, once per note as you open or save it. A marker that lost its closing tag hides the text after it without anything looking wrong, so the check runs on its own rather than waiting for you to go looking for it, and the notice says how to repair the marker.

Working with AI assistants

Because comments are plain text in the file, an AI assistant needs no plugin API or special integration. Ask it to review a chapter and it can leave categorized comments at the passages it means. Ask it to address your comments and it can edit exactly the flagged passages and reply in each thread explaining the change, leaving the rest of the document untouched. When the fix is a rewrite, the assistant marks the comment addressed and keeps the original text inside the marker, so you can accept, revise, or reject the change from the hover popup. Author tags (author=ai, author=claude) keep the conversation attributed.

To teach an assistant the format, run Export AI skill. It writes a skill file into the vault describing the marker grammar, the reply, address, and resolve conventions, and the exact categories you have configured. The exported skill instructs the assistant never to delete markers or resolve comments unprompted, so your review queue is never quietly cleared. The destination is a setting: .claude/skills/ for Claude Code, a .agent/skills/ folder for other assistants, or both. The skill is versioned; when an update changes the guidance, the plugin flags the exported file as out of date so you can re-export.

Public API

Annoteca has a public, versioned API for other plugins. A companion plugin can attach comments and AI-readable notes to a place in a document without building its own comment store: detect a comment marker with no dependency at all, read your comments, then create and jump to them through the API, and follow what happens to each comment as it happens. There is no hard dependency in either direction, and Annoteca stays the only writer of note markers. Full guide and copyable types: API.md.

Settings overview

Settings are grouped in the order they appear in the tab:

  • Categories: edit the category list, browse and save presets, and set each category's icon, color, underline tier and default text. Pick the default category, and turn on the index-entry preset for print indexing.
  • Editor indicators: how comments look in the editor. Indicator style (icon, underline, both, or hidden) and size; the hover preview and its delay; what a click or tap does (open the side panel or a popover); whether bodies render as Markdown; the reply count on markers; underline style and thickness; and whether comments show when a file opens.
  • Resolved comments: whether resolved comments are dimmed or hidden, how strongly they dim, and whether resolving deletes the marker instead of keeping it as history.
  • Composer: where the comment form opens (modal or side panel), whether Enter sends or adds a line break, and the floating comment button on selected text.
  • Reading view: the indicator that stands in for comments where markers are invisible: a note banner, per-section badges, both, or off.
  • Panel and navigation: whether the hub collapses files you are not editing, and where a marker lands when you jump to a comment (top, center, or minimal scroll).
  • Authors: your author tag, plus collaborators each with a color so a multi-party thread is easy to scan.
  • AI integration: where the exported skill file is written, the export button, the out-of-date indicator that appears after an update changes the guidance, and the optional event journal, a file a tool outside Obsidian can watch to follow comment changes (off by default; ids and metadata only, never comment text).
  • Frontmatter summary (Bases): maintain a Bases-friendly summary of each note's open comments in its frontmatter, choose whether to include the oldest-open date and the open categories, and an optional class tag (off by default, mainly for Fileclass or Metadata Menu users) with its property name.
  • Diagnostics: debug logging and where the log is written.

Installation

Annoteca requires Obsidian 1.13.0 or later. Obsidian offers the matching plugin version automatically; on older Obsidian versions the plugin will not appear as updatable beyond the last compatible release.

  1. Open Obsidian settings.
  2. Navigate to Community plugins.
  3. Click Browse.
  4. Search for Annoteca.
  5. Click Install, then Enable.

Manual installation

  1. Download main.js, manifest.json, and styles.css from the latest release.
  2. Create a folder named annoteca in your vault's .obsidian/plugins/ directory.
  3. Copy the downloaded files into this folder.
  4. Reload Obsidian.
  5. Enable Annoteca in Settings → Community plugins.

BRAT (optional, for pre-release testing)

BRAT lets power users install pre-release builds before they reach the marketplace.

  1. Install the BRAT plugin from Community Plugins.
  2. Open BRAT settings and click Add Beta Plugin.
  3. Enter: https://github.com/ckelsoe/obsidian-annoteca
  4. Enable Annoteca in Settings → Community plugins.

Privacy

Annoteca reads and writes only your vault. No network requests, no telemetry, no data leaves your machine. See PRIVACY.md.

Community

Questions, ideas, and general discussion happen on Discord. For anything that needs tracking, a GitHub issue is still the better home.

Contributing

See CONTRIBUTING.md for setup, quality gates, and conventions.

License

MIT. See LICENSE.