rect.sh

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.

1Authora view — React SDKor plain HTML2Publishrect publish →a reusable template3Issuea live instancewith its own URL4Collaboratehuman edits ↔ agentdrives, in real time5Read backthe final stateas plain JSON

1. Author a view

A view is a built UI bundle — an index.html plus its assets (or one self-contained UI file). The host supplies the shared Rect protocol runtime. Two paths produce the bundle:

  • React + the SDK — author with the @rectsh/rect/react hooks, compile with the @rectsh/rect/vite plugin. npm create rect scaffolds all of it.
  • Hand-written HTML — any HTML that embeds the spec block and uses the host-provided Rect global. 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, required stateSchema, optional agent instructions, and a catalog of named actions. SDK projects keep the operating instructions in rect.agent.md; the build publishes that Markdown into the spec. The build and publish gate validate the schema and example, and App publication validates every Screen's initial ViewModel against it. The schema does not validate later 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:

  • url — the human-facing URL (/r/<id>). Whether it opens anonymously or requires sign-in depends on the instance's read access.
  • checkUrl, stateUrl, dispatchUrl — addressed endpoints for programs. They enforce the same independent read and write access as the hosted page.

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 accepted write, regardless of surface, follows the same cycle:

  1. A writer sends a change: the human's edit relayed by the host shell, an agent's rect_dispatch or rect_patch, a CLI call.
  2. The host applies it to the authoritative store and bumps the revision.
  3. The host broadcasts the committed delta to every connected client — the human's browser applies it, and an agent polling checkUrl receives the latest full snapshot.

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.

Each instance chooses read and write access independently:

ScopeWho is allowed
anonymousAnyone with the instance ID
authenticatedAny signed-in user
workspaceMembers of the instance's workspace
ownerThe creator, workspace primary owner, or owner role

The hosted page, Realtime delta channel, HTTP API, MCP, CLI, and Rect Agent all apply those scopes. A caller who must sign in receives 401; a signed-in caller outside the permitted workspace or owner set receives 403.

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 declare patchPolicy: "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. Every instance has independent anonymous, authenticated, workspace, or owner read and write scopes. Publishing and account-scoped template management require authentication; public template discovery does not.

On this page