> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/local-ai/nvpair/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/local-ai/nvpair/_mcp/server.

# Using the PAIR terminal interface

`nvpair-tui` is a full-screen keyboard-driven interface for operating one PAIR
host.

**This is the headless option, not a second UI.** Use it on a machine with no
desktop environment, or over SSH, where the desktop application cannot run. If a
desktop is available, use the desktop application.

**It has known limitations.** It is an operations tool, not a full replacement.
It cannot list or delete models, change an engine's port, update an engine,
control engines on other nodes, or show which node served a workload. The full
list is in
[What the Terminal Interface Cannot Do](#what-the-terminal-interface-cannot-do),
and it is worth reading before you depend on it.

> **Never run the terminal interface and the desktop application on the same
> machine at the same time.** This is not a preference. Each one starts its own
> broker and full worker tree, so two sets of services would fight over the same
> proxy ports, try to manage the same engines, and write the same settings files.
> Expect port conflicts, engines that refuse to start, and confusing state on both
> sides. Quit one before starting the other.

Within its scope it is self-contained. It starts its own service process tree, so
you do not run anything else first.

## `nvpair` and `nvpair-tui` Both Start It

An installed PAIR puts `nvpair` on your `PATH` as a small wrapper that runs
`nvpair-tui`, so either command opens this interface.

**Do not count on `nvpair` existing on a headless machine.** Only the Debian
package writes the wrapper at install time. On Windows and macOS the desktop
application writes it when it starts, so on a machine where you never open the
desktop application — the case this interface exists for — it may never appear.
On macOS it is also skipped when `/usr/local/bin` is not writable. Run
`nvpair-tui` directly when `nvpair` is not found, and do the same for a source
build, which has no wrapper at all. Refer to
[Building PAIR](/local-ai/nvpair/building#run-without-the-desktop-application).

## Start It

Before you start it, confirm the desktop application is not running on this
machine, including minimized to the tray or menu bar. Quit it first.

```bash
nvpair-tui
```

From the release archive, extract it and run `nvpair-tui` from the directory the
binaries are in. It looks for `nvpair-ui-broker` beside itself, so keep the
extracted files together:

```bash
cd <directory containing nvpair-tui>
./nvpair-tui
```

| Flag                   | Effect                                                                                                                               |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `--broker-path <path>` | Use a service binary that is not beside `nvpair-tui`                                                                                 |
| `--log-level <level>`  | Verbosity of the terminal interface's own logging: `debug`, `info`, `warn`, or `error`. PAIR also reads this from `NVPAIR_LOG_LEVEL` |
| `--version`            | Print the version and exit                                                                                                           |

The interface's own log output goes to stderr, so it never corrupts the display.
Service logs appear on the **Logs** tab instead.

Press `q` to quit. Quitting shuts the services down cleanly rather than leaving
them running.

### Keep It Running After You Disconnect

Quitting stops the services, and losing an SSH connection ends the program the
same way. A node you reach over SSH therefore stops serving requests when your
session drops. Start it inside a terminal multiplexer so the session survives
independently of your connection:

```bash
tmux new -s pair
nvpair-tui
```

Detach with `Ctrl-b d`, and reattach later with `tmux attach -t pair`. The
services keep running in between.

[tmux](https://github.com/tmux/tmux/wiki) and
[GNU Screen](https://www.gnu.org/software/screen/) both work. With Screen, start
with `screen -S pair`, detach with `Ctrl-a d`, and reattach with
`screen -r pair`. Neither ships with PAIR. Install whichever your distribution
provides.

## The Screen

The top line shows `NVPAIR TUI` and the connection state on the right:
`connecting to broker...`, `broker ready v<version>`, or `broker disconnected`.
The second line is the numbered tab bar. The footer shows the keys available on
the current tab.

If you see `starting...`, the interface is waiting for the terminal size. If the
header stays on `connecting to broker...`, the service tree did not come up, and
the **Logs** tab says why.

![The terminal interface on the Overview tab, showing the header with broker ready, the numbered tab bar, the worker table, and the footer keys.](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/nvidia-personal-ai-router.docs.buildwithfern.com/0e078a6177397de19ac0c40d59c5e0e549982f2b1882be89642d3bfdc3fc93af/_dot_dot_/docs/assets/onboarding/terminal-interface/01-tui-overview.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIA6KXJSKKNFOCF7G4B%2F20260904%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260904T150554Z&X-Amz-Expires=604800&X-Amz-Signature=6b1cea977e3c91f48356f4217a4bc07a90b62369c51096ffc06fef2977adc322&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

## Moving Around

| Key                   | Action           |
| --------------------- | ---------------- |
| `tab`, `l`, `→`       | Next tab         |
| `shift+tab`, `h`, `←` | Previous tab     |
| `?`                   | Toggle full help |
| `q`, `ctrl+c`         | Quit             |

Within a table, `j` / `k` (or `↓` / `↑`) move the selection, `f` / `b` page, and
`g` / `G` jump to the first and last row.

While you are typing into a field, such as a PIN, an address, a port, or a model
name, every key goes to that field. Press `enter` to submit or `esc` to cancel.
Tab switching and `q` do not work until you do.

## Tabs

| #  | Tab           | What It Shows                                                                             |
| -- | ------------- | ----------------------------------------------------------------------------------------- |
| 1  | **Overview**  | Service uptime and version, and an `ok` / `DOWN` table for each worker                    |
| 2  | **Errors**    | Active service errors by severity, age, node, and message                                 |
| 3  | **Nodes**     | Nodes discovered on the network, with `Connected` or `In cluster` status                  |
| 4  | **Proxies**   | Both compatible proxies: listening port, discovered upstreams, and which node is selected |
| 5  | **Workloads** | Live inference workloads: ID, model, engine, state, and age                               |
| 6  | **Engines**   | Local engines: installed, running, healthy, and port                                      |
| 7  | **Cluster**   | This node's identity, cluster membership, and pairing                                     |
| 8  | **Manual**    | Nodes you added by address, with reachability                                             |
| 9  | **Settings**  | Node settings: force ports, cluster auto-sync, and cluster ID and name                    |
| 10 | **Logs**      | Service log output, with live log-level control                                           |

## Pair This Machine with Another

Pairing is the same six-digit PIN exchange the desktop application uses.

**To invite a machine you can already see**, from the **Nodes** tab (3):

1. Select it with `j` / `k`.
2. Press `i`. The status line shows the PIN.
3. Read that PIN to whoever is at the other machine.

This is the easier path, because there is no address to type. Prefer it whenever
PAIR has already discovered the machine you want.

**To invite a machine by address**, from the **Cluster** tab (7):

1. Press `i`.
2. Type the other machine's host, or `host:port` if it is not on the default
   pairing port.
3. Press `enter`. The status line shows the PIN.
4. Read that PIN to whoever is at the other machine.

Use this when discovery has not found the machine, for example on a network that
filters multicast.

**To accept an invitation from another machine**, from the **Cluster** tab:

1. Wait for the status line to read `invite received from <name>`.
2. Press `a`.
3. Type the PIN displayed on the inviting machine and press `enter`.

Press `d` instead to decline. After pairing, the peer appears under **Members**.

![The terminal interface Nodes tab with a discovered machine selected and the pairing PIN on the status line.](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/nvidia-personal-ai-router.docs.buildwithfern.com/c37b94889c43c777b7be15ee13bacfd8bf36d5815771623ee0b357b196918a20/_dot_dot_/docs/assets/onboarding/terminal-interface/02-tui-pairing.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIA6KXJSKKNFOCF7G4B%2F20260904%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260904T150554Z&X-Amz-Expires=604800&X-Amz-Signature=f0d135224908437144770d4705f542f71394493fdfa5ebe9d62080a9f7ab5017&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

| Key | Action                              | Tab     |
| --- | ----------------------------------- | ------- |
| `i` | Invite the selected discovered node | Nodes   |
| `i` | Invite by address                   | Cluster |
| `a` | Accept an inbound invitation        | Cluster |
| `d` | Decline an inbound invitation       | Cluster |
| `r` | Remove the selected member          | Cluster |
| `L` | Leave the cluster (capital L)       | Cluster |

Only pair when you trust both machines and the network. The PIN is a short-lived
bootstrap code, not a durable credential. Refer to the
[security policy](https://github.com/NVIDIA/Personal-AI-Router/blob/main/SECURITY.md).

## Prepare an Engine and a Model

From the **Engines** tab (6), select an engine with `j` / `k`, then:

| Key | Action           |
| --- | ---------------- |
| `i` | Install          |
| `s` | Start            |
| `x` | Stop             |
| `r` | Restart          |
| `u` | Uninstall        |
| `p` | Download a model |

Pressing `p` opens a prompt. Type the model name, for example `qwen4:12b`, and
press `enter`. Progress appears on the status line.

A node can serve a request only when it is online, a compatible engine is
running, and the requested model is present on that node. To route across several
machines, download the same model on each.

## Check Routing and Health

The **Workloads** tab (5) lists inference work as it runs, with its model,
engine, and state.

![The terminal interface Workloads tab listing live inference workloads with model, engine, state, and age.](https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/nvidia-personal-ai-router.docs.buildwithfern.com/998265d06a612e0551bde772872c680540291e83e93f10921517514f61479ef4/_dot_dot_/docs/assets/onboarding/terminal-interface/03-tui-workloads.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIA6KXJSKKNFOCF7G4B%2F20260904%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260904T150554Z&X-Amz-Expires=604800&X-Amz-Signature=7c8a6f2850be88ce9b6125b75de33df2e9be3e7a3e74e75508d0dc40428b93fe&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject)

The **Proxies** tab (4) shows each proxy's listening port and whether it is
routing automatically (`selected=auto`) or pinned to one node. Press `g` to
switch between the two engines, `enter` to pin the highlighted upstream, and `a`
to return to automatic routing. Leave it on automatic unless you are
deliberately testing one node.

The **Overview** tab (1) reports whether each worker is up. Worker status is
best-effort. `DOWN` means a worker reported a crash.

## Look at Errors and Logs

On **Errors** (2), press `c` to clear the selected entry.

On **Logs** (10), scroll with `j` / `k` and the page keys. Set the log level for
the whole service fleet with `d` (debug), `i` (info), `w` (warn), or `e` (error).
This is the first place to look when something has not started.

## Change Settings

On **Settings** (9), move with `j` / `k` and press `enter`. Booleans toggle
immediately. Text fields open for editing, with `enter` to save and `esc` to
cancel.

Change proxy ports on the **Proxies** tab with `p`, not here. Refer to
[Ports](/local-ai/nvpair/getting-started#7-connecting-your-agents-and-port-information)
for how PAIR arranges ports.

## What the Terminal Interface Cannot Do

It is an operations tool, not a full replacement for the desktop application:

* It cannot list or delete models. You can download one, but the interface shows
  no model inventory.
* It cannot change an engine's port. The port column is read-only. Use the
  desktop application to change it.
* It cannot update an engine or control engines on other cluster nodes.
* It does not show which node served a particular workload.
* It has no built-in way to send an inference request. Use `curl` or another
  client against the proxy port, as in
  [Getting Started](/local-ai/nvpair/getting-started#6-run-your-first-inference).

## See Also

These documents cover related topics:

* [Getting Started](/local-ai/nvpair/getting-started) — first-run setup and endpoints
* [Ports](/local-ai/nvpair/getting-started#7-connecting-your-agents-and-port-information) —
  which ports to use and how to change them
* [Troubleshooting](/local-ai/nvpair/troubleshooting)
* [`nvpair-tui` component reference](https://github.com/NVIDIA/Personal-AI-Router/blob/main/services/nvpair-tui/README.md) — internals
  and build instructions