---
title: OpenRobot POT CLI - install and operator guide
description: Install and operate the standalone OpenRobot POT CLI on macOS, Linux, and Windows.
canonical: https://pot.theopenrobot.com/
markdown: https://pot.theopenrobot.com/index.md
last-reviewed: 2026-08-31
---

# Cards in. Ready receivers out.

The complete standalone guide for manufacturing and offloading receiver SD cards from macOS, Linux, or Windows.

> **Note:** The `pot` command includes its own runtime and ext4 reader. It does not require Python, Homebrew, WSL, a filesystem driver, a distro package, or a source checkout.

[View this guide as Markdown](https://pot.theopenrobot.com/index.md) · [Agent documentation index](https://pot.theopenrobot.com/llms.txt)

## On this page

- [Install](#install)
- [Agent contract](#agent-contract)
- [Set up a station](#setup)
- [Readers and targeting](#readers)
- [Set up cards](#setup-cards)
- [Run batches](#batches)
- [Completion states](#states)
- [Cloud offload](#offload)
- [Local / SSD export](#export)
- [macOS over SSH](#ssh)
- [Linux](#linux)
- [Windows](#windows)
- [Recovery](#recover)
- [Troubleshooting](#troubleshooting)
- [Diagnostics and privacy](#diagnostics)
- [Command reference](#reference)

## 1. Install

### macOS or Linux

```console
curl -fsSL https://pot.theopenrobot.com/cli | sh
pot --version
```

The installer detects the operating system and CPU, downloads the matching bundle, verifies its SHA-256 checksum, and installs the `pot` command. Re-running the same command is also the supported update path.

If Terminal reports `pot: command not found`, run the PATH command printed by the installer and open a new shell.

### Windows 11 x86_64 (release candidate)

```powershell
irm https://pot.theopenrobot.com/cli.ps1 | iex
pot --version
```

> **Warning:** **Unsigned preview:** Windows 0.5.4 is publicly downloadable for testing, but it does not yet carry an Authenticode publisher signature. Read the warning and type `INSTALL UNSIGNED` when the installer asks. A managed Windows policy or Smart App Control may refuse an unsigned program without an override.

The installer still requires HTTPS, verifies the release ZIP size and SHA-256, rejects unsafe archive paths, verifies every bundled file against `SHA256SUMS`, and installs under the current user profile without WSL, Python, or the desktop app. It cannot prove the OpenRobot publisher identity until the future signed channel is available. Use **Run as administrator** only for commands that open physical cards.

### Supported hosts

| Host | Architectures | Release status |
| --- | --- | --- |
| macOS 11 or newer | Apple Silicon | 0.5.17 beta |
| Ubuntu 22.04+ or Debian 12+ | x86_64, ARM64 | 0.5.17 beta |
| Windows 11 | x86_64 | 0.5.4 unsigned public preview; native test passed |

You also need administrator access, Internet access, a partner code, a 2.4 GHz Wi-Fi network, and at least one SD-card reader.

## Agent execution contract

When an AI agent is asked to prepare a receiver card, the complete supported workflow is one command:

```console
pot setup BOARD
```

`pot setup BOARD` collects any missing station settings, then performs image selection and download, safety preflight, exact-card confirmation, flashing, verification, provisioning, Tailnet credential retrieval, configuration readback, and durable status. There is no separate card-editing or provisioning step.

> **Warning:** **Agents:** ask only for the board, partner code, Wi-Fi SSID/password, and the operator's intended reader/card selection when those values are not already configured. Never ask for a receiver password, Tailscale key, fleet key, routing token, image file, or hand-written config. Never replace a POT refusal with `dd`, mounted-volume edits, or raw disk commands.

## 2. Set up a station

Insert a disposable card into each physical reader slot that this computer is allowed to manufacture with, then run:

```console
pot setup
pot readers
pot doctor
```

`pot setup` collects and validates:

- the partner/operator code that owns the receivers;
- the 2.4 GHz Wi-Fi SSID and password written to every card;
- the approved physical reader slots; and
- the number of simultaneous writers, conservatively four by default.

The receiver login is always `operator` / `operator`; POT does not ask for it. Tailnet enrollment is mandatory, but POT obtains the configured reusable credential from the partner-gated Cloudflare broker and never asks an operator to paste a Tailscale key. The Wi-Fi password is the only station secret entered during setup. On macOS/Linux it is stored in an owner-only local credential file so the same station works locally, over SSH, and during privileged raw-disk operations. Windows uses the current user's Credential Manager. The password is never printed in status output.

`pot doctor` is the shift-start check. Keep a disposable card in an approved reader while running it so raw access and media-generation protection are actually tested.

### Non-interactive setup

For controlled automation, pass ordinary values as flags and secrets through the environment:

```console
export POT_SETUP_WIFI_PASSWORD='your-wifi-password'

pot setup --non-interactive \
  --partner DEV1-0000 \
  --wifi-ssid 'Your 2.4 GHz SSID' \
  --parallel 4 \
  --all-readers
```

In PowerShell, set the same temporary values with:

```powershell
$env:POT_SETUP_WIFI_PASSWORD = 'your-wifi-password'

pot setup --non-interactive `
  --partner DEV1-0000 `
  --wifi-ssid 'Your 2.4 GHz SSID' `
  --parallel 4 `
  --all-readers
```

Clear the environment variable after setup. Avoid putting passwords directly in command history.

## 3. Readers and exact targeting

POT never writes to every external disk. A target must be removable, safe by policy, present in a reader slot approved during setup, and unchanged at each destructive boundary.

```console
# Read-only inventory
pot readers
pot cards

# Live identification while cards are inserted or removed
pot cards --watch

pot scan --device /dev/disk4

# Replace the station's approved reader selection
pot setup --reselect-readers
```

`pot cards --watch` redraws a live table showing each disk, detected receiver board, capacity, card state, and Tailnet-key state. Use it when sorting a tray or matching a physical card to its current device name; press `Ctrl-C` to stop. It identifies the receiver board and provisioning state, but it is not proof of an exact golden-image version or build. Add `sudo` on macOS/Linux if raw reads need elevation; on Windows, run it from Administrator PowerShell.

**Cards leave the bench current (0.5.17).** Card setup now downloads the exact signed release your update channel serves, verifies it at the bench, and places it on the card; the receiver installs it during its first boot with no network required. If the release cannot be fetched or verified, the card is built exactly as before and the setup output says so. `--no-staged-update` opts out.

For an unbooted current golden, **KEY YES** means POT verified the credential-bearing persistent firstboot wrapper; the separate `stereorx-image.conf` file is intentionally created only after the receiver starts. **KEY PENDING** means the receiver has booted and its persistent Tailnet retry is active. POT never prints the key.

On Linux, device names usually look like `/dev/sdb`; on macOS, `/dev/disk4`; and on Windows, `\\.\PhysicalDrive3`. Always copy the name from POT's own inventory instead of guessing.

Readers with no serial, or several readers carrying the same factory serial, are supported on macOS when IORegistry exposes distinct USB `locationID` paths. The approval follows the physical controller, hub, and port. Moving a reader to another port therefore requires approval again. Native media-generation checks and retained raw handles still bind each write to the card selected for that slot.

Windows follows the same slot rule using the official physical PnP location path. Duplicate factory serial numbers are safe when the readers occupy distinct USB ports. If Windows exposes no physical location path, the reader cannot be approved.

> **Warning:** **Never infer that a card is empty from an unfamiliar label.** An unrecognized filesystem can still contain important data. Before manufacturing, verify the displayed device, capacity, and reader slot. `pot setup` is destructive.

## 4. Set up cards

The normal workflow is one guided command:

```console
pot setup radxa-cubie-a7z
```

POT first downloads and authenticates the catalog image, displays every selected target, and pins each selected medium read-only. It then asks once for `SETUP`. After confirmation it flashes through that retained raw handle, verifies the image byte for byte, provisions Wi-Fi, partner routing, receiver identity, login, and Tailnet material, verifies configuration readback, flushes the media, and records a durable result.

For diagnosis or planning only, `--dry-run` performs the same preflight and writes no card. It may still download, decompress, and cache the current golden image. It is optional because every real setup run performs that preflight again before confirmation.

### Supported current-golden board keys

| Board | Command key | Windows |
| --- | --- | --- |
| Radxa Cubie A7Z | `radxa-cubie-a7z` | Supported |
| Radxa Cubie A5E | `radxa-cubie-a5e` | Supported |
| Radxa Zero 3W | `radxa-zero-3w` | Use macOS/Linux |
| Raspberry Pi 3B+ | `raspberry-pi-3b-plus` | Supported |

### Limit a run to an exact card or reader

```console
# One currently attached device
pot setup radxa-cubie-a7z --only-device /dev/disk4

# One already-approved reader slot
pot setup radxa-cubie-a7z --reader darwin-reader:YOUR_READER_ID
```

Both flags are repeatable. Use identifiers copied from `pot readers` or the dry-run output.

### Previously used or sensitive cards

```console
pot setup radxa-cubie-a7z --secure-erase
```

`--secure-erase` zeros and reads back all logical capacity outside the new image. This is substantially slower on a large card. It provides logical-sector sanitization, not a guarantee against flash-memory wear-level recovery.

## 5. Run a batch

```console
# Keep the approved slots armed for replacement cards
pot setup radxa-cubie-a7z --watch

# Stop after 20 cards reach a terminal state
pot setup radxa-cubie-a7z --watch --count 20

# Follow durable state from another Terminal
pot status --watch
```

The station default is four simultaneous writers. Additional inserted cards queue. Set a different value during setup, or for one run:

```console
pot setup radxa-cubie-a7z --parallel 8
```

Use higher concurrency only after the powered hubs, readers, cards, and host have passed a real load test. A weak hub can corrupt writes rather than fail cleanly. POT accepts values from 1 to 20; that is a configuration ceiling, not a claim that every station is electrically qualified for 20 writers.

In watch mode, remove a completed card, leave the slot empty for about one second, and then insert its replacement. Never insert or remove media while a slot reports ERASING, WRITING, VERIFYING, or PROVISIONING.

## 6. Understand completion

| State | Meaning and action |
| --- | --- |
| **READY, SAFE TO REMOVE** | Image and configuration passed readback, data was flushed, and the exact retained device was safely ejected. Remove the card. |
| **READY, EJECT BEFORE REMOVAL** | Verification passed, but exact-handle eject was unavailable. Eject the card through the host operating system, then remove it. Linux normally uses this state. |
| **REMAKE_REQUIRED** | Do not ship the card. Put it through a complete `pot setup` run again. |
| **FAILED** | No shipping claim was made. Read the error, correct the station or media problem, and rerun. |

READY means valid Tailnet enrollment material is present on the card. The receiver enrolls after boot and retries persistently when the Tailnet service is temporarily unavailable. Enrollment waits until the receiver has derived its canonical hardware or stamped ID, uses that ID as the Tailnet hostname, and does not consume the credential for the generic discovery name `StereoRX`.

## 7. QC and offload directly to the cloud

`pot offload` goes from the receiver card directly to the routed OpenRobot cloud; it never stages plaintext on the operator computer. Use the separate [`pot export`](#export) command when the destination should instead be a local folder or external SSD. Recordings remain on the card unless you explicitly select one of the verified cloud erase options below. Windows supports the read-only upload path; verified recording erase requires macOS or Linux.

> **Note:** The partner code is the only cloud credential an operator enters. POT obtains the receiver authorization and individual session keys automatically. Do not install or paste a fleet key, routing token, or cloud storage credential.

### What you provide

| Credential | Who handles it | What it does |
| --- | --- | --- |
| **Partner code** | You enter it once | Selects the organization and operator destination for the upload. |
| Receiver authorization | POT automatically | Authorizes only the identified receiver and its assigned route. |
| Session decryption key | OpenRobot cloud, temporarily | Opens only the selected receiver and recording session. |
| Fleet decryption key | OpenRobot cloud only | Never leaves the protected cloud service and is never installed in POT. |
| Cloud storage credentials | OpenRobot cloud only | Uploads are routed to the organization bucket without giving the operator direct bucket credentials. |

### Partner capabilities

OpenRobot can independently enable or disable **manufacturing**, **cloud offload**, **local export**, and **recording erase** for each partner code. Run `pot partner` to see the capabilities stored at setup; every protected command then refreshes the policy from the service before opening a card. A disabled operation exits with a plain `does not permit ...` message and does not inspect, flash, upload from, or erase the card. `--erase-after-upload` requires both the offload and erase capabilities. These switches do not interrupt uploads made automatically by receivers already in the field.

Operators do not configure these switches in the CLI and do not need another credential. Ask the OpenRobot administrator who issued the partner code to change its policy, then rerun the same command.

### Run an offload

On an offload-only station, save and verify the partner code once:

```console
pot partner YOUR-PARTNER-CODE
```

Inspect the card, then run the complete preflight without uploading any recording bytes:

```console
pot scan --device /dev/disk4
pot offload --device /dev/disk4 --preflight
```

Preflight authenticates the receiver identity and routing, inventories every finalized file, and runs QC on every selected session before the first upload byte. The default is two concurrent sessions through independently retained, media-generation-checked card readers; `--session-parallel N` changes that bound. QC reads metadata, authenticated frame evidence, and IMU counters. It does not read the full video merely to judge it; when old metadata omits dimensions, POT reads only the authenticated opening video chunk needed to parse the H.265 picture size. QC uses authenticated frame timestamps rather than the receiver's wall clock. A session must have at least 200 Hz IMU; exactly 200 Hz passes.

After preflight passes, start the upload:

```console
pot offload --device /dev/disk4
```

During a normal upload, every session must pass QC before any bytes from that session are sent. As soon as the first session passes, POT begins its upload while later sessions continue through QC. This keeps the card and network busy without weakening the per-session 200 Hz gate.

Use `--only` to upload named sessions:

```console
pot offload --device /dev/disk4 \
  --only S_20260819_120000 S_20260819_130000
```

### Choose what happens to the card

| Choice | Command | Result |
| --- | --- | --- |
| **Keep recordings** (default) | `pot offload --device /dev/disk4` | The cloud copy is verified and the card remains unchanged. |
| **Erase after upload** | `pot offload --device /dev/disk4 --erase-after-upload` | POT asks you to type `ERASE`, uploads and verifies first, then frees only those successfully uploaded sessions. |
| **Erase later** | `pot erase-recordings --device /dev/disk4` | POT rehashes the current card and reads back the exact existing cloud manifests before freeing any space. Missing or mismatched cloud data is not silently uploaded or erased. |

Add `--only SESSION_ID ...` to erase named sessions. For controlled unattended operation, add `--yes` to `--erase-after-upload`; otherwise the confirmation is mandatory.

> **Warning:** **Erase means logical filesystem deletion.** It frees recording space for reuse, but it is not a forensic or NAND-level secure erase. POT refuses to delete when upload verification, card identity, the ext4 journal, the session inventory, or the final filesystem check is unsafe. QC-failed and unselected sessions stay on the card. Verified erase is available on macOS and Linux; Windows remains read-only in this release.

### How your data is protected

- **On the card:** recordings remain encrypted and the card is opened read-only throughout QC and upload. An explicitly requested erase opens it for writing only after cloud verification succeeds.
- **During upload:** POT authenticates and decrypts each file in bounded memory and sends it over HTTPS. It never creates a local plaintext copy.
- **In the cloud:** recordings are stored as usable plaintext files inside the access-controlled bucket assigned to the partner. Anyone granted access to that bucket can read them.

POT never uploads the card's wrapped-key envelope. A large recording is deliberately read twice: the first authenticated pass calculates the plaintext SHA-256 that the cloud router binds to the multipart upload, and the second pass streams the payload while recalculating that digest. Small encrypted files reuse the exact bounded body already authenticated by the first pass. POT keeps other approved sessions moving while a large file is in its hash pass; it does not stage plaintext or weaken the large-file comparison to claim a faster number.

The production default is two active sessions per card, with up to four 16 MiB parts in flight for each uploading session. QC for later sessions, hashing, and uploads overlap through separate retained readers and cloud object keys. Every session still passes QC before any of its bytes upload, and one failed session is reported without cancelling healthy siblings. Use `--session-parallel 1` for conservative serial operation. `--parallel N` tunes multipart concurrency. If the operating system cannot retain the requested readers, POT reports the smaller effective window instead of sharing a seek cursor. Multipart workers reuse healthy HTTPS connections, and native media-generation checks bracket each complete source stream instead of interrupting the part-refill loop. One forward-only producer authenticates, decrypts, and hashes the source while keeping one additional part prefetched; HTTP workers never share or seek its cursor. Dead cloud sockets time out after 90 seconds instead of ten minutes. POT prints a liveness line every 15 seconds while waiting, names every retry and backoff, and reports source MiB/s, acknowledged MiB/s, active HTTP parts, and the maximum window reached. A durable journal resumes only parts the service already acknowledged. It does not trust an old digest as proof of the currently inserted card; a rerun rereads the source, which prevents a clone card or repeated session name from being mistaken for a completed recording. POT verifies each remote object's plaintext size and SHA-256, then uploads and exactly reads back the session manifest last. Without an erase option the card remains unchanged. With one, any QC or upload failure stops before deletion begins.

To offload every readable receiver card currently attached with the two-session-per-card default, select that scope explicitly:

```console
pot offload --all-cards --card-parallel 3
```

For a qualified high-throughput station, all three bounds are independent:

```console
pot offload --all-cards \
  --card-parallel 3 \
  --session-parallel 2 \
  --parallel 8
```

`--card-parallel` controls cards, `--session-parallel` controls work within each card, and `--parallel` controls multipart requests within each uploading session. POT never infers `--all-cards`. Every card keeps its own device lock and resume journal. Legacy clone cards that report the same receiver identity cannot write that shared cloud namespace concurrently; POT refuses one instead of risking an overwrite. If the same remote session name already contains different bytes, POT also refuses to replace it. Do not remove a card while its command is active.

### Memory and local disk sizing

**Before starting, keep at least 500 MiB of local disk free** for the standalone runtime, release updates, logs, and durable resume journals. Cloud offload does not stage recordings on the computer, so a 90 GB card does not require 90 GB of free local disk. The journals contain hashes and acknowledged part metadata, not recording payloads.

The upper bound for multipart payload buffers is:

```console
cards × sessions per card × (HTTP parts + 1 prefetched part) × 16 MiB
```

| Profile | Payload-buffer ceiling | Practical RAM guidance |
| --- | --- | --- |
| `1 card × 2 sessions × 4 parts` (default) | 160 MiB | Keep at least 1 GiB available beyond the operating system. |
| `3 cards × 2 sessions × 4 parts` (default session/part windows) | 480 MiB | Keep at least 2 GiB available beyond the operating system. |
| `3 cards × 2 sessions × 8 parts` (qualified high-throughput profile) | 864 MiB | Keep at least 3 GiB available; qualify reader, CPU, and uplink behavior first. |

These figures cover payload bodies. Python, filesystem helpers, TLS, QC, and the operating system need additional memory. Increasing concurrency cannot exceed the station's uplink; use the smallest values that keep the link busy and remain stable.

`pot setup` separately calculates the exact cache space needed for the selected compressed and expanded golden image and refuses before the download if the workstation is short. `pot export --preflight` requires destination free space equal to the selected plaintext payloads plus 5% headroom.

Older standalone upload scripts that ask for a local fleet key or receiver token are not the supported customer workflow. Use `pot offload`.

## 8. Export to a local folder or external SSD

Use `pot export` when recording data must stay off the OpenRobot cloud. The card remains read-only. POT still needs Internet access: the partner code authorizes a short Worker request for each selected session key, while the fleet private key remains inside Cloudflare. No fleet key, receiver token, or storage credential is installed on the operator's computer.

POT accepts an internal local disk or directly attached external SSD as the destination. It rejects network shares, destinations without one local block-device backing, and any folder backed by the source card before requesting a session key. The folder supplied to `--to` must already exist, so a disconnected SSD path cannot be silently created on the workstation's internal disk.

> **Warning:** **The exported files are plaintext.** Protect the destination Mac or SSD as you would any usable footage. POT writes no plaintext temporary copy anywhere else and never exports `key-envelope.json`. Do not choose an iCloud Drive, Dropbox, OneDrive, or other OS-synced folder when the recording must remain local; POT makes no cloud upload, but a separate sync application still can.

### Operator tutorial

1. Stop the receiver cleanly, power it down, then remove its SD card.
2. Connect the card reader and, if needed, the destination SSD. Mount the SSD and create or select the export folder first, for example `/Volumes/Footage` on macOS or `/media/operator/Footage` on Linux, or `E:\Footage` on Windows.
3. Find the exact card device and sessions:

   ```console
   pot scan --device /dev/disk4
   ```

   On Linux, the same device may look like `/dev/sdb`. On Windows, use the `\\.\PhysicalDriveN` name printed by POT.
4. Run the complete read-only preflight. This checks partner authorization, authenticated QC (including IMU at or above 200 Hz), destination space, and that the destination is not on the source card:

   ```console
   pot export --device /dev/disk4 \
     --to /Volumes/Footage \
     --preflight
   ```
5. Export all passing sessions:

   ```console
   pot export --device /dev/disk4 \
     --to /Volumes/Footage
   ```

   To select sessions, add `--only S_20260819_120000 S_20260819_130000`.
6. Wait for **Export verified**. POT places output under `DESTINATION/RECEIVER_ID/SESSION_ID` and reports the verified session, file, and byte totals. Each session contains `pot-export-manifest.json` and standard `SHA256SUMS`. You can independently check one session on macOS:

   ```console
   cd /Volumes/Footage/RECEIVER_ID/SESSION_ID
   shasum -a 256 -c SHA256SUMS
   ```

   On Linux, use `sha256sum -c SHA256SUMS`. On Windows, POT's own readback is authoritative; individual files can also be checked with `Get-FileHash -Algorithm SHA256 FILE`.
7. After the command has finished, eject the card before physically removing it. On macOS use Finder or `diskutil eject /dev/disk4`. On Linux use the desktop eject action or `udisksctl power-off -b /dev/sdb`. On Windows use **Safely Remove Hardware**.

POT streams authenticated plaintext directly to a private staging directory, fsyncs every file, rereads and SHA-256 verifies it, writes the manifest last, then atomically publishes the session directory. A failed or interrupted session is never presented as a verified export. No recording data is uploaded to cloud storage, and this command never deletes from the card.

## 9. Headless macOS over SSH

Setup and manufacturing are supported over SSH. Allocate a terminal for the interactive confirmation:

```console
ssh -t operator@manufacturing-mac
pot doctor
pot setup raspberry-pi-3b-plus
```

`--yes` skips the `MAKE` prompt and is intended only after an exact dry run in controlled automation.

If Finder or `loginwindow` dissents from the normal whole-disk unmount, POT retries once with macOS's forced unmount. If macOS still refuses, keep the card physically inserted, eject its mounted volumes from the logged-in graphical session, and rerun. POT will not write until unmount succeeds.

Cloud QC and upload are read-only and open only the ext4 recording partition, so they do not unmount the Finder-visible boot volume or need the manufacturing forced-unmount path. A requested post-upload erase is a later, explicit write transaction.

## 10. Linux notes

- The installer selects x86_64 or ARM64 automatically and bundles the ext4 helpers used by supported receiver images.
- Commands that open a raw block device request `sudo`; read-only inventory commands normally do not.
- Copy device names from `pot readers` or `pot cards`. Never substitute a partition such as `/dev/sdb1` for the whole device `/dev/sdb`.
- Linux normally reports READY with an instruction to eject before removal, because safe path-based auto-eject is deliberately avoided.
- After a concurrent image write, POT waits for the exact new partition to settle in UDisks before mounting it for settings. A bounded timeout remains fail-closed and never redirects provisioning to another partition.
- Radxa Zero 3W ext4-only manufacturing is fail-closed on unsupported hosts; `pot doctor` reports missing capabilities before a write.

## 11. Windows notes

> **Note:** Windows is a native standalone CLI. It does not require the desktop app, Python, WSL, or an ext4 filesystem driver.

```console
# Run these from Administrator PowerShell, using POT's printed device name
pot scan --device \\.\PhysicalDrive3
pot offload --device \\.\PhysicalDrive3 --preflight
pot offload --device \\.\PhysicalDrive3
pot export --device \\.\PhysicalDrive3 --to E:\Footage
```

- Run raw-card commands from a PowerShell window opened with **Run as administrator**.
- Whole disks are named like `\\.\PhysicalDrive3`. Copy the exact name from `pot cards` or `pot readers`; never infer it from a drive letter.
- Reader approval uses the USB device's physical PnP location path, not a vendor serial that may be duplicated across a tray. Moving a reader to a different port requires approval again.
- Before any write, POT binds the retained handle to its exact Windows storage device/partition number and media-change counter. A driver that cannot provide those checks is rejected by `pot doctor`.
- Cloud offload reads ext4 directly through POT's bundled read-only parser. Do not install an ext4 filesystem driver, do not attach the card to WSL, and always cancel Windows' offer to format the Linux partition.
- Current FAT-config golden images can be manufactured on Windows. Radxa Zero 3W's ext4-only provisioning remains fail-closed before erase; use macOS or Linux for that board.
- `pot offload`, `pot export`, inventory, QC, and current FAT-config golden manufacturing are supported. Recording erase, journal recovery, full e2fsck, and Zero 3W ext4-only manufacturing remain deliberately unavailable on Windows.

## 12. Check and recover recording cards

```console
# Read-only filesystem consistency check
pot check --device /dev/disk4

# Replay an unclean journal; this writes to the card
pot recover --device /dev/disk4
```

Run `recover` only when POT reports that recovery is needed. It is not a substitute for remaking a manufacturing card marked REMAKE_REQUIRED. On Windows, `pot check` reports read-only superblock health but does not claim a full e2fsck, and `pot recover` refuses before opening the card for writing.

## 13. Troubleshooting

| Message or symptom | What to do |
| --- | --- |
| Station not ready | Run `pot doctor`. If settings or credentials are missing, rerun `pot setup`. |
| No card in an approved reader | Run `pot readers`. Insert a card in the intended slot, then use `pot setup --reselect-readers` if the reader moved. |
| No unique stable reader-slot identity | Keep each reader on a distinct physical USB path. On macOS, verify each slot has a distinct `locationID`; reconnect and reapprove the slots if hub topology changed. On Windows, keep each reader on a distinct PnP location path and rerun setup after moving ports. |
| At least one volume could not be unmounted | Close Terminal or Finder windows using the mounted volume. If the reported dissenter is `loginwindow`, eject the volume in the logged-in session while leaving the card inserted, then rerun. |
| An agent asks for a receiver login password or Tailscale key | Do not continue that workflow. Use `pot setup BOARD`; it collects missing station settings itself. The receiver login is fixed to `operator/operator`; POT retrieves Tailnet enrollment from Cloudflare. Do not hand-create `stereorx-image.conf`. |
| More than one card matches | Pass `--device` to inspection or offload commands, or `--only-device` to `pot setup`. |
| Cloud route expired or was revoked | Keep the card inserted and rerun. POT live-verifies the configured partner and refreshes the receiver-bound route once automatically. It never asks the operator to paste the fleet key. |
| QC found no deliverable sessions | Nothing was uploaded and the card was not changed. Read the per-session measurement. An IMU rate below 200 Hz fails; 200 Hz or higher clears the IMU requirement, but the other frame, duration, gap, and resolution checks must still pass. |
| QC reports a `key-envelope.json` collision or `captured NonexNone` | Update to POT 0.5.3 or newer and rerun preflight. The envelope is verified as source-only control material and is not uploaded. When old metadata omits dimensions, POT reads the H.265 SPS from the authenticated opening video chunk. |
| Card appears blank, unknown, or foreign | Assume it contains data until independently verified. Do not run `pot setup BOARD` on it merely because POT cannot recognize the filesystem. |
| REMAKE_REQUIRED | Do not ship or patch the card manually. Start a complete `pot setup BOARD` run. |

### Diagnostics and privacy

POT sends bounded command health logs and unexpected crash reports to OpenRobot's Sentry error monitoring. This is best-effort diagnostics only: a network or Sentry failure never changes a CLI result or card operation.

Reports include only the POT release, fixed command name, operating-system family, CPU architecture, bundle/source runtime, exit status and duration, a random Sentry trace correlation ID, plus the exception type and sanitized code location for a crash. The random value is not a host, operator, card, receiver, or recording identifier. Exception messages are replaced before transmission.

POT does **not** send command arguments, environment values, host or user identity, IP or email addresses, device names, reader/card or receiver IDs, partner codes, session names, recording names/paths/content or hashes, Wi-Fi details, Tailnet/fleet keys, routing/upload credentials, or local variables. Performance tracing and profiling are disabled.

To opt out for a command, set `POT_TELEMETRY=0`:

```powershell
# macOS / Linux
POT_TELEMETRY=0 pot offload --device /dev/disk4

# Windows PowerShell
$env:POT_TELEMETRY = "0"
pot offload --device \\.\PhysicalDrive3
```

## 14. Operator command reference

| Command | Purpose |
| --- | --- |
| `pot setup` | Configure partner, Wi-Fi, concurrency, and approved readers. Receiver login and Tailnet issuance are automatic. |
| `pot readers` | Show approved, available, and rejected reader slots. |
| `pot doctor` | Check station settings, partner, Tailnet broker, helpers, raw access, and media generation. |
| `pot cards` | Show every detected card; add `--watch` to follow insertion and removal. |
| `pot scan` | List recording sessions on one card. |
| `pot setup BOARD` | Preflight, flash, verify, provision, and journal approved cards. |
| `pot status` | Show the latest durable manufacturing job; add `--watch` for live changes. |
| `pot offload` | QC and resumably upload recording sessions directly from a card that remains read-only during transfer. |
| `pot export` | QC, decrypt, atomically write, and SHA-256 verify selected sessions in a local folder or external SSD without cloud upload. |
| `pot erase-recordings` | Reverify existing cloud copies, then logically delete selected recording sessions from a macOS/Linux card. |
| `pot check` | Run a read-only filesystem consistency check. |
| `pot recover` | Replay an unclean recording-card journal. |
| `pot images` | List published receiver images. |
| `pot selfupdate` | Check whether a newer POT CLI is published. |
| `pot COMMAND --help` | Show every option for a command. |

Most commands accept the global `--json` flag for machine-readable output. Keep destructive confirmation enabled unless the caller has already performed and recorded an exact dry run.

## Update

```console
# macOS / Linux
pot selfupdate
curl -fsSL https://pot.theopenrobot.com/cli | sh

# Windows PowerShell (unsigned preview; confirm the installer warning)
pot selfupdate
irm https://pot.theopenrobot.com/cli.ps1 | iex
```

The stable installer selects and checksum-verifies the current package for this host. It can be rerun safely.

[Back to top](#top) · standalone CLI · macOS/Linux 0.5.17 beta · Windows 0.5.4 unsigned preview

Never remove or insert a card while POT reports ERASING, WRITING, VERIFYING, or PROVISIONING.

```json
{
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "about": {
    "@type": "SoftwareApplication",
    "applicationCategory": "DeveloperApplication",
    "name": "OpenRobot POT CLI",
    "operatingSystem": "macOS, Linux, Windows"
  },
  "dateModified": "2026-09-01",
  "description": "Install and operate the standalone OpenRobot POT CLI on macOS, Linux, and Windows.",
  "headline": "OpenRobot POT CLI install and operator guide",
  "inLanguage": "en",
  "url": "https://pot.theopenrobot.com/"
}
```
