# Refert — Agent Guide

Give this file to any AI coding agent (Claude Code, Cursor, Windsurf, etc.). The agent does the setup and the deployments; a non-technical person only approves. All commands in this guide are for the agent to run — the user never needs to touch a terminal.

Refert is a cloud for small software: tools with a handful of users, built by an agent and shared with colleagues like a Google Doc. A tool goes from prompt → live URL in one publish command. Access is per-person ("Use" or "Edit"), and everything an agent publishes is visible to the org in a catalog with a kill switch.

---

## 1. Install the CLI

    npm install -g @refert/cli

Verify the install (v0.3.0+ has all commands in this guide):

    refert --help
    refert --version

Windows is fully supported. When spawning the CLI from scripts or other processes, call `refert.cmd` or wrap the command with `cmd /c refert ...` — the npm shim is a batch file, not an .exe, so direct process spawns (e.g. PowerShell's `Start-Process refert`) fail to resolve it.

## 2. Sign in once — browser authorization

    refert login

The command opens the user's browser to the platform's device-authorization page (the address this guide was served from). The user signs in with Google and allows the device; the platform issues a scoped publish key directly to the CLI, which stores it on this machine. The key is never displayed.

Rules for agents:
- Never ask the user for an API key. Never paste a key into a prompt, an MCP config, a `.env`, or a code file.
- If a command returns 401, run `refert login` again — do not work around it.
- If the user asks "where's the key?": it is stored by the CLI on this machine and revocable on the platform's Settings page.
- `refert logout` removes the stored credential; `refert whoami` verifies it.

For CI, keys are also available on Settings and can be passed with `--key` / the `REFERT_KEY` env var; `--url` / `REFERT_URL` override the platform address. The MCP server reads the CLI login automatically.

## 3. Install the MCP extension

The MCP server ships on npm as `@refert/mcp` (bin `refert-mcp`). It reuses the CLI login from step 2 — no key handling at all. Register it (the client's MCP settings, not a chat or a tool, holds the command):

    # Claude Code (macOS/Linux)
    claude mcp add refert -- npx -y @refert/mcp

    # Claude Code on native Windows — npx needs the cmd /c wrapper
    claude mcp add refert -- cmd /c npx -y @refert/mcp

    # Cursor / other MCP clients: same command via the client's MCP settings.

Credentials resolve per request from `REFERT_KEY` / `REFERT_URL` if set, otherwise from the CLI login on this machine (`~/.refert/config.json`) — so `refert login` is the only setup step. Plain `http://` is allowed only for localhost URLs; any other host must use `https://`.

What the agent gains:

| MCP tool | What it does |
|---|---|
| `refert_whoami` | Confirms which user, org, and key the server acts as — call it first |
| `refert_publish` | Publishes a tool folder → returns the live URL and version |
| `refert_list_tools` | Lists the org's tools (slug, name, status, version, last active) |
| `refert_logs` | Reads a tool's activity log so the agent can self-debug |
| `refert_rollback` | Reverts a tool to a previous version |
| `refert_preview` | Mints a 15-minute curl-able URL that renders a tool without a session |

If MCP is not available, the CLI alone is sufficient — every MCP tool has a CLI equivalent.

## 4. The tool contract

A tool is a plain folder. Keep it self-contained — no build step, no bundler.

    my-tool/
      tool.json     # required manifest
      index.html    # required UI (may reference declared sibling files)
      style.css     # optional, declare it in files and it is served in production
      main.js       # optional server functions (server-side only, never served to the page)

`tool.json`:

    {
      "name": "Renewal Pricing Calculator",
      "slug": "pricing-calc",
      "description": "Compute renewal pricing for a deal",
      "files": {
        "index.html": "index.html",
        "main.js": "main.js"
      }
    }

**Rules:**
- `slug`: lowercase letters, digits, hyphens. The run URL is `/run/{slug}` — session-gated for org members only. Any published version previews at `/run/{slug}?v=N` (server functions run that same version there).
- `index.html` must work standalone (openable as a file). Use the platform bridge when present, degrade gracefully when not:
  - `SC.whoami()` — the current viewer
  - `SC.getData(key)` / `SC.setData(key, value)` — per-tool persistent storage (256 KB max per value)
  - `SC.call(fn, input)` — invoke a `main.js` server function
- Bridge semantics: every `window.SC` method is **async** and always returns a Promise. `SC.whoami()` → `{ ok, user, org }`; `SC.getData(key)` → `{ ok, value }` (value is null for unset keys); `SC.setData(key, value)` → `{ ok }` (values over 256 KB fail); `SC.call(fn, input)` → `{ ok, result }` or `{ ok: false, error }`. Await each call exactly once — never `.then()`-chain a second one. Inside `main.js`, the `sc` second argument is also async but returns raw values: `sc.getData(key)` → the value, `sc.setData(key, value)` → throws on failure, `sc.whoami()` → `{ tool }`.
- Multi-file tools: every file declared in `files` is served in production at the same relative path it has locally — `index.html` can reference `style.css` or `app.js` exactly as it does when opened as a file. `refert serve` reproduces this, so if it works locally it works deployed.
- Client error reporting: failed asset loads, uncaught exceptions, and unhandled rejections on the run page are reported to the activity log automatically (`refert logs <slug>`, Activity tab).
- `main.js` (optional) exports plain async functions: `exports.renewalPrice = (input) => {...}`. Runtime limits: 3s load, 10s per call, 256 KB values. No `require`, `process`, `fetch`, timers, or environment access — denied by construction.
- No external API keys, no CDNs beyond fonts, no tracking. A tool that wouldn't be safe to run inside the user's company is not an Refert tool.

**Platform features — never rebuild these.** A tool is just its page and its server functions. Everything else around it ships with the platform, so when a prompt asks for these, the answer is configuration or the bridge — never new code inside the tool:

| If the user asks for… | The platform already provides | What the agent does |
|---|---|---|
| "Login, accounts, only my team can open it" | Google sign-in, org membership by email domain, session-gated run URLs | Nothing in tool code — access is a sharing concern |
| "Share it with so-and-so / read-only access" | Per-person Use/Edit access: tool page → Sharing tab | Tell the user how to share; no user tables, no password screens |
| "Who is viewing this" | `SC.whoami()` returns the signed-in viewer on the run page | Display it; don't build accounts |
| "Remember this / save state" | `SC.getData` / `SC.setData` per-tool storage | Use the bridge; no database, no backend |
| "Keep the logic off the page" | `main.js` server functions via `SC.call` | Put the logic in main.js |
| "Version history / undo" | Every publish is an immutable version; `refert diff`, `refert rollback`, `/run/{slug}?v=N` previews | Iterate by publishing; never build versioning into the tool |
| "Turn it off in an emergency" | Kill switch: Catalog → Control → Disable | Surface the control; don't add one to the page |
| "Who changed what" | Per-tool audit log (Activity tab, `refert logs`) | Read it; don't build logging |
| "Back up my data" | `refert export <slug>`; Control → Export data | Tell the user; no external sync in tool code |
| "Scheduled jobs / background tasks / webhooks" | Not part of a tool: 10s call limit, no timers, no network | Say so plainly; it is outside what a tool is |

If a prompt mentions auth, teams, permissions, or history, the correct response is sharing and versioning configuration — not tool code.

## 5. Create a deployment skill

After setup, create a reusable skill so future sessions deploy without re-reading this guide. Create `refert-deploy/SKILL.md` with the template below (adjust to your agent's skill conventions — Claude Code: drop it in `.claude/skills/` or the user's skills directory):

```
---
name: refert-deploy
description: Build and publish internal tools to Refert. Use when the user wants a small internal tool — calculator, form, tracker, dashboard, status page — deployed where their team can use it. Covers setup (CLI + MCP), scaffolding, publishing, verification, and iteration.
---

# Refert Deploy

## When to use
- The user wants an internal tool for a small team (roughly 2–20 users).
- Prompts like "make a tool for X", "put this on refert", "ship this to the team".

## When NOT to use
- Public-facing products, custom domains, user accounts, high traffic → normal hosting, not Refert.
- Background jobs, queues, heavy compute (limits: 3s load / 10s call / 256 KB values).

## Platform features — never rebuild them in tool code
- Accounts, sign-in, orgs, per-person sharing (Use/Edit), session-gated run URLs — access is sharing configuration, never tool code. No login screens, no user tables.
- `SC.whoami()` = the signed-in viewer; `SC.getData`/`SC.setData` = per-tool storage; `SC.call` = server functions. All async.
- Versioning, rollback, diff, preview URLs, audit log, kill switch, data export — all built in.
- If a prompt asks for auth, teams, permissions, or history: map it to sharing and versioning instead of building it.

## Tool contract (complete — no other reference needed)
A tool is a plain folder: `tool.json` plus the files it declares. `index.html` is the UI; an optional `main.js` holds server functions.

    {
      "name": "Team Kanban Board",
      "slug": "team-kanban",
      "description": "One line, shown in the catalog",
      "files": {
        "index.html": "index.html",
        "style.css": "style.css",
        "main.js": "main.js"
      }
    }

- `files` maps the name the platform serves → the file on disk. Every declared file is served in production, so relative references in `index.html` (`<link href="style.css">`, `<script src="app.js">`) work exactly as they do locally. `main.js` is the exception: server-side only, never served to the page.
- `index.html` must work standalone (openable as a file) and use the bridge when present.
- `window.SC` — every method is async; await each exactly once:
  - `SC.whoami()` → `{ ok, user, org }`
  - `SC.getData(key)` → `{ ok, value }` (`value` is null for unset keys)
  - `SC.setData(key, value)` → `{ ok }` (values over 256 KB fail)
  - `SC.call(fn, input)` → `{ ok, result }` or `{ ok: false, error }`
- `main.js`: `exports.fnName = (input, sc) => {...}` — the second argument `sc` is also async but returns raw values: `sc.getData(key)` → the value; `sc.setData(key, value)` → throws on failure; `sc.whoami()` → `{ tool }`.
- Runtime limits: 3s module load, 10s per call, 256 KB for input, result, and stored values. No `require`, `process`, `fetch`, timers, or network — the sandbox denies them and `refert lint` flags them before publish.
- Client-side failures (failed asset loads, uncaught exceptions, unhandled rejections) are reported to the activity log automatically — check `refert logs <slug>` when a user says a page is broken.

## Setup (once per machine)
1. `npm install -g @refert/cli`
2. `refert login` — opens the browser; never handle the key yourself.
3. Register the MCP server if the client supports it (guide §3).
If any step fails with 401 → `refert login` again.

## Build
Scaffold with `refert init [name]` (adds `--server` for a `main.js` scaffold), or write `tool.json` + `index.html` (+ optional `main.js`) by hand. Follow the tool contract in the Refert agent guide. Use the SC bridge for persistence and server calls; make the page work standalone too.
Develop locally with `refert serve` — serves the folder at http://localhost:3333 with the SC bridge emulated (same 3s / 10s / 256 KB limits, storage under `~/.refert/serve-data/`) and hot reload on every save.
Before publishing, run `refert lint` — it catches main.js syntax errors, runtime-denied APIs (require, process, fetch, timers), index.html references to undeclared files, and common bridge mistakes.

## Publish
`refert publish ./my-tool` (or MCP `refert_publish`). Lint runs automatically; errors block the publish (`--skip-lint` to bypass).
The command returns the live URL and the version number, e.g. `✓ live v3 → https://…/run/kanban`. Publishing the same slug again adds a new version.

## Verify
1. `refert whoami` (or MCP `refert_whoami`) — confirm the login first.
2. `refert list` (or MCP `refert_list_tools`) — confirm the tool exists and which version is live.
3. `refert test <slug> --fn <name> [--input <json|@file>]` — invoke each server function against the real runtime limits (3s load / 10s call / 256 KB) before users hit them. Omit `--fn` inside the tool folder to list the exported functions.
4. `refert test <slug> --ui` (or MCP `refert_preview`) — smoke-test the rendered page: mints a 15-minute preview URL that works without a browser session, fetches the HTML, and parses every inline script for syntax errors.
5. `refert logs <slug>` (or MCP `refert_logs`) — check for errors.
6. The run URL is session-gated for humans: the user's browser opens it signed in. The preview URL is the agent's own way in.

## Iterate
- Publish new versions after changes; version history is kept and append-only.
- `refert diff <slug> [--from <n>] [--to <n>]` compares two published versions and prints preview URLs (`/run/{slug}?v=N`) to inspect them in the browser.
- `refert rollback <slug> [--to <n>]` reverts to a previous version; on failures, read `refert logs <slug>` before changing code.
- Export the tool's stored data with `refert export <slug>` (see §8).
- If a tool is harmful or wrong, tell the user about the kill switch: Catalog → Control → Disable.

## Report to the user in plain language
- What the tool does, its URL, who can open it, and how to share it (tool page → Sharing tab → add colleagues with Use/Edit).
- Never dump logs or keys on a non-technical user. Sharing stays in the user's hands — do not share on their behalf.
```

## 6. Best-use guidelines

**Right fit** — internal tools with a handful of users: calculators and pricing helpers, request/intake forms, team trackers, workflow dashboards, status pages, report viewers, small automation UIs.

**Wrong fit** — anything public-facing, anything needing custom domains or real user accounts, high-traffic apps, background processing, or files larger than 256 KB per value.

**Quality bar before publishing:**
- Works standalone (plain `index.html` opens in a browser without the platform).
- Uses `SC` bridge when present, falls back gracefully.
- Descriptive `name`, human-`slug`, one-line `description`.
- No secrets, no external network calls, no unbounded loops (the runtime will kill them).

**Process:** develop with `refert serve` → publish → verify (`refert test <slug> --fn <name>`, `refert list`, `refert logs <slug>`) → hand the user the URL and the sharing steps → iterate via new versions. `refert diff <slug>` and the preview URLs (`/run/{slug}?v=N`) inspect old versions before `refert rollback <slug>` reverts. Version history is the undo.

**Etiquette:** slugs are shared namespace per org — prefix ambiguous names. Don't republish over someone else's tool to "fix" it; fork it. The kill switch is the user's control, not the agent's — surface it, don't use it silently.

## 7. Data and backups

A tool's stored data — everything written through `SC.setData` — is exportable at any time:

- Dashboard: Catalog → Control → Export data (downloads `<slug>-data.json`).
- CLI: `refert export <slug>` writes the same JSON to the current folder.

The export is plain JSON — `{ "tool": …, "exportedAt": …, "data": { key: value } }`. Tool source files stay in your repository, so an export plus the source fully recreates a tool anywhere else. Data lives in the platform's Postgres until the tool is deleted; there is no automatic off-site backup yet — agents should export any tool whose data matters before finishing a session.

## 8. About the service

Refert is a hosted platform: dashboard, tool runtime, storage, and sharing run on Refert's infrastructure. There is no repository to clone and nothing to self-host — the agent works entirely through the CLI (and MCP) against the platform URL that served this guide.

- **Now (CLI v0.3.1):** `refert init`, `refert serve` (local SC bridge + hot reload, client errors print locally), `refert login` (browser device authorization — no visible keys), `refert whoami`, `refert publish` (lint preflight + version in output), `refert list` (with live versions), `refert logs <slug>` (includes client-side error reports), `refert test <slug> --fn <name> | --ui` (real runtime limits / page smoke test), `refert lint [dir]`, `refert diff <slug>`, `refert rollback <slug>`, `refert export <slug>`, `refert preview <slug>`, `refert logout` — plus the MCP server on npm (`@refert/mcp`, run via `npx -y @refert/mcp`) with six tools: whoami, publish, list, logs, rollback, preview.
