# Scrivener Annotations

> When the user wants to work with Scrivener comments and footnotes — both linked (margin) notes and inline notes. Use when the user says "add a comment", "insert a footnote", "show comments/footnotes", "list the comments on this chapter", "convert inline footnotes to linked", or "who wrote this comment". Detecting that a document has comments/footnotes is available now; adding, editing, deleting, and converting them is planned. For pulling note bodies out into Markdown/text, see scrivener-extract. For editing the surrounding body text, see scrivener-edit. For direct text formatting, see scrivener-formatting.

- Skill: `donnfelker/scrivener-annotations` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add donnfelker/scrivener-annotations`
- Raw SKILL.md: https://api.skillmd.com/api/skills/donnfelker/scrivener-annotations/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: donnfelker (https://skillmd.com/u/donnfelker)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/donnfelker/scrivener-annotations

---


# Scrivener comments & footnotes

You help the writer work with Scrivener's two kinds of margin notes — **comments**
and **footnotes** — each of which can be stored in **two ways**: *linked* (the note
body lives in a side file and is anchored from the text) or *inline* (the note is
written directly into the body text). Today the toolkit can **detect** that a
document carries comments/footnotes; **creating, editing, deleting, and converting**
them is on the roadmap because it needs the token-preserving RTF layer.

Always read the document first so you know which kinds of notes are present before
proposing any change.

## The two storage models

Scrivener stores a comment or footnote as **either**:

- **Linked (margin) note** — the note **body** lives in the per-document
  `content.comments` XML file (with author and color), and the **anchor** is an RTF
  `HYPERLINK` field inside `content.rtf` whose target is `scrivcmt://<UUID>`. The body
  and the anchor are two separate things in two separate files, joined by that UUID.
- **Inline note** — there is no side file. An **inline annotation** (the comment-like
  inline note) and an **inline footnote** are written *directly into* `content.rtf` as
  marked ranges. Nothing in `content.comments`.

A *comment* and a *footnote* differ only in role (margin remark vs. numbered note at
compile); both exist in linked and inline form. See
**[references/comments-and-footnotes.md](references/comments-and-footnotes.md)** for the
full storage map, the `content.comments` XML shape, and the planned commands.

## Why this all lives partly inside content.rtf

Linked-note anchors (`scrivcmt://`), inline annotations, and inline footnotes are
encoded **inside the RTF byte stream**, alongside style markers, internal links, and
embedded images. That is the same reason `scrivener-edit` defaults to a
**token-preserving** edit model: naïvely regenerating "minimal RTF from text" would
orphan every linked comment (the anchor disappears but the `content.comments` body
stays, pointing nowhere), delete inline notes, and break links and images.

So **writing** comments/footnotes — placing or removing the `HYPERLINK` anchor,
editing the matching `content.comments` entry, or converting inline↔linked — requires
the token-preserving RTF writer. That layer is still being built, which is why the
write/convert commands below are marked planned, not available.

## Detecting notes today (available)

`read <id>` exposes a `constructs` object. When a document contains any comment or
footnote, `constructs.comments_or_footnotes` is `true`:

```bash
python3 ${CLAUDE_PLUGIN_ROOT}/tools/scrivener/cli.py read "<uuid-or-title>" \
  --project "<path.scriv>" --format json
```

Use this to answer "does this chapter have comments/footnotes?" and to decide whether
a later edit needs the destructive guard. The `constructs` flag tells you a note
exists; it does not yet return the note bodies, authors, or colors as structured
fields.

To pull the note bodies (linked comment/footnote text) out as Markdown or text, route
to **scrivener-extract**, which reads `content.comments`. Don't hand-parse RTF here.

## Adding, editing, converting notes (planned)

These are the planned workflows. When asked, explain the intended command, note it is
**not yet in the CLI**, and suggest the closest available step (read to confirm what's
there; extract to pull bodies out; edit body text in `scrivener-edit`).

| Goal | Planned command |
|---|---|
| Add a linked or inline comment | `comment add <id> --text … [--author …] [--color …] [--inline]` |
| Edit / delete a comment | `comment edit <id> <comment-id> …` · `comment delete <id> <comment-id>` |
| Add a footnote (linked or inline) | `footnote add <id> --text … [--inline\|--linked]` |
| Edit / delete a footnote | `footnote edit …` · `footnote delete …` |
| Add an inline annotation | `annotation add <id> --text …` · `annotation delete …` |
| Convert a note inline↔linked | `note convert <id> --to inline\|linked` |
| List comments/footnotes (structured) | `comment list <id>` · `footnote list <id>` |

Until these ship, "convert inline footnotes to linked" cannot be done safely by the
toolkit — say so plainly rather than risk a destructive RTF rewrite.

## Safety (restate before any future write)

- Close the project in Scrivener **and** let cloud sync (Dropbox/iCloud) finish first.
- Writes auto-backup (zip) and auto-snapshot a document before overwriting its text.
- `docs.checksum` mismatches are advisory — never treat them as corruption.
- Titles are not unique — address a document by **UUID** when a title is ambiguous.
- Never regenerate a rich document from plain text; a document with linked anchors,
  inline notes, styles, links, tables, or images must be edited token-preserving (or
  snapshotted and passed `--allow-destructive` deliberately).

## Toolkit support

✅ Available now:

- `read <id>` — exposes `constructs.comments_or_footnotes` (true when the document has
  any comment or footnote); also `constructs` flags for styles/images/tables/links/lists.

🔜 Planned:

- `comment add|edit|delete|list` — linked & inline comments (author, color).
- `footnote add|edit|delete|list` — linked & inline footnotes.
- `annotation add|delete` — inline annotations in the RTF.
- `note convert --to inline|linked` — switch a note's storage model.

All planned commands depend on the token-preserving RTF write layer.

## Related skills

- **scrivener-extract** — pull comment/footnote bodies out of `content.comments` into
  Markdown/text (the way to *see* note text today).
- **scrivener-edit** — token-preserving edits to the surrounding body text;
  explains why rich docs are never regenerated from plain text.
- **scrivener-formatting** — direct text formatting; comments/footnotes are notes, not
  formatting, but both live inside `content.rtf`.
- **scrivener-format** — the package reference: where `content.comments` and the
  `scrivcmt://` anchors sit in a `.scriv`.

