Skip to main content

labgrid-tui

A terminal dashboard for labgrid labs. It connects to a labgrid coordinator over gRPC, shows every place and resource live as it changes, and turns each one into the exact labgrid-client command line to copy or edit. It has no state or protocol of its own: a discoverability lens over what the coordinator already exposes and what labgrid-client already does.

labgrid-tui is an independent, third-party project. It is not affiliated with or endorsed by the labgrid project or its maintainers.

At a glance

  • Live fleet view: places, resources, holders and reservations from the coordinator's own event stream; no polling.
  • Every action is a real command line: console, power, SSH, file transfer, SD-mux, video, acquire, release, shown as the exact labgrid-client invocation for that bench; what you cannot do right now is greyed with the reason. r gets a bench in one line, queueing when it is busy.
  • Several coordinators: named entries, switched at runtime (shift+p) or from the CLI.
  • Shareable command packs: a team's recipes in a small TOML file, placeholders filled in per bench, copy-only by design.
  • Reservations and an activity log: queue for a busy bench, see the allocation happen, cancel with the token filled in.
  • Keyboard-first, read-only: Vim keys, works in a narrow tmux pane, never mutates anything over gRPC, needs no credentials, manages no places.

Install

uv tool install labgrid-tui
# or: uv tool install git+https://github.com/onurcelep/labgrid-tui

Python 3.11+. labgrid-client on PATH is optional: commands are copied either way and run in place only when it is present.

Usage

labgrid-tui tour             # guided walkthrough on fake data, no coordinator needed
labgrid-tui config init      # optional: persist a coordinator address
labgrid-tui                  # or: labgrid-tui -x coordinator.example.org:20408

Press ? in the dashboard for every key, the table legend and the operations reference; the in-app help is the only copy of that material.

Configuration

Coordinator address, in order: -x, then LG_COORDINATOR, then the active named coordinator, then coordinator in config.toml, then 127.0.0.1:20408. A bare host gets the default port. All files live in ~/.config/labgrid-tui/ ($XDG_CONFIG_HOME honoured); none needs to exist.

config.toml (hand-edited; labgrid-tui config init writes a commented template, config show prints every resolved value and its source):

coordinator = "coordinator.example.org:20408"   # or a named coordinator
prefix = "labgrid-client -x coordinator.example.org:20408"   # optional

[capabilities]
MyCustomResource = "power"        # resource class -> resource chip

[[commands]]                      # extra labgrid-client entries
category = "Custom"
label = "Ping DUT"
suffix = "ssh -- ping -c1 10.0.0.1"
class = "NetworkService"          # omit for a place-level entry

Named coordinators live in coordinators.toml, written by the tool: shift+p in the TUI (enter switch, n new, e edit, x delete) or labgrid-tui coordinator list|add|use|remove|show|edit. -x and coordinator accept a name from it as well as an address.

LG_PROXY is not supported: if it is set, labgrid-tui refuses to start. UI state (panels, theme) persists to ~/.local/state/labgrid-tui/ui.toml.

Bring your own lab

The six benches in labgrid-tui tour are a plausible real lab, written out in examples/lab/: exporter.yaml declares the serial, power and SSH resources for labgrid-exporter, and places.sh runs the labgrid-client calls that create the matching places and tag them.

A place carries a free-form tags dict (labgrid-client -p NAME set-tags board=imx8 env=dev site=lab1) and labgrid-tui shows it in one Tags column of key=value pairs. Each key gets a fixed slot, sized over the whole fleet, so the same key sits at the same column on every row; a pair every place shares is dimmed and is the first to go when the terminal runs out of room. Tag with whatever your lab sorts by; there is no fixed schema.

Command packs

A pack is a TOML file of copy-only recipes. Register it explicitly; nothing is discovered on its own:

labgrid-tui pack add PATH|URL     # also: list, show, update, remove

A path is re-read on every start; an HTTPS URL is cached and refreshed by pack update. Each pack is its own tab in the command overlay (c) and its own palette group; enter copies, the TUI never executes a pack entry.

