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.commentsorfootnotes is true:
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.commentsorfootnotes (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.