> ## 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 is published to npm and requires Node.js 22.12 or newer.

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

### Upgrading

The CLI is versioned and released independently of the Realm web application. Install the newest release over your current one:

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

Run `realm --version` to see which version is installed.

## 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.

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.                            |

### 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.
