Skip to content

The command line

pb is one command with a verb after it:

pb run demo.py
pb repl
pb service log -f

Every command that acts on a hub takes --hub NAME to say which one, and every command takes -v for more detail — -vv and -vvv when something is going wrong and you want to see why. The Commands page lists them all, generated from the tool itself, so it says exactly what your copy accepts.

Where an option comes from

Most of the time you type it. When you do not, pb looks in three more places before the command decides for itself. Highest wins:

Where Good for
1 What you type This one command
2 The environment — PB_HUB and friends One shell, or one CI job
3 The project file — [tool.pb] in pyproject.toml Everyone who clones the project
4 The hub chosen with pb use You, everywhere, until you change it
5 The only hub connected Not having to think about it

A project beats a standing preference because it is the more specific statement: whoever clones a robot project should get that robot's hub without having to know that you once ran pb use.

Running from somewhere else

-C runs a command as if you were in another directory, the way git -C does:

pb -C robot-a run src/robot/demo.py

Point it at the directory holding a project's pyproject.toml, or at the top of your source when there is no project file. It settles three things at once: which project's settings apply, what a relative path means, and where a program's imports are looked for.

It earns its place when one repository holds more than one robot:

robots/
  robot-a/pyproject.toml     [tool.pb] hub = "Bumblebee"
  robot-b/pyproject.toml     [tool.pb] hub = "Rover"

From the top of that tree, neither project's settings apply to anything, and from inside robot-b they are robot-b's — which is the wrong hub, not merely a missing one. pb -C robot-a says which you mean, and it means the same thing from any shell.

What a command exits with

Code Meaning
0 It worked
1 Something on this computer went wrong
3 The hub, or the program on it, was the problem
4 No hub is connected
130 Interrupted

A program that ends in an unhandled exception exits 3, and one interrupted with Ctrl+C exits 130, which is what CPython does.

Where output goes

Data goes to stdout and everything else to stderr, so a command can always be piped:

pb scan > hubs.txt          # the hubs, and nothing else
pb service log > problem.txt
pb run demo.py | tee run.log

Down a pipe the tables become tab-separated fields and nothing is coloured, so cut and grep work on them. Progress, spinners, prompts and log lines are on stderr and stay out of the way.