# Foleo Publish agent contract

Foleo turns local Markdown and trusted active HTML into reversible share links. Invited accounts have two agent transports: the `@foleo/cli` commands below, which remain the documented default, and a remote MCP server at `https://mcp.foleo.app/mcp`. Foleo is not listed in any plugin marketplace yet, so MCP is connected by hand.

## Install and authenticate

Requires macOS, Node.js 22+, and an invited Foleo account.

```sh
npx -y @foleo/cli login
npx -y @foleo/cli whoami --json
npx -y @foleo/cli doctor --json
```

Commands use npm `latest`. Signing in to the Mac app does not sign in the CLI. Never ask the user to reveal a token, and never put credentials in prompts, files, artifacts, logs, or repositories. `npx -y @foleo/cli doctor` is read-only: it does not sign in, mint a key, or publish. `npx -y @foleo/cli skill get` prints its bundled portable skill to stdout; it installs nothing. Write that output wherever you load reusable skills or instructions from so it persists across sessions, creating folders as needed. The skill covers local review, publishing, and Artifact lifecycle safety, and it — not this page — is the full command surface: every command, flag, naming rule, numeric limit and error code is documented there, and no gated operation requires fetching this page to complete. Optional: `npm install --global @foleo/cli` puts `foleo` on PATH. Production is the default. For an operator-approved rehearsal, add `--staging` to every command and confirm with `npx -y @foleo/cli environment --staging`.

Use `--json` and carry returned ids, opaque `etag`, `version`, and compatibility `stateRevision` values forward exactly. Use `npx -y @foleo/cli list --json` to recover owner state through the canonical Artifact catalog. From `@foleo/cli` 0.1.32 a normal login can delete and restore — delete is reversible, keeping the bytes for a 30-day restore window — and earlier versions need `--allow-delete`, which newer ones still accept and ignore. Either way, irreversible purge needs a second opt-in: after explicit human approval, re-run login with `--allow-purge`.

## Remote MCP (invited accounts)

```sh
claude mcp add --transport http foleo https://mcp.foleo.app/mcp
```

Then complete sign-in in the browser — in Claude Code, `/mcp`. Nothing is pasted: the connection is OAuth, so never ask a user for a Foleo token, password, one-time code, or recovery code, and never write one into a config file. Other harnesses connect the same Streamable HTTP URL through their own remote-MCP configuration.

The tools are artifact-generic and mirror the commands below: `list_foleo_artifacts`, `get_foleo_artifact`, `publish_foleo_artifact`, `update_foleo_artifact_settings`, `unpublish_foleo_artifact`, `delete_foleo_artifact`, `restore_foleo_artifact`, `get_foleo_deletion_status`. Call `get_foleo_capabilities` first: it reports the connected organization and role, the scopes actually granted, what the account may publish, current size limits, and the MCP contract version — trust it over any bundled instructions. Carry the same opaque `etag` this page describes, and generate an `idempotencyKey` per mutation.

A connection starts with read, publish, active HTML, settings, unpublish, delete, and refresh access; it has no elevated scope and never uses step-up. Purge is not an MCP tool: delete instead starts the 30-day trash window, during which restore remains available, and Foleo auto-purges on schedule. Manual purge remains a dashboard or CLI action. Publishing active HTML still stages an exact candidate and returns a review URL — a human approves those precise bytes by hash before anything is served. Revoke a connection at Account → Agent connections in the dashboard; deleting a client's config does not revoke it.

## Artifact discovery and lifecycle

The following commands work for both Markdown and approved HTML. The server resolves source format from the id; do not invent `html-delete`, `html-restore`, or similar commands.

```sh
npx -y @foleo/cli list --json
npx -y @foleo/cli list --kind document --format markdown --json
npx -y @foleo/cli get <id> --json
npx -y @foleo/cli status <id> --json
npx -y @foleo/cli unpublish <id> --revision <etag> --json
npx -y @foleo/cli delete <id> --revision <etag> --json
npx -y @foleo/cli restore <id> --revision <deletion-etag> --json
npx -y @foleo/cli purge <id> --revision <etag> --confirm <id> --json
npx -y @foleo/cli deletion-status <id> --json
```

Unpublish is reversible, timerless, and byte-preserving. Delete immediately stops routing and starts a 30-day restore window for Foleo-held cloud bytes; it never deletes local user files. Purge skips the grace window but remains asynchronous. A `202` response means accepted, not erased. Poll `deletion-status` and claim erasure only when state is `complete`. Purge always requires explicit human intent and an exact id confirmation; `--yes` is not a substitute.

