# CLI Reference

The CLI is the primary publish surface for humans, agents, and CI.

Human page: /docs/cli
Markdown page: /docs/cli.md

## Commands

| Command | Purpose |
| --- | --- |
| `agent-paste help publish` | Agent-oriented publish guide with mode choices, recipes, and JSON fields. |
| `agent-paste login` | Sign in through browser OAuth and store a scoped local credential. |
| `agent-paste logout` | Revoke the stored credential when possible, then remove it locally. |
| `agent-paste whoami` | Show the resolved Workspace, actor, and granted scopes. |
| `agent-paste publish <path>` | Upload files, publish a Revision, and print the result. Content-only and private. |
| `agent-paste pull <artifact-id> <path>` | Read one stored file's content back from an Artifact. |
| `agent-paste edit <artifact-id> <path>` | Apply literal find/replace edits to one stored file, then publish a new Revision under the same link. |
| `agent-paste set-visibility <artifact-id> <private|unlisted>` | Change visibility. `unlisted` returns `unlisted_url`; `private` revokes active Access Links. |
| `agent-paste version` | Print the CLI version baked into the package or binary. |
| `agent-paste upgrade [<tag>]` | Self-update a standalone binary install. |

## Auth checks

`agent-paste whoami` answers the auth state query. It exits `0` when signed out because the command ran successfully and returned a valid signed-out state. Agents and scripts should use `agent-paste whoami --json` and branch on `authenticated`, not on the process exit code.

## Publish flags

| Flag | Purpose |
| --- | --- |
| `--artifact-id <id>` | Publish a new Revision of an existing Artifact. |
| `--title <text>` | Set the display title. New Artifacts default to the file or folder name; revisions preserve the existing title unless this is explicit. |
| `--entrypoint <path>` | Choose the file opened first by viewers. |
| `--render-mode <mode>` | Override inferred mode: `html`, `markdown`, `text`, `image`, `audio`, or `video`. |
| `--ephemeral` | Restricted accountless fallback for non-interactive text/images/static output. Ignores stored login, disables scripts while unclaimed, and prints `unlisted_url` plus `claim_url`. |
| `--claim-code <clm_...>` | Optional attribution for `--ephemeral`. Preserve it when copied instructions include one; the API embeds it in the Claim Token and the CLI never returns it separately. |
| `--revision-id <id>` | With `pull`, read a specific Revision instead of the latest Published Revision. |
| `--edits <file>` | With `edit`, read the JSON edit array from a file instead of stdin. |
| `--json` | Emit pure JSON on stdout. Errors still go to stderr. |
| `--quiet` | Suppress human-readable stdout. |
| `--color` / `--no-color` | Force rich or plain output. Default: rich on a TTY, plain when piped. |

## Path behavior

`publish <path>` accepts a file or directory. Directory publish uploads every included file and preserves relative paths, so an HTML entrypoint can load sibling CSS, JS, JSON, images, and fonts. Entrypoint inference is exactly `index.html`, `index.md`, `README.md`, then the only file in the directory. If a multi-file directory has none of those, publish fails; pass `--entrypoint <path>`.

Folder uploads exclude `.git/`, `.DS_Store`, `node_modules/`, `.env`, and `.env.*`.

## Output

Publish is content-only and private. A successful CLI publish leads with `View`, the `private_url` (`/v/<artifactId>` clean viewer for the Workspace Member), then an `Update` line: the one command to revise this Artifact in place (`publish <path> --artifact-id art_...`). The `Update` line is the explicit revise handle on the human surface — Revision IDs, `revision_content_url`, and `agent_view_url` stay in the JSON output. Revising keeps the same link and live-updates pages already open; publishing again without the id makes a new Artifact on a new link.

```text
✓ Published "My Publication Title"

  View      https://app.agent-paste.sh/v/art_01H...
  Expires   2026-06-20
  Upload    3/3 uploaded, 0 reused · 42 KB sent, 0 B cached

  Update    npx @zaks-io/agent-paste publish ./report --artifact-id art_01H...
            (revises this Artifact; same link live-updates the open page)

  → open https://app.agent-paste.sh/v/art_01H...
```

> Private Links are login-walled
> A `private_url` opens the app viewer for a signed-in Workspace Member. Plain HTTP clients can receive the app shell or sign-in redirect state with a 200 response; that does not make the Artifact reachable without login. Use `set-visibility <artifact-id> unlisted` for a no-login browser link.

> Authenticated unlisted sharing is a separate step
> Authenticated publish is content-only and private; `private_url` is the login-walled `/v/<artifactId>` clean viewer. When a human needs a no-login URL that follows later publishes, run `agent-paste set-visibility <artifact-id> unlisted`; it mints or reuses the one unlisted Share Link and returns `unlisted_url`. Accountless `--ephemeral` publish is the exception: it auto-creates that unlisted Share Link and returns `unlisted_url` immediately. `set-visibility <artifact-id> private` revokes active Access Links. `revision_content_url` is raw signed byte delivery for one Revision.

> Ephemeral output leads with the no-login link
> With `--ephemeral`, human-readable output leads with `unlisted_url`, the no-login script-disabled Share Link that works immediately. The `claim_url` is the keep/upgrade path for owning the Artifact and unlocking interactivity. There is no user-backed session before claim; the signed-in browser session that opens `claim_url` chooses the destination Workspace, and pre-claim credentials stop working after claim. If the publish command includes `--claim-code <clm_...>`, the CLI sends it for attribution and the API embeds it in the Claim Token; no generated URL contains `claim_code`. Agents should relay `unlisted_url` for viewing and never relay `private_url` from an unclaimed ephemeral publish.

> Check auth before ephemeral
> Agents should run `agent-paste whoami --json` before using `--ephemeral`; it exits `0` either way, so check the JSON, not the exit code. If it reports you are signed in, publish normally. If browser auth is possible, run `agent-paste login` before publishing. Use `--ephemeral` only when login is unavailable or explicitly skipped. Ephemeral is fine for non-interactive text, markdown, images, and static HTML/CSS. It is wrong for interactive HTML/JS because scripts stay disabled while unclaimed; after claim, interactivity runs through the controlled Artifact Viewer.

## Pull and edit

`pull` reads one stored file back so an agent can inspect or edit against the current bytes. Plain `pull` writes the text body to stdout; `--json` adds metadata such as `sha256`, `size_bytes`, `is_binary`, and `body` when the file is UTF-8 text and within the inline size limit.

```sh
agent-paste pull art_01H... index.html > current-index.html
agent-paste pull art_01H... index.html --revision-id rev_01H... --json
```

`edit` applies the same literal find/replace shape as MCP `multi_edit`, then publishes a new Revision under the same stable Artifact link.

```sh
printf '[{"old_string":"old","new_string":"new"}]' |
  agent-paste edit art_01H... index.html --json

agent-paste edit art_01H... index.html --edits edits.json --json
```

Each `old_string` must match the current file exactly once unless `replace_all: true` is set. A non-matching or ambiguous edit fails loudly; pull the file first to get the exact base text.

## Retries

The CLI generates one idempotency key per publish and reuses it across automatic retries, so transient failures do not create duplicate Artifacts or Revisions.
