# Fi-Wi framework — command-line reference

This document lists how to invoke the Fi-Wi CLI from a shell. For architecture, see [fiwi-design.md](fiwi-design.md). For library-style automation, see [fiwi-test-authoring.md](fiwi-test-authoring.md).

## How to run

```text
python3 /path/to/fiwi.py [options] <command> [arguments…]
```

## Global options

| Option / env | Meaning |
|--------------|---------|
| `--async` (CLI) | Sets `FIWI_REMOTE_DEFER=1` before parsing the rest of argv. Deferred remote operations return handles or `asyncio.Task`s internally so work can overlap (for example during `panel calibrate`) without starting Python threads. |
| `FIWI_REMOTE_DEFER=1` | Same idea as `--async`; can be set in the environment or `remote_ssh.env`. |
| `fiwi.py --ssh user@host <command>…` | Runs that command on the remote via SSH using `FIWI_REMOTE_PYTHON` and `FIWI_REMOTE_SCRIPT` on the **remote** machine. No local BrainStem import for that invocation. |

## Environment and files (SSH / remote)

Copy `remote_ssh.env.example` to `remote_ssh.env` next to `fiwi.py` on the machine **from which you SSH** (paths inside the file refer to the **remote** host).

| Variable | Purpose |
|----------|---------|
| `FIWI_REMOTE_PYTHON` | Remote interpreter (default `python3`). |
| `FIWI_REMOTE_SCRIPT` | Remote `fiwi.py` path. |
| `FIWI_SSH_BIN` | SSH client binary (default `ssh`). |
| `FIWI_SSH_OPTS` | Extra SSH client arguments (for example `-o BatchMode=yes`). |
| `FIWI_CALIBRATE_REMOTES` | Comma-separated `user@host` list for hybrid `panel calibrate` without repeating `--ssh`. |
| `FIWI_REMOTE_DEFER` | Enable deferred remote subprocess overlap (see above). |

`fiber_map.json` may also carry `calibrate_remotes` for the same hybrid idea.

## Commands (summary)

Default command if omitted: **`status`** (with default target `all`).

| Command | Description |
|---------|-------------|
| `discover` | List hubs (serial, port count); no per-port power I/O. |
| `status [target]` | Port status; target examples: `all`, `1.3`, `all.2`. |
| `on \| off [target]` | Power downstream. |
| `reboot [target]` | Reboot downstream; skips empty ports. |
| `reboot-force [target]` | Reboot; does not skip empty ports. |
| `setup` | Udev setup helper. |
| `verify` | Verification helper. |
| `calibrate-ports-json` | Prints JSON `[[hub, port], …]` for downstream calibration ordering (used by tools and hybrid calibrate). |
| `lsusb-lines-json` | JSON lines from `lsusb` for local snapshot. |
| `wlan-info-json` | JSON wireless / NIC snapshot (sysfs, `lspci`, `iw` where relevant). |
| `power fiber-port <id> on\|off` | Power by fiber map id; SSH-forwarded if the map routes that id to another host. |
| `fiber status` | Table of fiber ports, routes, power, saved previews. |
| `fiber chip <fiber_port_id> [save]` | Local `lsusb` probe; **not** used for SSH-mapped PCIe/fiber paths (see stderr message if misused). |
| `panel status` | Patch panel positions `1…N` (`N` from `patch_panel.slots`, default 24). |
| `panel on\|off <n>` | Power panel position `n`. |
| `panel reboot <n>` | Reboot with `skip_empty=True`. |
| `panel reboot-force <n>` | Reboot without skipping empty. |
| `panel calibrate [merge] [<N>] [--ssh user@host]…` | Interactive calibration: set panel size, walk hubs, update `fiber_map.json`. Optional **`merge`**, limit **`N`**, and one or more **`--ssh user@host`** for remote legs. Order: local downstream ports, then each remote’s ports. |
| `help` | Longer built-in help text (also `-h` / `--help`). |

## Fiber map routing (CLI behavior)

Entries under `fiber_ports` may set routing to another machine, for example:

- `"ssh": "user@host"`, or
- `"remote": "…"`, or
- `"host"` + `"user"`.

On the SSH **destination**, the same fiber id should be **local** (no `ssh` field) so commands are not forwarded again.

Optional **`pcie`** objects hold switch / SFP / bus metadata; calibrate can fill these via numeric prompts.

## Exit codes

The CLI generally returns **0** on success and **non-zero** on usage errors or tool failures. **`fiber chip`** on an SSH-mapped port returns **2** with an explanatory stderr message (by design).