## Markdown workflow

Create `notes.md`, then:

```sh
npx -y @foleo/cli publish ./notes.md --json
npx -y @foleo/cli update <id> ./notes.md --revision <etag> --json
```

Publishing returns a stable rendered `url`; the Markdown source is the same URL with `.md` appended. Updates preserve both URLs. New pages are unlisted. Unpublish makes reader URLs return `404` while retaining owner history. Mermaid fences render as diagrams in the reader's browser inside a sandboxed frame: they need JavaScript, print once loaded, and are usually dropped by reader modes, so never let a diagram carry information the text omits.

If creation returns `matching_source_exists`, report the named owner-scoped candidates and use the selected id for update/reconnect. Do not create a duplicate automatically. `--publish-separately` is an explicit override and requires the human to intend a distinct Artifact with identical content.

## Trusted active-HTML alpha

Before creation, stop and ask the human to inspect the source and approve executable hosting risk. Do not add `--accept-hosting-risk` yourself without that explicit approval. HTML can run JavaScript, show forms, and initiate downloads. Use no sensitive information and open test links in a dedicated/private browser profile.

Create a static site rooted at `site/index.html`. The alpha accepts additional UTF-8 `.html`/`.htm` pages and allowlisted local CSS, JavaScript, images, fonts, JSON, and Wasm assets. Direct page paths, clean `.html` routes, and directory `index.html` routes work; Foleo does not generate navigation, redirects, or an SPA fallback. Pages render at full fidelity — remote scripts, styles, fonts, images, media, fetch/XHR/WebSocket, frames, and forms all work. Only Worker/SharedWorker/ServiceWorker are blocked. This trusted pre-PSL alpha still accepts parent-domain cookie risk between testers.

An HTML artifact gets its own subdomain, so **`--name <label>` is required**, and that name is the artifact's address — there is no generated fallback host. Choose it with the human. Rules: 3-63 chars, `a-z`, `0-9`, hyphens, no leading/trailing/doubled hyphen. `name-check` and `--dry-run` are free and consume no publish quota. Markdown never requires a name.

Renaming later is explicit and must say what happens to the old URL, which is the human's call: `name set <id> <label> --previous keep-as-alias` keeps the old URL working (each alias holds one of 25 active names); `--previous release` stops it working and holds the name for this account for 30 days, where renaming back reclaims it. `name release <id> <label> --acknowledge-link-breakage` drops an extra name; an artifact's last name cannot be released. `names --json` lists what the account holds and its name quota.

```sh
npx -y @foleo/cli name-check leadtube --json
npx -y @foleo/cli publish ./site --accept-hosting-risk --name leadtube --dry-run --json
npx -y @foleo/cli publish ./site --accept-hosting-risk --name leadtube --json
npx -y @foleo/cli names --json
npx -y @foleo/cli name set <id> leadtube-2026 --previous keep-as-alias --json
npx -y @foleo/cli name release <id> leadtube --acknowledge-link-breakage --json
npx -y @foleo/cli update <id> ./site --revision <etag> --json
npx -y @foleo/cli settings <id> --json
npx -y @foleo/cli settings <id> --set visibility=private --revision <etag> --json
npx -y @foleo/cli settings <id> --password-stdin --revision <etag> --json
npx -y @foleo/cli limits --json
```

`publish` infers Markdown vs HTML from the path, and the name requirement follows that inferred format — never the command spelling. Under `--json` every failure is one object on stdout with a stable `error.code`; read it rather than the exit status alone, and never retry a `quota_attempts_exhausted`. The six commands remain deprecated `html-*` aliases and still accept compatibility `stateRevision`. Always use the newest returned opaque `etag` on generic update and settings mutations; stale mutations fail with `revision_drift` or `state_drift`. Pipe the secret to `--password-stdin`; never pass `--password` on argv or inside `--set`/`--settings`. Password setting changes visibility to `password`. `private` conceals the page from public readers; `unlisted` restores link sharing. Public/indexed HTML is unavailable. Unlisted HTML renders in a frame below a Foleo bar, at the same URL; don't depend on being top-level, `window.open` handles, or passkeys. Clients that send no browser fetch metadata (agents, curl, link unfurlers) still get the exact bytes. The bar can be hidden per artifact with `settings <id> --set foleoBarDisplay=hidden --revision <etag>`, which needs the `publish.badge.remove` entitlement (Foleo staff only during beta); without it the call fails with `entitlement_required`, so don't retry.

On an API error, report its exact code and stop rather than guessing, minting credentials, changing environments, or creating a replacement artifact.
