name: paper-review description: Set up and run the botference document-review interface (Google-Docs-style comments on rendered LaTeX/Markdown, bots replying in threads, apply/commit of accepted changes) in any repo — and follow the round protocol when the user asks for a review round or tags you from the review page.
paper-review — GDocs-style review of rendered sources, with bots
The engine is built and battle-tested. Canonical engine:
$BOTFERENCE_HOME/frontends/review/ (ships with botference). Architecture, decision history, and the unbuilt roadmap (CI
rounds, cloud version): design.md next to this file. This file tells
you how to USE the system.
Setting up a new project ("set up paper review in <dir>")
Preferred: botference review [dir] — one command does all of the
below (engine copy, detection via scripts/review-detect.mjs with an
echoed summary, gitignore, build, serve; --share, --hosted,
--port N, --no-agents, --upgrade). Use the manual steps only when
the launcher isn't available:
- Copy the engine from the reference implementation into
<dir>/review/:build.mjs,server.mjs,chat.mjs,apply.mjs,submit.mjs,init-config.mjs,bridge-system-prompt.md,SCHEMA.md,assets/(review.js, style.css). Never copyreview.config.json,state/,suggestions.json, orsite/— those are per-project. - Run
node review/init-config.mjsfrom<dir>(it inspects the directory: master file via\documentclass, sections via\input/\includeorder, bib, abbreviations, todo macros, figures dir, a free port, and the bridge block). Show the user what was detected and get their confirmation before proceeding — never guess the master file silently. - Add the gitignore block (see reference repo):
review/site/andreview/state/*ignored EXCEPTstate/users/andstate/threads.json;suggestions.jsontracked. Conversation must travel through the repo; runtime files must not. node review/build.mjs, then commitreview/("Add review interface"). Requirespandocon PATH — check and tell the user if missing.
Running it
Sync note: the workspace copies of this skill at
<vault>/botference/.claude/skills/paper-review/SKILL.mdand<vault>/botference/.agents/skills/paper-review/SKILL.mdare plain copies of this file — when you edit it (either copy in botference-main or those), update all four.
botference review— build + serve; agents are on by default when the machine can run them (python3 + aclaude/codexCLI on PATH — the launcher printsagents: on (…)or anagents: offexplanation).--no-agentsforces off;--agentsforces on (clear error if impossible).botference review --share— hosted mode behind a cloudflared quick tunnel: respectsREVIEW_PASSWORDor generates one, printsshare this: <url> password: <pw>; Ctrl-C stops server + tunnel together. Missing cloudflared → install hint, keeps serving locally.- Manual (no launcher):
node review/server.mjs— static + comment mirror, no bots;--chatadds the bot bridge (needsBOTFERENCE_HOMEor the config'sbridge.core_dir);--hostedadds theREVIEW_PASSWORDgate, rate limits, and owner-gated summons. The gate asks for a name and the password together (a name is not a credential — it only picks whichusers/<handle>.jsonthe guest writes; asking on the gate is what makes hosted mode work on a phone, where the sidebar picker is inside a drawer). The server serves ONLYreview/site/+ the figures dir (path-traversal guarded) — keep it that way. - Collaborator options: the owner's
--shareURL (read + comment; their agent summons queue for the owner to release), or clone the repo and run the identicalbotference review(agents auto-detected; without the CLIs they still read and comment), or plainnode review/server.mjs— thennode review/submit.mjs [--push](commits only their ownstate/users/<handle>.json). - The server is long-lived and owned by the human; don't leave your own test servers running.
The interface contract (don't regress these)
- Comments are the only surface for discussing the document.
There is no chat-about-the-paper panel and there will not be one: it
was tried, it was confusing, it is rejected. Anything about the
text is an anchored margin thread. The one exception, added
deliberately, is the task console — a bottom-docked, collapsible,
owner-only, desktop-only bar for document-level instructions that
have no anchor text: "apply all", "commit", "restructure section 3",
"verify every citation resolves". Same strict routing (no
@claude/@codex/@all, no agent). The Changes widget lives inside it, because committing is itself a document-level task. Interrupts (permissions/choices) render on the card, in the console for console-issued turns, or as sidebar toasts when off-page (120s default-deny). - Strict-but-social routing.
@clauderoutes to Claude alone; the free-form footer handoff is disabled on review turns. To involve the other agent, @-tag it in your thread reply — the server converts that into a visible mention turn (depth cap 1 per thread per round).@allengages both. - Mentions fire only on explicit confirm (Done/Enter), never while composing.
- Every author is visually distinct (stable accent color; Claude
coral, Codex blue, humans hashed hues); resolved comments live in a
reopenable resolved tab — and ANYONE may resolve/reopen ANY thread, attributed as "resolved by <handle>" (server-mediated; ownership boundary intact); humans can edit/delete their own entries
(
edited: true— treat an edited entry newer than your ack as new input); author filter chips; light/dark/system theme toggle. - Changes widget (inside the task console, owner-only) is the
commit workflow: accept → ⚡ Apply (gathers every participant's accepts; the owner's explicit decision wins conflicts) → read → ✓ Commit (or ↩ Revert).
Apply is deterministic AND author-agnostic (
apply.mjs: unique-span replacement over bot cards and human suggestions, atomic bib append, JSON-aware edits for config-key targets,needs_manual_resolutionon drift — never guessed). Apply and commit are always separate actions. Out-of-band source edits surface in the widget with a commit action. - Everything is commentable. Paragraphs, figures, headings, list
items, block quotes, captions, table cells and the masthead title all
carry a
data-cid.blk-Nis a POSITIONAL index over#paper p, #paper figureand every existing comment is anchored to one — so that selector is frozen, and each newly anchorable type has its own namespace (-hd-N,-misc-N). Never widen theblkselector. - Humans suggest too. The composer has Comment and Suggest modes.
A human suggestion is an entry in that human's own
users/<handle>.json(suggestions.jsonstays bot-owned), renders inline as del/ins in that human's colour through the same path as a bot card, and flows through the same accept → Apply → Commit. Its source span is resolved to something UNIQUE at compose time — widened with context if ambiguous, anchored on the enclosing macro for headings, aimed at the configtitlekey when the masthead comes from there — and the UI shows what it locked onto. See SCHEMA.md. - Presence is coarse and private. Humans + agents in the top-right cluster; state computed from real interaction, in server memory only, never written to disk, symmetric for everyone, desktop-only.
- Three tiers, not two.
state/grants.json(owner-written) can let a named handle summon agents within a visible daily cap. Apply, Commit, Revert, model switching and permission answers stay owner-only forever — a grant never confers them. - Never invent a quota number. Neither provider exposes
subscription (Pro/Max, ChatGPT plan) quota to anything scriptable;
the Settings panel says so and points at
/usage. Do not reverse-engineer internal endpoints to fake it. - Calm UI: no
prompt()/alert()/confirm(), no scroll-jumps, layout reflows (nothing overlays content), engine files stay 100% document-agnostic (all specifics inreview.config.json).
File ownership (never write another writer's file)
| File | Writer |
|---|---|
| state/users/<handle>.json | that human's browser (via server) — comments, decisions, thread replies AND that human's suggestions |
| suggestions.json | bots |
| state/threads.json | bots |
| state/ack.json | bots |
| state/apply.json | apply.mjs (round ledger) |
| state/grants.json, state/grant-usage.json | the owner, via the server |
| site/, suggestions.js | build.mjs only |
| presence | nobody — server memory only, never a file |
Round protocol (when summoned — by an @tag or "read my comments")
- Read all
users/*.json, diff against yourack.jsonentry (include entries withedited:truenewer than your ack). Those files now also carry humans' ownuser-suggestionentries — read them as proposals, and do not duplicate one a human already made. A DOCUMENT-LEVEL turn from the task console says so in its envelope: answer in the turn text, do not write a thread entry for it. - Reply to each new comment in
threads.json— length case-by-case, never more than 6–8 sentences, no restating, no preamble. If a text change is warranted, add a suggestion card (current_text/proposed_text,reply_to) — see SCHEMA.md. - Rejected cards get exactly one follow-up (concede or your single best counter-argument).
- Never edit document sources during a round. Source changes go
through the user's Apply/Commit buttons only. Site styling/engine
fixes the user asks for directly may be made in
review/files and committed with a clear message. - Update
ack.jsonlast (crash mid-round → the round re-triggers).
Verification bar for any engine change
node --check all touched JS; rebuild; confirm served assets updated;
never kill the human's running server (verify on a throwaway port);
grep engine files clean of document-specific strings; if a change
touches document sources, compile the document (e.g. latexmk -pdf)
and inspect the output before claiming done.
Long-lived processes (servers, tunnels)
To serve or tunnel anything that must outlive your turn, use
botference service start <name> -- <command…> — or the one-shot
botference review --share --service / botference plan --share --service, which run the whole share (server + tunnel) as a managed
service, print the share this: <url> password: <pw> line, and
return control. Never bare background processes (&, nohup,
setsid by hand): they die with your turn's process-group teardown.
Manage what you started with botference service list|logs|stop.
Next.js App Router Expert
Development
A skill that turns Claude into a Next.js App Router expert.
README Generator
Development
Creates professional and comprehensive README.md files for your projects.
API Documentation Writer
Development
Generates comprehensive API documentation in OpenAPI/Swagger format.