Skip to content
Back to skills

Loupe Documents

ASecurity

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).

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 13, 2026
ai-agentsrustgophpapi

Works with

  • terminal
  • cli
  • api
  • mcp

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned October 7, 2026

npx -y skills add ubermuda/loupe --skill loupe-documents --agent claude-code

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.

Security grade badge for Loupe Documents
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ubermuda-loupe-documents/badge)](https://www.skillsdirectory.com/skills/ubermuda-loupe-documents)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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).

Files in this skill

  • SKILL.md12.4 KB
  • references/decision-fences.md3.9 KB
  • references/highlights.md1.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.