[pack]
name = "robot"

[[commands]]
label = "Smoke tests on this bench"
command = "robot -v PLACE:{place} -v DUT_IP:{res.NetworkService.address} tests/smoke"
requires = ["res.NetworkService"]

Placeholders: {place}, {coordinator}, {prefix}, {token} (your reservation for this place), {tag.KEY}, {res.CLASS.PARAM} (first matched resource of that class; PARAM may be name). requires items: res.CLASS, tag.KEY, held. An unmet requirement or an unresolvable placeholder greys the entry with the reason instead of failing. A full example ships in examples/robot.toml.

Extending

Plugins are Python modules registered under the labgrid_tui.plugins entry-point group that may define capabilities: dict[str, str] (resource class to capability) and commands: dict[str, tuple[CommandTemplate, ...]] (resource class to extra entries). A plugin that raises while loading is skipped with a warning.

Building a larger shell on top (authentication, another execution backend, extra status): every widget and screen takes its data through constructor arguments, LabgridTuiApp is subclassable, and every action is dispatched through one two-method protocol:

class ActionRunner(Protocol):
    def run(self, entry: CommandEntry) -> None: ...
    def copy(self, entry: CommandEntry) -> None: ...

Hand the widgets your own runner and the validity engine (which commands are offered, and why not) stays shared. Extra status-bar segments are Callable[[], str | None] providers on extra_status_segments. Unknown keys in coordinators.toml entries survive edits, so a shell can store its own per-coordinator data there. This surface may change before 1.0.

Development

See CONTRIBUTING.md for the gate to run before opening a PR.

uv sync
uv run pre-commit install      # ruff check and format on every commit
uv run ruff check src tests
uv run mypy src
uv run pytest                  # unit and UI tests against a fake coordinator
  • tests/model and tests/coordinator: pure logic and the gRPC layer.
  • tests/ui: widgets and screens, driven through Textual's pilot.
  • tests/integration: a real coordinator, excluded by default. Start one with docker run -d -p 20408:20408 labgrid/coordinator and run uv run pytest -m integration (LABGRID_TUI_TEST_COORDINATOR points elsewhere).
  • scripts/generate-stubs.sh regenerates the gRPC stubs from the vendored proto.

Release: tag vX.Y.Z and push the tag. The version is derived from the tag at build time, and the publish workflow uploads to PyPI through trusted publishing.

License

Apache-2.0. Copyright 2026 Onur Celep. The package metadata declares Apache-2.0 AND LGPL-2.1-or-later because of the vendored labgrid file below.

labgrid-tui does not include or import the labgrid Python package. It contains an unmodified copy of labgrid's coordinator protocol definition (labgrid-coordinator.proto, LGPL-2.1-or-later, licence text in LICENSE.labgrid) and gRPC stubs generated from it; it talks to a labgrid coordinator over the network and runs labgrid-client as a separate process.

Release files for labgrid-tui 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for labgrid-tui 0.2.1
File Size Uploaded
labgrid_tui-0.2.1.tar.gz 201.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for labgrid-tui 0.2.1
File Interpreter ABI Platform
labgrid_tui-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 352.1 kB

Release files / labgrid_tui-0.2.1.tar.gz

Download URL labgrid_tui-0.2.1.tar.gz
Size 201.7 kB
Tags Source
SHA-256 checksum
How to use checksums
5a2da7ef9c6a0e03a08b9dcc9a8aebb504e1e007b33e47cff16c154fecb7a4c4
BLAKE2b-256 checksum
How to use checksums
74542a9de55ad00033504326d0f4188a6cc8aceb88a7416d686e7787f24a6015
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / labgrid_tui-0.2.1-py3-none-any.whl

Download URL labgrid_tui-0.2.1-py3-none-any.whl
Size 150.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5359b3c8d6dc83c7d2e760ac619add14407a364c2e8331e1e44c81108919d148
BLAKE2b-256 checksum
How to use checksums
d239211b38a16de7d56449a9ab76b937d711c4f6f1b301d06b540d422b9a5281
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page