Skip to content

Pybricks Tools

Run Python programs on your Pybricks hub from your computer — from the command line, or from your own Python code.

Status

Beta. Commands and APIs may still change before 1.0.0.

Install

The recommended way is with uv. If you do not have it, uv's installation page has the ways to get it.

uv tool install pybricks-cli

That gives you the pb command. It is an ordinary Python package, so pipx or pip install into a virtual environment work too.

Run a program

Switch your hub on, then:

pb connect          # find a hub and connect to it
pb run demo.py      # compile the script, send it, and run it

pb run stays with the program: what it prints appears as it prints it, and what you type goes to the hub, so input() works and Ctrl+C interrupts.

Press Esc Esc to stop the program — one key, twice, so it is there when a robot is heading for the edge of the table. Press Ctrl+] Q to leave, or Ctrl+] H for the rest.

pb connect only needs doing once. Later commands reuse the connection, so pb run is quick to repeat while you are working on a program — and the hub stays awake, instead of switching itself off after a few minutes the way one with nothing connected to it does.

pb run demo.py      # again, without reconnecting

Everyday commands

Command What it does
pb connect Connect to a hub and keep it connected
pb run SCRIPT Compile a script, send it, and run it
pb run -c CODE Run a line or two of Python without a file
pb repl Talk to the hub's interpreter, a line at a time

The rest — stopping a program, sending one without running it, seeing which hubs are connected — is on the Commands page, along with every option each one takes.

You never have to run pb scan: pb connect does its own looking. It is there for when you want to know what is out there without connecting to any of it. It fills its table as hubs are heard rather than when it finishes, so a hub appears the moment you switch it on. Each row says what kind of hub it is and how strong its signal is:

  Name           Type           Signal
  Bumblebee      Inventor hub     ▁▃▅▇
  Rover          City hub         ▁▃▅·

A hub is named when its firmware is installed, and a hub flashed without a name being chosen answers to Pybricks Hub like every other one. So the two columns are what tell those apart: which kind of hub it is, and whether it is on the desk or through a wall. Both are known without connecting to anything.

pb check needs no hub at all — it is the compiler on its own, so it will tell you whether a program has a mistake in it before you go and switch anything on:

pb check demo.py

To pick a hub from that list instead of reading it, use pb connect --scan. Up and Down move the selection and Enter connects. There is no time limit, so you can switch the hub on while it is watching, and Ctrl+C gives up without connecting to anything.

With more than one hub connected, name the one you mean with --hub, which every command takes:

pb run demo.py --hub "Rover"

If it is always the same hub, choose it once instead of saying so every time:

pb use                      # choose from the hubs connected and nearby
pb use --hub "Rover"        # or name it

What is remembered is the hub's name, so the choice survives switching the hub off and on, and outlives the background service; every shell sees the same one. The hub does not have to be connected, or even switched on, so the hub a project belongs to can be chosen before any of it is plugged in. pb use --clear forgets it again.

Every command takes -v for more detail, and -vv or -vvv when something is going wrong and you want to see why.

From Python

The same things are available as a library, so you can drive a hub from your own program:

from pathlib import Path

import anyio
import pb_client


async def main() -> None:
    async with pb_client.connect() as pb:
        hub = await pb.connect_hub(name="Rover")
        print(f"connected to {hub.name}, firmware {hub.firmware}")

        program = await pb_client.compile_script(Path("demo.py"))
        reason = await pb.run_program(program)
        print(f"program {reason}")


anyio.run(main)

It is async throughout, and everything it opens is closed for you when the async with block ends — including the hub, if you were the one who connected it. The API reference has the rest.

When something goes wrong

pb tries to say what happened in one line and, where there is one, what to do about it:

$ pb run demo.py
No hub found.
Switch the hub on and press its button so that its light flashes.

If you ever see a traceback instead, that is a bug in pb rather than something you did — please report it at pybricks/support, including the traceback and what you were doing.

Where to next

  • The command line — every command, every option, and where an option comes from when you do not type it.
  • API reference — the library, generated from the code.
  • How it works — what keeps a hub connected between commands, and why the tools are split the way they are.
  • Contributing — getting set up, and the rules the code follows.

Source code

The source is on GitHub at pybricks/pybricks-tools, under the MIT licence.

Bugs and questions go to pybricks/support, which is where they are collected for every Pybricks project — ask a question in its discussions, or report a bug in its issues.