# fuast docs

fuast is a small cloud for team software. An agent writes a little full-stack TypeScript app called a capsule, fuast runs it with a database, sign-in, storage, schedules, and email built in, and you share it with coworkers like a doc.

If you are an agent, treat the capsule directory as the whole app. Write the server contract, write the Preact client, run the fuast CLI, read the runtime state, and deploy without leaving the terminal. The [agent start guide](https://fuast.com/docs/agents.md) is the short version of this site.

An agent without a terminal can do the same through the [MCP server](https://fuast.com/docs/mcp.md) at `https://fuast.com/mcp`: Claude, ChatGPT, Cursor, and VS Code connect to it and deploy from file contents.

## Start here

```sh
bunx @revnu/fuast new my-app --template todo
cd my-app
bunx @revnu/fuast dev
```

`fuast create` is an alias for `fuast new`. To turn the current, empty directory into a capsule, run `fuast init`. Templates: `todo`, `guestbook`, `signature`, `approvals`, `live-demo`. See [examples](https://fuast.com/docs/examples.md). The dashboard's **New app** button deploys the same templates without a terminal.

A capsule has this shape:

```txt
server/index.ts      default export capsule({...}): schema, queries, mutations, actions, endpoints, schedules
client/index.tsx     export function App(): the Preact UI
shared/              pure TypeScript both sides import
.env.fuast.server    optional server-only env (KEY=value lines)
favicon.svg          optional (.ico also works)
fuast.json           {"app": "<slug>"}, written by the first deploy. Commit it.
fuast-env.d.ts       type declarations for fuast/server, fuast/client, fuast/ui
tsconfig.json
AGENTS.md            instructions for coding agents (CLAUDE.md imports it)
```

Import rules:

- `server/` imports `fuast/server` and relative files.
- `client/` imports `fuast/client`, `preact`, `preact/hooks`, `preact/jsx-runtime`, and relative files (and, optionally, the `fuast/ui` component kit).
- `shared/` imports only relative files.
- No npm packages and no Node built-ins anywhere.

## Server contract

```ts
import { boolean, capsule, endpoint, json, mutation, query, string, table, userId } from "fuast/server";

export default capsule({
  name: "Notes",
  schema: {
    notes: table({
      body: string(),
      pinned: boolean().default(false),
      ownerId: userId()
    }).index("by_owner", ["ownerId"])
  },

  queries: {
    notes: query(async (ctx) => {
      const { userId } = ctx.auth.requireIdentity();
      return ctx.db.notes
        .withIndex("by_owner", (q) => q.eq("ownerId", userId))
        .order("desc")
        .collect();
    })
  },

  mutations: {
    addNote: mutation(async (ctx, body: string) => {
      const { userId } = ctx.auth.requireIdentity();
      const clean = body.trim().slice(0, 500);
      if (!clean) throw new Error("Write something first.");
      return ctx.db.notes.insert({ body: clean, ownerId: userId });
    })
  },

  endpoints: {
    health: endpoint({ method: "GET", path: "/api/health" }, () => json({ ok: true }))
  }
});
```

Handlers receive `ctx`:

- `ctx.auth`: who is calling. `requireIdentity()` returns a guest or account, `requireSignedIn()` returns an account, both throw otherwise.
- `ctx.db`: async table access through declared indexes. Read-only in queries, actions, and read-only endpoints.
- `ctx.env`: server-only values from `.env.fuast.server` and the dashboard.
- `ctx.log`: structured logs you read with `fuast logs`.
- `ctx.storage`, `ctx.email`, `ctx.team`, `ctx.workspace`: files, email, workspace-shared tables, and workspace members.
- Global `fetch()` for outbound HTTP.

Details: [capsule API](https://fuast.com/docs/capsule-api.md), [database](https://fuast.com/docs/database.md).

## Client contract

```tsx
import { canAccessApp, createClient, retryAuth, SignInButton, useAuth } from "fuast/client";
import { useState } from "preact/hooks";
import type app from "../server/index";

const client = createClient<typeof app>();

export function App() {
  const auth = useAuth();
  if (auth.isLoading) return null;
  if (!canAccessApp()) {
    return (
      <main className="p-6">
        {auth.error ? <p role="alert">{auth.error}</p> : <p>Sign in to use this app.</p>}
        {auth.error ? <button type="button" onClick={() => void retryAuth()}>Retry</button> : null}
        <SignInButton />
      </main>
    );
  }
  return <Notes />;
}

function Notes() {
  const notes = client.useQuery("notes");
  const addNote = client.useMutation("addNote");
  const [draft, setDraft] = useState("");
  return (
    <main className="p-6">
      <form onSubmit={(e) => { e.preventDefault(); void addNote(draft).then(() => setDraft("")); }}>
        <input value={draft} onInput={(e) => setDraft(e.currentTarget.value)} />
      </form>
      {notes === undefined ? null : notes.length === 0 ? (
        <p>No notes yet. Write one above.</p>
      ) : (
        <ul className="transition-opacity duration-200 starting:opacity-0">
          {notes.map((n) => <li key={n.id}>{n.body}</li>)}
        </ul>
      )}
    </main>
  );
}
```

`client.useQuery` returns `undefined` until the first result, then re-renders whenever a write changes the data it read. Mutations and actions return promises. See [capsule API](https://fuast.com/docs/capsule-api.md#client).

## Auth and env

Every app belongs to a workspace (your company, by verified email domain). Sharing decides who can open it: `private` (you and people you add), `workspace` (your coworkers), or `public` (anyone with the link, including guests). Public apps give visitors a guest session until they sign in, and their `userId()` data follows them to their account. See [auth](https://fuast.com/docs/auth.md) and [teams](https://fuast.com/docs/teams.md).

Server secrets go in `.env.fuast.server`:

```txt
OPENAI_API_KEY=sk-...
WEBHOOK_SECRET=whsec_...
```

Read them only in handlers with `ctx.env.OPENAI_API_KEY`. `fuast dev` loads the file. `fuast deploy` uploads it. Keep it out of git (the starter `.gitignore` does).

## Inspect the runtime

While `fuast dev` runs:

```sh
fuast check
fuast run notes
fuast run addNote '"first note"'
fuast inspect --port 3000
fuast inspect --query notes
fuast db dump --port 3000
fuast logs --port 3000
```

`fuast run` calls a handler headlessly and prints its result. `inspect --query` shows how many rows one query read for what it returned. Locally, handler errors in `fuast logs` carry stacks mapped to your source. See [test and debug](https://fuast.com/docs/testing.md).

For a deployed app, pass its slug (from `fuast.json`) or URL. Without one, these commands target `fuast dev`:

```sh
fuast inspect my-app
fuast run notes my-app
fuast db dump my-app
fuast logs my-app --follow
```

Dev and hosted apps serve the same `/__fuast/*` inspection routes with the same JSON. Use them before guessing. See [reference](https://fuast.com/docs/reference.md#inspection-routes).

## Deploy

```sh
fuast check
fuast deploy
```

`deploy` needs no account. Without a login it puts the app online as a preview for 72 hours and prints a preview link and a claim link. The person the app is for opens the claim link, signs in, and the app is theirs: private, with the data it already holds. See [deploy without an account](https://fuast.com/docs/reference.md#deploy-without-an-account).

```sh
fuast login
fuast deploy
fuast share --visibility workspace
```

`fuast login` opens a browser page where a person signs in and approves the CLI, once per machine. CI sets `FUAST_TOKEN` instead. Logged in, `deploy` goes straight to that account, and after a claim it keeps deploying the claimed app. `deploy` uploads source, type checks it (type errors block the deploy), builds it, and swaps it in with the data intact. Every deploy is an immutable record: `fuast deploy list` shows them and `fuast deploy rollback <id>` returns to one. See [reference](https://fuast.com/docs/reference.md#deploy).

## Current limits

- One server entry (`server/index.ts`) and one client entry (`client/index.tsx`).
- No npm packages, no Node built-ins, no CSS files. Tailwind classes compile automatically.
- Per handler: 1000 rows returned, 5000 rows read, 4 MiB read, 1000 writes, 5 s of CPU, 10 s wall clock.
- Per app: 100000 rows, 64 MiB of rows, 100000 requests and 20000 mutations per UTC day, 100 emails per day.
- Files: 25 MiB each, 1 GiB per workspace.

Every limit, its error, and what to change: [limits](https://fuast.com/docs/limits.md).

## Read next

- [Agent start guide](https://fuast.com/docs/agents.md): the build, verify, deploy loop for coding agents.
- [Capsule API](https://fuast.com/docs/capsule-api.md): server, client, handler capabilities, types.
- [Database](https://fuast.com/docs/database.md): indexes, field types, pagination, schema changes, ingest.
- [Auth](https://fuast.com/docs/auth.md): accounts, guests, sign-in policy, endpoint credentials.
- [Teams](https://fuast.com/docs/teams.md): workspaces, sharing, invites, members, team tables.
- [Custom domains](https://fuast.com/docs/domains.md): serve an app at a domain you own, with DNS verification and HTTPS.
- [Storage](https://fuast.com/docs/storage.md): user uploads and server-side files.
- [Schedules](https://fuast.com/docs/schedules.md): cron jobs.
- [Jobs](https://fuast.com/docs/jobs.md): run a mutation or action later with `ctx.scheduler`, durably and transactionally.
- [Email](https://fuast.com/docs/email.md): transactional email from handlers.
- [Agent tools](https://fuast.com/docs/agent-tools.md): expose handlers to browser agents with WebMCP.
- [MCP server](https://fuast.com/docs/mcp.md): connect Claude, ChatGPT, Cursor, VS Code, or Claude Code and build without a terminal.
- [Test and debug](https://fuast.com/docs/testing.md): `fuast check`, `fuast run`, `inspect --query`, logs, `run-many`.
- [Security](https://fuast.com/docs/security.md): what fuast guarantees and what your capsule must check.
- [Limits](https://fuast.com/docs/limits.md): every limit and error.
- [Reference](https://fuast.com/docs/reference.md): CLI, inspection routes, HTTP API, env vars.
- [Examples](https://fuast.com/docs/examples.md): complete starter apps.
- [Migration to v2](https://fuast.com/docs/migration-v2.md): upgrade a capsule written for the old fuast API.
- [Support](https://fuast.com/docs/support.md): platforms, compatibility, persistence.
- [Isolation](https://fuast.com/docs/isolation.md): how fuast keeps apps apart.
- [llms.txt](https://fuast.com/llms.txt): an index of every page for agents. [/agents.md](https://fuast.com/agents.md) is the agent start guide, and [/docs.json](https://fuast.com/docs.json) the index as JSON.
