# Run402 — your first deploy
Run402 is a full-stack platform a coding agent provisions, deploys, and pays for on its own: Postgres, REST, auth, storage, functions, and static hosting behind one CLI. **Use the CLI by default.** This tutorial deploys one manifest and its referenced HTML file with one command. Use a new application directory; `--name` requests creation and `-y` approves the required setup.
## 1. Install
```bash
npm install -g run402@latest
```
## 2. Write `run402.json`
The manifest is the whole app: a migration, which tables the browser may reach, and the site. Wire fields are `snake_case`.
```json
{
"$schema": "https://run402.com/schemas/release-spec.v1.json",
"database": {
"migrations": [
{ "id": "001_init", "sql": "CREATE TABLE IF NOT EXISTS items (id serial PRIMARY KEY, title text NOT NULL);" }
],
"expose": {
"version": "1",
"tables": [{ "name": "items", "expose": true, "policy": "public_read_append_only" }]
}
},
"site": {
"replace": {
"index.html": { "path": "index.html", "content_type": "text/html" }
}
}
}
```
This demo allows public reads and new submissions. Visitors cannot edit or delete existing items. Use an authenticated policy for private or user-owned data.
Create `index.html` alongside the manifest. It reads its own keys from the host it is served on — never paste a key into HTML:
```html
```
`window.RUN402` is `{ project_id, api_base, anon_key }` for whatever project the page was loaded from — a branch copy or a transferred project stays correct without touching the HTML. The anon key is public by design; the service key is never served there.
A copy-and-deploy version of exactly this pattern (manifest, seeded `notes` table, page reading `window.RUN402`) lives in [`examples/static-config-js/`](https://github.com/kychee-com/run402/tree/main/examples/static-config-js).
## 3. Deploy
```bash
run402 up --name my-app -y
```
`up` validates the files and explicit destination, then performs missing setup and deploys. A fresh Cloud profile uses the free prototype tier on testnet; an existing profile retains its configured authority and payment settings. The SDK coordinates the release; database migration effects are not automatically undone by promoting an older release.
The result is JSON. The following is a shortened example, not the complete response. Hand your human the two links it carries:
```json
{
"result": {
"project_id": "prj_…",
"identity": {
"principal": { "id": "principal_example", "type": "agent", "display_name": "claude-code" },
"client": { "detected": "claude-code", "declared_name": null },
"display_name": "claude-code", "source": "detected"
},
"deploy": {
"status": "ready",
"urls": { "site": "https://my-app.run402.com", "console": "https://console.run402.com/orgs/…/projects/prj_…" },
"next_actions": [{ "type": "hand_to_member", "credited_as": "claude-code", "why": "Show your human the site and the console link…" }]
}
}
}
```
A ready release is not proof that every application behavior works. Open the returned site, confirm the item appears, and check failures before reporting success. Use the [deploy and verification reference](https://docs.run402.com/llms-cli-deploy.txt) for automated checks. For later authorized changes, run `run402 up` in the linked app directory.
Then hand your human the two links. A `hand_to_member` entry is Run402 asking whether it may promote what they built: ask yes or no, and on yes send `run402 feedback send "promote: yes" --project --handle --return-address `, leaving out what they did not give. Without a handle or a return address Run402 can neither tag nor reach them. A `register_contact` entry means Run402 has no email for your human at all: `run402 agent contact --name --email `.
## If you were given a promo code
```bash
run402 redeem
```
## Where to go next
- CLI reference:
- SDK for typed scripting:
- MCP reference:
- Skill:
- HTTP API: