> ## Documentation Index
> Fetch the complete documentation index at: https://docs.withrealm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Command line interface

> Drive the Realm API from your terminal with the Realm CLI

## Overview

The Realm CLI wraps the same REST API documented in this section. It gives you agent chats with live streaming answers, document management for API data sources, and an interactive chat session, all from a terminal. Every command accepts `--json`, so the CLI also works as a scripting tool in pipelines.

## Installation

The CLI ships as a single standalone executable. On macOS and Linux:

```bash theme={null}
curl -fsSL https://storage.googleapis.com/realm-cli/install.sh | bash
```

On Windows, in PowerShell:

```powershell theme={null}
irm https://storage.googleapis.com/realm-cli/install.ps1 | iex
```

The installer downloads the executable for your platform together with `SHASUMS256.txt`, verifies the SHA-256 checksum before installing, installs to `$HOME/.realm/bin/realm` (`%USERPROFILE%\.realm\bin\realm.exe` on Windows), adds that directory to your `PATH`, and runs `realm --version` to confirm the result. Nothing else is required: the executable carries its own runtime.

Prebuilt executables cover macOS x64 and arm64, Linux x64 and arm64 for both glibc and musl, and Windows x64 and arm64. Three environment variables change what the installer does: `REALM_INSTALL_DIR` selects the install directory, `REALM_VERSION` pins an exact version such as `0.2.0`, and `REALM_RELEASE_URL` points at an alternate release location, which `realm update` honours as well.

The CLI is also published to npm, which requires Node.js 22.12 or newer:

```bash theme={null}
npm install -g @realmtechnologies/cli
realm --version
```

### Upgrading

An executable installed with the install script updates itself:

```bash theme={null}
realm update
realm update --check
```

`realm update` downloads the latest release for the running platform, verifies its checksum, and replaces the running executable in place. `realm update --check` reports the latest release without installing it, and `realm update --json` prints `{current, latest, channel, target, update_available, updated}`.

When a newer release exists, an interactive run prints one notice on standard error, such as `Update available: 0.1.1 → 0.2.0. Run realm update.`. The version lookup runs in a detached background process at most once every 24 hours and is cached in the CLI configuration directory, so it never delays or fails a command. The notice is suppressed with `--json`, when standard error is not a terminal, when `CI` is set to anything other than `false`, and when `REALM_CLI_NO_UPDATE_CHECK=1`.

On an npm installation, `realm update` declines and points you at `npm install -g @realmtechnologies/cli@latest`.

Run `realm --version` to see which version is installed. An executable also reports its release target, for example `0.1.1 (linux-x64)`.

## Authentication

Create an API key first. See [API keys](/admin/api) for how to create and manage keys, and note that a key carries scopes: `chat:read`, `chat:write`, and `documents:write`.

### Interactive login

```bash theme={null}
realm auth login
```

The command prompts for your key, verifies it against `GET /agents`, and stores it in your operating system credential store. When no credential store is available, for example on a headless Linux host, the key is written to a configuration file with owner-only permissions instead.

The standalone executables always use that configuration file, because the credential-store binding is a per-platform native library that cannot be embedded in a cross-compiled executable. The npm installation uses the credential store whenever one is available. Everything else about the two installations is identical.

A key that carries only `documents:write` cannot list agents. Login still accepts and stores such a key, and notes that chat commands are unavailable with it. A key that fails authentication outright is never stored.

Check or remove the stored key:

```bash theme={null}
realm auth status
realm auth logout
```

### Continuous integration

Set `REALM_API_TOKEN` in the environment. It takes precedence over any stored key, so no login step is needed in a pipeline.

```bash theme={null}
export REALM_API_TOKEN="realm_api_..."
realm agents list --json
```

### Multiple tenants

The default base URL is `https://app.withrealm.com`. Single-tenant deployments live on their own host, which you select with `--base-url` on any command, or persist with `realm config set base-url`. The `REALM_BASE_URL` environment variable overrides the persisted value.

Keys are stored per host, because API keys are tenant scoped. Logging in against two hosts keeps two keys side by side, and each command uses the key of the host it targets. Storing a key for a host also clears any copy of it held by the other store, so a single key per host is all the CLI can ever resolve.

The base URL must use `https://`, because the key travels in an `Authorization` header. Plain `http://` is accepted only for local development hosts: `localhost`, `*.localhost`, `127.0.0.1`, and `::1`.

```bash theme={null}
realm config set base-url https://acme.withrealm.com
realm auth login
realm agents list --base-url https://app.withrealm.com
```

## Global flags

| Flag               | Description                                            |
| ------------------ | ------------------------------------------------------ |
| `--json`           | Print the raw API payload with no decoration.          |
| `--base-url <url>` | Target host for this invocation.                       |
| `--token <token>`  | Use this key instead of the stored or environment key. |

## Command reference

### Authentication and configuration

| Command                           | Description                                                                |
| --------------------------------- | -------------------------------------------------------------------------- |
| `realm auth login`                | Prompt for an API key, verify it, and store it for the active host.        |
| `realm auth status`               | Show the active host, where its key came from, and a masked key prefix.    |
| `realm auth logout`               | Remove the stored key for the active host.                                 |
| `realm config get base-url`       | Print the configured base URL.                                             |
| `realm config set base-url <url>` | Persist the base URL used by later commands.                               |
| `realm update`                    | Replace the running executable with the latest release. Accepts `--check`. |

### Agents and data sources

| Command                 | Description                                                                                                      |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `realm agents list`     | List the agents your key can reach, including which one is the default.                                          |
| `realm connectors list` | List the API data sources of your organization. Their IDs are the data source IDs used by the document commands. |

### Chat

```bash theme={null}
realm chat
```

Running `realm chat` without a subcommand opens an interactive session: pick an agent, send messages, and watch answers stream in. Tool calls that need approval are presented as a prompt, and answering continues the same chat. The session prints its chat ID on exit so you can resume the transcript with `realm chat messages`. The session needs a terminal on both input and output, so with `--json`, redirected output, or piped input the command points you at `realm chat ask` instead.

| Command                         | Description                                                                                                        |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `realm chat ask "<message>"`    | Send one message and print the answer.                                                                             |
| `realm chat list`               | List chats. Accepts `--limit`, `--after`, and `--order`.                                                           |
| `realm chat messages <chat_id>` | Print the messages of a chat in full, one block per message headed by its ID and role. Accepts `--citation-style`. |
| `realm chat delete <chat_id>`   | Delete a chat.                                                                                                     |
| `realm chat approve <chat_id>`  | Resume a chat that is waiting for tool approval.                                                                   |

Flags for `realm chat ask`:

| Flag                       | Description                                                         |
| -------------------------- | ------------------------------------------------------------------- |
| `--agent <id>`             | Agent to ask. Required.                                             |
| `--chat <id>`              | Continue an existing chat instead of starting a new one.            |
| `--stream`                 | Print the answer token by token as it is generated.                 |
| `--research`               | Run the request in research mode.                                   |
| `--tool-mode <mode>`       | One of `ask`, `act`, or `off`.                                      |
| `--citation-style <style>` | One of `link` or `remove`.                                          |
| `--output-format <format>` | One of `markdown` or `text`.                                        |
| `--answer-only`            | Return only the final answer text. Non-streaming only.              |
| `--eco`                    | Use cost-efficient models when the agent allows it.                 |
| `--tool-connector <id>`    | Replace the configured external tools for this request. Repeatable. |
| `--var <key=value>`        | Set a prompt variable. Repeatable.                                  |

```bash theme={null}
realm chat ask --stream --agent ag_123 "Summarize our vacation policy"
```

When an answer stops on a tool approval, the CLI prints the pending tool calls together with the exact `realm chat approve` invocation that resumes the chat.

### Documents

Every document command takes a data source ID from `realm connectors list` and requires the `documents:write` scope.

| Command                                                           | Description                                                                                                                                                                                                                                                                   |
| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `realm documents upsert <data_source_id> --file <path>`           | Create or update documents from a JSON file, in batches of 100.                                                                                                                                                                                                               |
| `realm documents list <data_source_id>`                           | List documents. Accepts `--fields`, `--cursor`, `--limit`, and `--all`. With `--fields` the table shows exactly those columns in the order given; otherwise it shows the fields the API returned. Object values such as `meta` print as compact JSON.                         |
| `realm documents get <data_source_id> <document_id>`              | Print one document.                                                                                                                                                                                                                                                           |
| `realm documents delete <data_source_id> <document_id>`           | Delete one document.                                                                                                                                                                                                                                                          |
| `realm documents prune <data_source_id> --older-than <timestamp>` | Delete documents not updated since an ISO 8601 timestamp. Asks for confirmation, which only `--yes` skips. The prompt needs an interactive terminal on both input and output, so with `--json`, redirected output, or piped input the command refuses to run without `--yes`. |
| `realm documents upload <data_source_id> <file>`                  | Upload a file for indexing. The file is streamed, so large files do not have to fit in memory.                                                                                                                                                                                |

```bash theme={null}
realm documents upsert int_123 --file ./docs.json
```

The upsert file holds either `{ "documents": [...] }` or a bare array of documents, with the fields described in the [upsert documents](/api-reference/documents/upsert-documents) endpoint.

Flags for `realm documents upload`:

| Flag                       | Description                                                                                                  |
| -------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `--title <title>`          | Document title. Defaults to the file name.                                                                   |
| `--id <id>`                | Document ID to upsert. A new document is created when omitted.                                               |
| `--mime-type <type>`       | Content type of the file. Inferred from the file name when omitted.                                          |
| `--url <url>`              | Source URL recorded on the document.                                                                         |
| `--verified`               | Mark the document as verified.                                                                               |
| `--read-access <email>`    | Restrict the document to this user. Repeatable. Omit it to leave the document readable by everyone in Realm. |
| `--meta <key=value>`       | Set a metadata field. Repeatable.                                                                            |
| `--created-at <timestamp>` | Document creation time, as an ISO 8601 timestamp.                                                            |
| `--updated-at <timestamp>` | Document update time, as an ISO 8601 timestamp.                                                              |

## Scripting

With `--json`, a command prints machine-readable JSON on standard output and nothing else, which makes it safe to pipe into a parser such as `jq`.

```bash theme={null}
realm agents list --json | jq '.data | length'
```

Most commands pass the API response through unchanged, so the endpoint reference describes their payload. These are the exceptions:

| Command                      | JSON shape                                                                                                                                                                                                                                          |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `realm auth login`           | `{ "host", "source", "agents", "staleKeychain" }`, where `agents` is the reachable agent count, or `null` when the key cannot list agents, and `staleKeychain` is `true` when a previous key is still in the OS keychain and would take precedence. |
| `realm auth status`          | `{ "host", "source", "token", "agents" }`, with `token` masked.                                                                                                                                                                                     |
| `realm auth logout`          | `{ "host", "loggedOut" }`.                                                                                                                                                                                                                          |
| `realm documents list --all` | `{ "documents": [...] }`, with every page combined and the per-page cursor fields dropped.                                                                                                                                                          |
| `realm documents upload`     | `{ "sourceId" }`. The one-time upload URL is used internally and never printed.                                                                                                                                                                     |
| `realm documents upsert`     | `{ "results" }`, plus `{ "error" }` describing the batch that stopped the run when one fails partway. `error.outcome` is `failed` when the API rejected the batch and `unknown` when no response arrived.                                           |
| `realm chat ask --stream`    | Newline-delimited JSON: one object per stream event, not a single payload.                                                                                                                                                                          |

Indexing is asynchronous, so treat a successful `realm documents upsert` as accepted rather than searchable. An upsert of more than 100 documents is sent in batches; if a batch fails, the command reports the results of the batches that already succeeded, so you can retry only the remainder instead of duplicating accepted documents. If a batch never returns a response, its outcome is reported as unknown: the server may have applied it, so replay it only when every document in it has an explicit `id`.

Without `--json`, redirected output is tab-separated. Cell values are escaped, so a tab, newline, carriage return, or backslash inside a field becomes `\t`, `\n`, `\r`, or `\\`, and every record stays on one line with a fixed column count.

A streamed answer is occasionally revised by the agent, for example when it repairs the language of a reply. On a terminal the CLI erases the answer and reprints it; with redirected output it cannot erase, so it prints a `[answer revised]` marker line before the replacement.

## Exit codes

| Code  | Meaning                                                                                                                                                                                                                                                                                             |
| ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0`   | Success.                                                                                                                                                                                                                                                                                            |
| `1`   | Usage error, such as a missing argument or an unreadable file.                                                                                                                                                                                                                                      |
| `2`   | Authentication error, from a `401` or `403` response.                                                                                                                                                                                                                                               |
| `3`   | API error, from any other failing response, a transport failure such as an unreachable host or a request that exceeded the 60-second response deadline, a partial failure such as an upsert where some documents were rejected, or a streamed answer that ended before the API reported completion. |
| `70`  | Internal CLI failure. Reported with a stack trace; please open an issue.                                                                                                                                                                                                                            |
| `130` | Interrupted with `Ctrl+C`.                                                                                                                                                                                                                                                                          |

## Rate limits

The CLI is bound by the API limit of 600 requests per minute per organization per endpoint. When you exceed it, the request fails with `429 Too Many Requests`, and the CLI reports the `Retry-After` hint from the response. Space out scripted loops and back off when you hit the limit.
