How it works
The lifecycle of a rect, from authoring to reading the result back.
A rect's life has five stages. This page walks the whole loop once, conceptually — every stage links to the guide that covers it in depth.
1. Author a view
A view is a built bundle — an index.html plus its assets (or one
self-contained file). Two paths produce one:
- React + the SDK — author with the
@rectsh/rect/reacthooks, compile with the@rectsh/rect/viteplugin.npm create rectscaffolds all of it. - Hand-written HTML — any HTML that embeds the spec block and loads the
Rect.jsruntime. Good for simple views.
Either way the view is self-describing: an inert
application/rect-view+json block declares its name, when to use it, an
example view model, optional agent instructions and stateSchema, and a
catalog of named actions. SDK projects keep the operating
instructions in rect.agent.md; the build publishes that Markdown into the
spec. stateSchema describes the view model for discovery and tooling; it is
not runtime validation for issue or patch writes. The view runs in a sandboxed
iframe and only ever touches its view model — the view
contract spells out the constraints.
2. Publish it as a template
rect publish builds the project, uploads the bundle, and
registers it as a template (also just called a rect) — keyed by a slug,
so republishing updates the same template in place. At upload the host
extracts the spec and actions blocks and validates them; a view whose actions
don't match its spec fails the publish, not a dispatch three days later.
A template is inert. It holds the view and its declared shape — nothing else.
3. Issue a live instance
Issuing creates a live instance of a template: a fresh view model
(initialized from the caller's state, or the spec's example), its own
revision counter, and a set of URLs:
viewUrl— the human-facing capability URL (/r/<id>). Whoever has it can open the view; the opaque id is the access. No login, no invite.checkUrl,stateUrl,dispatchUrl— the same capability, for programs.
An agent normally searches for the best-fitting template, reads its full spec, then issues it. Keyword-based search matches template names and slugs, plus words in descriptions, actions, and state fields. The same public and workspace visibility rules apply to every result. Deterministic catalog listing remains available for browsing or as a fallback when search is unavailable or unhelpful.
Agents issue over MCP (rect_issue), the CLI
(rect issue), or the HTTP API. One template can back
thousands of independent instances.
4. Collaborate in real time
This is the stage everything else exists for. The instance's view model is a single JSON document with one write op — an RFC 7386 JSON Merge Patch — and every write, from anyone, follows the same cycle:
- A writer sends a change: the human's edit relayed by the host shell, an
agent's
rect_dispatchorrect_patch, a CLI call. - The host applies it to the authoritative store and bumps the revision.
- The host broadcasts a fresh snapshot to every connected client — the
human's browser re-renders, and an agent polling
checkUrlsees the new revision.
No polling inside the view, no stale reads: the human and the agent are always looking at the same state. State & syncing covers the optimistic-write mechanics inside the view.
Two write styles coexist:
- Patches are free-form — right for edits with no rules attached, like typing in a field.
- Actions are semantic — the view declares named
operations (
approve,addTodo) whose handlers run host-side in a sandbox, validate business rules, and can reject with a structured code the caller can react to. Views can even declarepatchPolicy: "actions-only"to turn away free-form agent patches entirely.
Files ride alongside: attachments upload to private
storage and appear as references in the reserved $attachments namespace —
never as bytes in the view model.
5. Read the result back
When the human is done (or at any point before), the agent reads the full view
model and revision back — rect_get_result over MCP, rect read from the
CLI, or a GET on checkUrl. The result is plain JSON in exactly the shape
the view's spec declared, ready to act on.
If the loop needs an explicit "I'm done" signal, model it in the view — a
submitted flag, an approve action — so the agent can read it straight off
the view model instead of guessing.
The security model in one paragraph
Views are untrusted code, so they run in a sandboxed iframe with a
host-owned CSP — no cookies, no storage, no direct network; everything goes
through the host over postMessage. Action handlers are untrusted too, so
they run server-side in a QuickJS sandbox with a CPU deadline and memory
cap, pinned clocks and randomness, and JSON-only inputs and outputs. Instances
are capability-addressed: the opaque instance id is the credential, which
is what makes "just send the human a link" possible. Publishing and template
management, by contrast, always require an authenticated account.