Use when writing or revising a document for the Loupe app, anything sent through the loupe MCP's document_create or document_revise (implementation plans, specs, RFCs, audit reports, retrospectives, any long-form review document).
Installs into .claude/skills of the current project.
Are you the author of Loupe Documents?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/ubermuda-loupe-documents)
---
name: loupe-documents
description: Use when writing or revising a document for the Loupe app, anything sent through the loupe MCP's document_create or document_revise (implementation plans, specs, RFCs, audit reports, retrospectives, any long-form review document).
---
# Writing documents for Loupe review
Reviewers read what you send to `document_create` / `document_revise` in the
Loupe review UI, where they select passages and comment on them. Format for that
reading context, not for a terminal or a README.
## Rules
1. **No H1 title in the body.** Loupe's own `title` field holds the title, so an
`# Heading` repeating it renders twice. Start with content, or with the first
`##` section.
2. **Prefer numbered lists over bullet lists.** Reviewers cite entries in
comments ("point 3 is wrong"), which numbers permit and bullets do not. Use
bullets only where order and reference genuinely do not matter, such as a
short set of interchangeable examples.
3. **Cross-references need stable IDs, because list numbering restarts at every
heading.** Markdown starts a new ordered list after each `##`, so source
entries numbered 1–33 render as 1–2 under the first heading, then 1–5 under
the next, and a "see finding 6" points at nothing the reviewer can see. A
self-hosting audit shipped with every cross-reference broken, and the
reviewer's first comment was that finding 6 did not exist.
When entries refer to one another, give each a short ID that does not depend
on rendering: `C1`, `H4`, `M5` for severity-banded findings, or any scheme
where the prefix names the section. Lead the entry with it:
```markdown
4. **H4 — There is no administrative console command.** …
```
Refer to **H4**, never "finding 4". Keep the list numbered as well (rule 2
still applies): the number gives the reviewer something to point at, the ID
gives the text something stable to cite. Entries that never reference each
other need no IDs.
4. **In long lists, open every entry with a short introductory sentence** saying
what the entry is about, before the detail. A reviewer scanning the list must
grasp each entry from that sentence alone, without diving into a wall of
`file:line` references or jargon.
5. **Make decision points look like decisions.** Where the document offers more
than one way to do something, the formatting must show the reader that you
ask for a choice. Write an explicit "**Decision needed:**" lead-in or
equivalent, put the alternatives in a numbered sub-list so they can be
referenced, and name your recommendation if you have one. Never fold
alternatives into a flat sentence ("do X or do Y."): that reads as an
instruction, and the reader sails past the choice.
Where the alternatives are a clean either/or, also wrap them in a **decision
fence** (rule 12), so the reviewer clicks an option instead of typing "option
2" into a comment for you to parse back out.
6. **After you address review comments, revise the document.** Send a new
version with `document_revise` so the document shows the resolved state; an
outcome recorded in an issue tracker, the chat or a commit message leaves the
returning reviewer on a stale proposal. Mark each affected entry with a
**Decided:** line naming what was chosen and where the work now lives. Add no
revision note, changelog or "updated on <date>" header, because Loupe tracks
versions itself and shows them in the UI. Skip the revision only when the
comments changed nothing in the content: pure acknowledgements, or questions
answered entirely in chat with no bearing on what the document says.
Revising re-anchors open comments onto the new version, and those whose
quoted text no longer appears come back **orphaned**. Rewriting a passage you
were asked about therefore orphans that comment. That is normal and no reason
to avoid revising, but keep the reviewer's quoted phrases intact where you
can, and expect the orphan count in the tool's response.
7. **Reply to comments before you revise, or re-read the review afterwards.**
`document_reply_to_comment` and `document_mark_comment_addressed` take the
comment ids from `document_get_review`, and **`document_revise` invalidates
every one of them**: re-anchoring copies a comment onto the new version and
leaves the original behind. The old ids still exist and still look pending,
so the natural order of read-review, revise, then reply writes into rows
nobody reads. Both tools reject a stale id loudly, with a `superseded` skip
or an error naming both version numbers, but by then you have composed a
reply you must redo. Two orders work:
1. Reply to each comment and mark it addressed **first**, then call
`document_revise` once at the end.
2. Revise first, then call `document_get_review` again and use the fresh
ids.
The first is usually better: your replies describe changes the reviewer is
about to see, and each thread's status is already correct when the new
version lands.
8. **Replies are two or three sentences.** A reply is a turn in a conversation,
not a section of the document: say what you did or what you concluded, then
stop. Use no headings, no bold lead-ins, no bullet or numbered lists and no
tables. Do not restate the comment back to the reviewer, and do not rehearse
the reasoning that produced the answer. This is a complete reply: "Renamed to
`AccountStatusChecker` — `ActiveUserChecker` collides with `countActive()`,
which already means something else here."
Reply length also tells you where an answer belongs. An answer needing more
than a short paragraph belongs in the document, which the reviewer re-reads
later; a comment thread is the worst place to keep a decision. Put it in the
next version and let the reply be the pointer, as in "Reworked that section
in v4." Disagreement earns more room, because the reviewer needs the
reasoning to judge it, and even then one paragraph is enough.
9. **Say what changed in the version description.** `document_revise` requires a
`description`, and `document_create` takes an optional one. Loupe shows it
under that version in the review UI's version list, and a reviewer coming
back to "v4" reads it to decide whether to re-read the document at all. Name
what you rewrote, added or dropped, and why, in one or two plain sentences.
Useful, because a reviewer can act on it:
```
Replaced the rollout section with a phased plan, and answered the two
questions on caching. Section 3 is unchanged.
```
Useless, because it restates the mechanism the version already proves:
```
Updated the document. · Revision 4. · Addressed review comments.
```
Name the sections or entries you touched, so a reviewer can skip straight to
them. Say explicitly when something they commented on did **not** change, and
why, because silence reads as an oversight. Do not restate the title, the
date or the version number; Loupe records all three itself.
On `document_create` the description answers a different question: what this
document is and what it exists to settle. One sentence is usually enough
("Design spec for the site-review widget, deciding the auth model").
10. **Renaming is `document_rename`, not a revision.** To fix a typo in a title,
or to make a batch of related documents consistent, call `document_rename`;
it changes the title and nothing else. Resubmitting unchanged markdown
through `document_revise` mints a version whose description can only say
"renamed", and every version after it is one more entry a reviewer has to
skip. `document_revise` takes a `title` only when the content and the title
change together.
11. **Point at the passages that matter with `document_highlight`, where the
instance offers it.** Highlighting is off by default, and an instance with it
off does not advertise the tool at all. **If `document_highlight` is not
among your tools, skip this rule.** Nothing else in it applies and there is
no fallback: say what you would have marked in prose, or say nothing.
Where it is on, use it: on a long document, where the reviewer starts
reading is most of what you control. Quotes match the **rendered prose**,
not your Markdown source, every call replaces the whole set, and
`document_revise` drops them. Read `references/highlights.md` before you
call it.
12. **A decision fence turns a choice into something the reviewer clicks.** A
pair of `<!-- decision: some-id -->` and `<!-- /decision -->` comments around
the alternatives renders them as radio buttons, whose answer comes back in
`document_get_review` under `decisions`. Mark every option `- [ ]` instead
to let the reviewer pick several. End the one option you recommend with
`(recommended: high)`, `moderate` or `low` to show a badge on it. **An id
is permanent once published**, and **a changed id silently discards the answer**: no error, no
warning, and the decision reads as unanswered again. A malformed fence
degrades to a plain list, also with no error. Read
`references/decision-fences.md` before you write one.
13. **A stray HTML comment renders as a visible annotation**, on its own line as
a block note or inside a paragraph as an inline note. Never wrap such a
comment in an HTML element that opens its own block. Loupe then keeps the
element and drops the comment, so the annotation disappears with no error.
14. **Find a document with `document_list`, not with `document_get` on every
row.** Each row carries the description of the document's current version,
so the list alone usually tells you which document you want. Four arguments
narrow it, and they combine:
1. `search` matches full-text terms against the title and the current
content of every document. Quotes and `OR` work as in a web search box.
The rows come back by relevance instead of by recency.
2. `status` keeps one state: `in-review`, `approved` or
`changes-requested`. An unknown value is refused.
3. `tag` keeps the documents that carry one tag, matched ignoring case.
Read `tag_list` for the project's vocabulary.
4. `series` keeps the documents in one series, matched ignoring case, and
orders them by their position in it. Read `series_list` for the names.
Archived documents stay out until you pass `includeArchived`. Keep paging
while `hasMore` is true, under a search as much as without one.
15. **A product design or a tech design follows
`references/design-structure.md`.** It opens with "At a glance", and each
open decision gets a pros and cons table. Write the design for a reader who
knows the product and not the code. Keep code names in the parts that this
reader can skip, as its section "Write for a reader who knows the product"
says. Read that file before you write one.
16. **Give the meaning of each outside ID.** An outside ID is a short ID that
the document does not define and does not take from a referenced document.
Examples are a rule ID of a skill, a decision record number, or an ID of a
document that is not in `references`. The reviewer reads the document
without the source open, so a bare outside ID tells them nothing.
1. Put the meaning in a few words at the first mention of the ID in each
section, such as "C2 (offer a design session only on a visual option
set, from `claude-design.md`)".
2. Name the source file or document once in each section, at that first
mention.
3. A colliding ID goes in a code span, with its meaning in prose:
`` `P4` (the Options phase of the session, from `session-flow.md`) ``.
An outside ID collides when it shares its letter prefix with IDs that
the document or a referenced document defines. The review page gives a
bare mention of a defined ID its tooltip. A bare outside `P4` therefore
shows the tooltip of priority P4 when the document defines P4. The
prefix test also protects an ID that a later revision defines. The page
skips a code span.
4. The IDs of a referenced document need no meaning. The review page shows
their tooltip when `references` holds that document and its list entries
lead with a bold ID, such as `**R3: Title.**`. Keep the reference, and keep
the bold lead in the source document.
17. **Create a document as a draft when you can still change it before your
run ends.** A new document goes to the reviewer's inbox at once. A
revision in the same run then changes the version that the reviewer
reads. A draft stays out of review and out of the inbox, and a
`document_revise` keeps it a draft.
1. Pass `draft: true` to `document_create`.
2. Revise the draft as often as you need.
3. Call `document_publish` for each draft of the run, as your last
document step. The document then enters review on its final version.
4. When `document_publish` is not among your tools, the instance does not
have drafts yet, and `document_create` refuses the `draft` argument.
Create the document without `draft`, as before.
A review round on a document that is already in review revises it once,
and needs no draft step. A person in the session with you can read the
document at once, so an interactive session needs no draft either.
## Example
Entry shape, lead sentence first and detail after:
```markdown
1. **Token flush on every request.** Each widget API call writes
`last_used_at` synchronously. `ApiTokenAuthenticator.php:45` runs
`markUsed()` + `flush()` inside the auth path… (detail follows)
```
Not this, which starts mid-jargon, glues fragments together and presents
nothing:
```markdown
1. `ApiTokenAuthenticator.php:45` — markUsed() + flush() on every Bearer
request · hot-row contention · fix: …
```
Decision shape, where the choice is visible and the options referenceable:
```markdown
**Decision needed** — how to stop reset-link host poisoning:
1. Drop `x-forwarded-host` from `trusted_headers` (recommended: smallest
change, removes the attacker input).
2. Generate emailed links from a pinned `default_uri` instead of request
context.
```
Not: "Drop `x-forwarded-host` or generate these links from a pinned
`default_uri`." The reader cannot tell that a decision is expected.
## Common mistakes
- Pasting a report drafted for the terminal into `document_create` unchanged.
Terminal formatting habits (dense bullets, `·`-separated fragments, H1
headers) are exactly what these rules exist to undo.
- Numbering only the top level. Nested lists that reviewers will discuss also
get numbers.
- Cross-referencing by list number across headings. The rendered numbering is
per-section, so the reference lands on the wrong entry or none at all. Use
stable IDs (rule 3).
- Holding comment ids across a `document_revise` call. They do not survive it
(rule 7); re-read the review, or reply before revising.
- Paging the whole document list to find one document. Pass `search`, or a
`status`, `tag` or `series` filter, and read each row's version description
(rule 14).
- Quoting your own Markdown to `document_highlight`. It matches the rendered
prose, so inline markup in the quote finds nothing (rule 11).
- Answering a one-line comment with a structured essay: bold lead-ins,
sub-points, the whole argument that produced the answer. Give the answer
(rule 8); if it does not fit in a short paragraph, it belongs in the document.
- Writing a table and then the same content again in prose. The table replaces
the text it covers (rule 15).
- Writing a decision in the terms of the code: class names, fields, and
"(checked, File.php)" on each sentence. The owner decides with no file open.
Write the question and the options in product terms. A tech design puts the
code in the How list (rule 15).
- Citing a rule ID of a skill, such as C2, with no meaning and no source. The
reviewer does not have the skill open (rule 16).