How Sandpaper is designed — the one invariant, the data flow, the modules, and one turn end to end. The exhaustive detail is one link away in the engineering spec.
← §A Overview · §B Product · §C Architecture · §D Rationale →
The HTML file on disk is the document. The server serves it, the selected Claude Code or Codex adapter edits it, direct operations splice it, and the watcher reloads it. Server hashes decide whether a turn really saved bytes; no stdout becomes document content. engg →
Outbound and inbound are separate paths over one local server. A turn writes the file; the watcher pushes the reload. Status rides the same SSE channel as a typed event stream. engg §02 →
Provider registry, adapters, state stores, server, toolbar, and tests form one server-owned global lifecycle with zero runtime dependencies.
| Module | State | Responsibility |
|---|---|---|
| bin/cli.js | verified | Validate the arg, start the server, log the URL. |
| src/server.js | verified | Authenticated API, lifecycle, hashes/snapshots, undo, SSE, watcher and scoped reload. |
| src/path-policy.js | verified | Shared serve, mutation, and doctor repository boundary. |
| provider registry + adapters | verified | Diagnose and dispatch claude -p or controlled codex exec; normalize provider frames and scoped resume IDs. |
| public/sp-client.js + toolbar.* | verified | Authenticated transport, explicit provider selection/default/reset, separate transcripts, truthful status/undo, Sand, Hands, rollback and accessibility. |
| test/ | verified | Node integration and Chromium browser suites with a deterministic fake runner. |
Component map → · authoritative build status → engg §06
data-cid), type a change.fs.watch routes page-scoped reloads, preserving only the initiating tab's confirmed optimistic direct edit.Full 10-step sequence → engg §04
| Event | State | Chip |
|---|---|---|
| system/init | init | Starting… |
| message_start | thinking | Composing the change… |
| tool_use · Edit | editing | Editing <doc> |
| result · success + changed hash | done | Saved · Undo |
| result · success + unchanged hash | done | Replied |
Full event map → engg §03
A local-only tool, scoped tight: bound to 127.0.0.1; per-process token plus same-origin/loopback checks on mutations and SSE; shared path policy denies secrets, runtime state, traversal, and escaping symlinks; request bodies are capped. Provider processes still have directory-level write ability. Codex's controlled flags are not OS isolation, and external-path detection is best-effort only.
Threat model → engg §05 · why local-only → §D rationale