# artifact.cafe docs

artifact.cafe publishes static HTML artifacts for review. The core loop is:

```sh
npx artifact-cafe@latest publish .
# share the review URL and collect guest comments
npx artifact-cafe@latest comments
# make changes, then publish v2 from the same folder
npx artifact-cafe@latest publish .
```

Each publish creates a new immutable version. Comments stay attached to the
version where they were made.

## For agents

Paste this into `CLAUDE.md`, `AGENTS.md`, or an agent instruction file:

```md
When you produce a reviewable HTML artifact, publish it with:
npx artifact-cafe@latest publish . --title "<descriptive title>" --json --no-open

Use the returned url as the review link. Keep working from the same folder so
.artifactcafe/config.json links future publishes to the same artifact.

Before revising, pull reviewer feedback with:
npx artifact-cafe@latest comments . --json --status open --version current

After changes, publish again from the same folder. Each publish creates a new
immutable version; do not edit old versions in place.
```

## CLI

### `publish`

```sh
npx artifact-cafe@latest publish [dir]
```

Options:

- `--title <title>` sets the artifact title.
- `--notes <text>` records a bullet-point changelog for this version (newline-separated), shown in the versions sidebar.
- `--entry <file>` selects the HTML entry file.
- `--artifact <id>` publishes to a specific existing artifact.
- `--password <password>` password-protects the artifact (min 6 characters).
- `--json` prints machine-readable output and does not open a browser.
- `--no-open` prints the review URL without opening it.

### `comments`

```sh
npx artifact-cafe@latest comments [dir]
```

Options:

- `--status open | resolved | all` filters threads. Default: `open`.
- `--version current | all` filters versions. Default: `current`.
- `--json` prints the full export for agents.

### `protect`

```sh
npx artifact-cafe@latest protect [dir]
```

Sets or removes the password gate on the linked artifact.

Options:

- `--password <password>` sets or updates the gate password (min 6 characters).
- `--off` removes the password gate.
- `--json` prints machine-readable output.

### `open`

```sh
npx artifact-cafe@latest open [dir]
```

Prints and opens the linked artifact review URL.

There is no `login` command. Use the claim link from first publish to attach an anonymous artifact to an account.

## Publishing concepts

Artifacts are static HTML folders. artifact.cafe does not run SSR, backend
processes, databases, cron jobs, or serverless functions for the artifact.

Entry file detection:

- `index.html` is used when it exists.
- If the folder root has exactly one HTML file, that file is used.
- Otherwise pass `--entry file.html`.

The CLI skips repo metadata, dependency folders, `.artifactcafe/`, env files,
private keys, symlinks, unsafe paths, and zero-byte files.

Limits:

- Maximum file size: 100 MB.
- Maximum total artifact size: 250 MB.
- Maximum files per publish: 1,000.
- Publish sessions expire after 1 hour.
- Anonymous publishing is limited to 20 publishes per IP per day.
- Anonymous artifacts expire 24 hours after their last publish unless claimed.

## Tokens and auth

First publish stores `.artifactcafe/config.json` in the published folder. It
contains the artifact id, review URL, API URL, and publish token needed for
future versions.

- The publish token is returned once by the API and is not printed by the CLI.
- The CLI auto-adds `.artifactcafe/` to an existing `.gitignore`.
- If the file is lost (or you don't want to check it in for CI), set
  `ARTIFACT_CAFE_TOKEN` in the environment — the CLI falls back to it when
  `.artifactcafe/config.json` is missing or doesn't cover `--artifact <id>`.
  `ARTIFACT_CAFE_URL` overrides the API URL the same way. If you don't have
  the token, publish a new artifact and share the new URL.
- The claim link is shown once on first publish and turns an anonymous artifact
  into an owned artifact after sign-in.

## Reviewing

Reviewers open the artifact link, enter a guest name, and leave feedback where
it belongs. Point comments attach to an element position. Text comments attach
to selected text. Threads can be resolved or reopened. The version switcher
keeps old feedback visible on the version it described.

Some links are password-protected — enter the password once when prompted and
the artifact stays unlocked for later visits. If an artifact looks unsafe, see
Security and trust below for how to report it.

## Security and trust

Artifact HTML is untrusted content. It renders on its own
`{slug}.artifactcafe.dev` origin inside a sandboxed iframe, separate from
the review app. Legacy `{slug}.artifact.cafe` URLs redirect there.

- Do not enter passwords, API keys, or private data into an artifact.
- Anonymous artifacts expire after 24 hours unless claimed.
- Anonymous publishing is rate-limited by IP.
- Owners can password-protect an artifact so only reviewers with the password
  can open it.
- Report an unsafe artifact with `POST /api/v1/artifacts/{artifactId}/report`,
  or contact the person who sent you the link.

## Errors

API errors return `code`, `message`, optional `retryAfter`, and `docsUrl`.
Stable anchors live at `/docs/errors#<code>`.

- `invalid_request`: request body, params, query, or manifest is not valid.
- `unauthorized`: a guest identity, publish token, or signed-in owner is required.
- `forbidden`: the credential is valid, but it cannot perform this action.
- `not_found`: the route, artifact, version, session, or thread does not exist.
- `rate_limited`: a publish, comment, or report rate limit was hit; retry after
  `retryAfter` seconds.
- `payload_too_large`: a file or artifact exceeds publish size limits.
- `session_expired`: the publish session expired before finalize.
- `session_finalized`: the publish session was already finalized.
- `uploads_incomplete`: finalize ran before every required upload reached storage.
- `claim_token_invalid`: the claim link is not recognized.
- `claim_token_expired`: the claim link expired with the anonymous artifact window.
- `claim_token_used`: the claim link was already used.
- `already_claimed`: the artifact already has an owner.
- `slug_taken`: another artifact already uses that slug.
- `slug_reserved`: that slug is reserved by artifact.cafe.
- `password_required`: the artifact is password-protected and no valid unlock
  cookie, publish token, or owner session was present.
- `invalid_password`: the password submitted to unlock a protected artifact
  was incorrect.
- `internal_error`: the server failed unexpectedly.

## HTTP API

The CLI uses the same public `/api/v1` API that agents can call directly. Exact
schemas are available at `/api/docs`.

Key endpoints:

- `POST /api/v1/publish`
- `POST /api/v1/publish/{publishSessionId}/finalize`
- `GET /api/v1/artifacts/{artifactId}`
- `PATCH /api/v1/artifacts/{artifactId}` (owner)
- `DELETE /api/v1/artifacts/{artifactId}` (owner)
- `GET /api/v1/artifacts/{artifactId}/versions`
- `PUT /api/v1/artifacts/{artifactId}/protection`
- `POST /api/v1/artifacts/{artifactId}/unlock`
- `POST /api/v1/artifacts/{artifactId}/report`
- `GET /api/v1/artifacts/{artifactId}/comments`
- `GET /api/v1/artifacts/{artifactId}/comments/export`
- `POST /api/v1/artifacts/{artifactId}/comments`
- `POST /api/v1/comment-threads/{threadId}/messages`
- `POST /api/v1/comment-threads/{threadId}/resolve`
- `POST /api/v1/comment-threads/{threadId}/reopen`
- `DELETE /api/v1/comment-threads/{threadId}` (owner)
- `POST /api/v1/claim/{token}`

## Boundary

artifact.cafe is for reviewable static artifacts, not production app hosting.
Backend hosting, private apps, secrets, login-gated reviewer flows, analytics,
templates, and self-hosting are not part of the product.
