--- myst: html_meta: description: "Command-line tools for working with instro" --- # CLI {.lead} Command-line tools for working with instro `instro` ships a command-line interface for inspecting and discovering instruments on your bench. ## Running the CLI The CLI comes with the `instro` package (see [Installation](/installation.md)). In a project that has `instro` installed, run: ```bash uv run instro discover ``` For regular use, put `instro` on your PATH instead so you can call it from anywhere: ```bash uv tool install instro instro discover ``` ## Usage ### instro --version Prints version information. ```bash instro --version # prints version information ``` ### instro discover Scans all available VISA resources and serial ports, queries each instrument for its identity, and prints a summary table. To force a specific VISA backend, pass `--backend`: ```bash instro discover --backend=@py instro discover --backend "@ivi" ``` :::{note} The `@ivi` backend finds an available IVI-compliant backend on your system e.g. NI-VISA or Keysight IO. `@ivi` is more reliable for USB and GPIB instruments. The `@py` backend (`pyvisa-py`) is a pure-Python fallback that works without NI-VISA installed but may not detect all instruments. ::: ### Output Before scanning, the command prints which VISA backend is active (`@ivi`, or `@py` when no IVI VISA is installed). On the `@py` backend it also lists any interfaces the scan cannot cover — for example `GPIB: unavailable — gpib_ctypes is installed but could not locate the gpib library (install NI-488.2 or linux-gpib)` — so you know when an empty result reflects a missing library rather than an empty bench. These notes are informational; the scan still runs and the command exits 0. The command groups results into up to three tables. **Recognized devices** — instruments with a known driver. The table shows the VISA resource address, instrument category, and the `instro` driver class to use. **Serial devices** — serial ports detected by the OS. These are listed separately because serial instruments require manual configuration; `instro discover` cannot query them automatically. **Unrecognized devices** — instruments that responded to `*IDN?` but did not match any known driver. The raw IDN response is shown so you can identify the device. If no devices are found at all, the command prints a single error panel; on the `@py` backend the panel repeats any unavailable interfaces. ### Using a recognized device Pass the resource address from the **Recognized devices** table directly to the driver's constructor: ```python from instro.psu.drivers.bk_9115 import BK9115 from instro.psu import InstroPSU psu = InstroPSU(name="psu", driver=BK9115("USB0::0x15EF::0x0099::INSTR"), num_channels=1) psu.open() ``` ### Unrecognized devices If your instrument appears in the **Unrecognized devices** table, `instro` does not yet have a driver for it. See [Custom instruments](/library/custom-instruments.md) for how to author one, or [instro-contrib](/library/contrib.md) to check for community-contributed drivers. ### Discovering programmatically `instro discover` is a thin wrapper around `scan_visa_resources`, which is also available directly from `instro.lib` for use in your own scripts: ```python from instro.lib import scan_visa_resources result = scan_visa_resources() for info in result.instruments: print(info.resource, info.category, info.driver_name) for unrecognized in result.unrecognized: print(unrecognized.resource, unrecognized.idn) for error in result.errors: print(error.resource, error.hint or error.message) ``` `scan_visa_resources` accepts the same `backend` the CLI's `--backend` flag does, plus an optional `timeout` (seconds per instrument query, default `2`) that the CLI doesn't currently expose. It returns a `VisaScanResult` with `instruments` (`DiscoveredInstrument`), `unrecognized` (`VisaUnrecognizedInstrument`), and `errors` (`VisaScanError`) — the same data the CLI renders into the tables above. Each `DiscoveredInstrument` can build what you need next, so a script never re-derives the driver from the resource string: ```python from instro.psu import InstroPSU psu_info = next(i for i in result.instruments if i.category == "psu") # a ready-to-open driver (VisaConfig with the backend the scan was asked for) psu = InstroPSU(name="psu", driver=psu_info.make_driver(), num_channels=psu_info.num_channels) # or the ``driver`` block of a JSON config, for InstroPSU(config=...) driver_block = psu_info.config_block() ``` `visa_config()` returns the `VisaConfig` on its own, and `driver_class()` the driver class, when you want to construct the driver yourself.