# Yaprak agent setup

Yaprak keeps what you make at a permanent URL. Publish a file, a folder or a built static site
and give the user the link. Every publish is an immutable version; the live one can be rolled
back. Sites are public by default and can be put behind a password or made private.

Use the file or folder the user asked to publish. Ask only if the target is unclear.

## Which lane to use

- **One file or a small folder, no install:** the HTTP lane below. No account needed.
- **A project folder, repeat work:** the CLI, `npx -y https://yaprak.app/cli/yaprak.tgz publish <dir>`.
- **An MCP client:** local `npx -y https://yaprak.app/cli/yaprak.tgz mcp` (stdio), or hosted
  `https://api.yaprak.app/mcp` (Streamable HTTP).
- **A project that needs a build** (Vite, Astro, Next.js with `output: "export"`, Nuxt
  `generate`, SvelteKit static, Docusaurus, VitePress…): with an account, `publish` on the
  project folder builds it in an isolated cloud container and publishes the output. Without an
  account, build locally and publish the output folder.
- **A server application:** not supported. Build it to static files and publish the output.

## Before you publish: reuse the existing space

Look for `.yaprak/space.json`, walking up from the folder you publish. If it exists, publish to
that `space_id` instead of creating a new space. The CLI does this by itself. If an earlier
publish in this conversation returned a space, update that one.

Treat claim tokens, session tokens and API keys (`yc_…`, `ys_…`, `yk_…`) as secrets: do not
print them in shared logs or commit them. Never publish `.env` files, `.git`, private keys or
dependency folders; the API refuses `.env` and `.git` paths.

## HTTP lane (no account)

One file:

```bash
curl -sS -H "X-Yaprak-Client: agent/<your-agent>" -F "files=@index.html" https://api.yaprak.app/v1/publish
```

Several files keep their paths through the part's filename:

```bash
curl -sS -F "files=@index.html" -F "files=@css/site.css;filename=css/site.css" https://api.yaprak.app/v1/publish
```

A folder as one zip (paths relative to the site root; one shared top folder is removed):

```bash
(cd dist && zip -qr ../site.zip .) && curl -sS -F "archive=@site.zip" https://api.yaprak.app/v1/publish
```

The answer has `url` (live now) and, for anonymous publishes, `claim.url` and `claim.token`.
Give the user `url` and `claim.url`: the site stays up 33 hours 20 minutes after its latest
publish unless the user claims it. To publish a new version of the same anonymous space, send
its id and claim token:

```bash
curl -sS -H "X-Yaprak-Claim-Token: $CLAIM" -F "space_id=$SPACE" -F "files=@index.html" https://api.yaprak.app/v1/publish
```

Anonymous limits: 1,000 files, 50 MB per file, 100 MB per version, 20 publishes per hour.

## CLI

```bash
npx -y https://yaprak.app/cli/yaprak.tgz publish ./dist     # prints the URL
npx -y https://yaprak.app/cli/yaprak.tgz login              # email code; then publishes go to the account
npx -y https://yaprak.app/cli/yaprak.tgz versions
npx -y https://yaprak.app/cli/yaprak.tgz rollback 3
npx -y https://yaprak.app/cli/yaprak.tgz access private && npx -y https://yaprak.app/cli/yaprak.tgz share "client review"
```

With an account only changed files upload. A folder with a `build` script in `package.json`
and no `index.html` builds in the cloud (Node.js 24; npm, pnpm, yarn or bun from the lockfile;
15 minutes at most); force it with `--build`, skip it with `--no-build`, and override with
`--command "<cmd>"` and `--output <dir>`. The API lane is `POST /v1/spaces/{space_id}/builds`
with a gzipped tar of the project. In CI set `YAPRAK_TOKEN` to an API key from
https://yaprak.app/account. Signing in and publishing a folder that was published anonymously
claims it into the account.

## MCP

Local (stdio), for Claude Code:

```bash
claude mcp add yaprak -- npx -y https://yaprak.app/cli/yaprak.tgz mcp
```

Any client with a `mcpServers` map:

```json
{ "mcpServers": { "yaprak": { "command": "npx", "args": ["-y", "https://yaprak.app/cli/yaprak.tgz", "mcp"] } } }
```

Hosted (Streamable HTTP, no filesystem: `publish_files` takes inline content):

```bash
claude mcp add --transport http yaprak https://api.yaprak.app/mcp --header "Authorization: Bearer yk_..."
```

The header is optional; without it publishes are anonymous. Tools: `publish` (local only, a path),
`publish_files`, `list_spaces`, `list_versions`, `rollback`, `set_access`, `create_share_link`,
`preview`, `add_domain`, `check_domain`.

## API

Reference: https://api.yaprak.app/docs (OpenAPI at https://api.yaprak.app/openapi.yaml).

Change-only publishing for large sites:

1. `POST /v1/spaces` creates a space (or reuse one).
2. `POST /v1/spaces/{space_id}/versions` with `{"files":[{"path":"/index.html","sha256":"…","size":123}]}`
   answers with `uploads`: presigned `PUT`s for the content not stored yet. Send each body with
   the given headers; storage checks the SHA-256.
3. `POST /v1/spaces/{space_id}/versions/{version_id}/finalize` makes it live.

## Site behaviour

- `/about` serves `/about/index.html` (redirecting to `/about/`) or `/about.html`.
- `/404.html` is the not-found page.
- `_redirects` and `_headers` in the site root work like Netlify's: `/old /new 301`,
  `/blog/* /posts/:splat 302`, `/* /index.html 200` for single-page apps.
- Each version also lives at `https://v<number>--<slug>.yaprak.app`.
- Custom domains: `POST /v1/spaces/{space_id}/domains` with `{"hostname":"www.example.com"}`
  returns the CNAME and TXT records to add. For providers that only accept IP addresses use
  `"mode":"nameservers"` and point the domain's nameservers to the returned ones.
