The project file¶
A project can name the hub it belongs to, so that everybody who clones it gets
the right one without having to remember a flag. Put it in the project's
pyproject.toml:
[tool.pb]
hub = "Bumblebee"
Every command run anywhere inside that project acts on that hub. pb looks for
the nearest pyproject.toml at or above the directory you are in, so it does
not matter how deep in the tree you are working, and
-C is how you point at a different one.
A pyproject.toml with no [tool.pb] in it is stepped over rather than
stopping the search. So a repository holding several projects can name a hub
once at the top and override it where it matters:
robots/pyproject.toml [tool.pb] hub = "Bumblebee"
robots/robot-a/pyproject.toml a package, nothing about pb -> Bumblebee
robots/robot-b/pyproject.toml [tool.pb] hub = "Rover" -> Rover
It beats the hub chosen with pb use, because a project is the more specific
statement, and it loses to PB_HUB and to anything you type. Inside a project
that names a hub, pb use on its own pins that hub rather than offering a list
— the hub is no longer missing, so there is nothing to choose. pb use --clear
first if you want the list.
What the table understands¶
| Key | Meaning |
|---|---|
hub |
The name of the hub this project's commands act on |
transport |
How to reach it — usb or ble |
transport is for a project whose robot drives away from the desk: pin it to
ble once and nobody has to remember a flag. Left out, pb uses whichever
transport works and prefers USB where a hub is reachable both ways.
[tool.pb]
hub = "Rover"
transport = "ble"
That is the whole list at the moment, and an unknown key is refused by name rather than ignored:
$ pb list
[tool.pb] does not understand hubb.
Check /home/you/robot/pyproject.toml. [tool.pb] understands hub, transport.
Being strict here is deliberate, and it is the one place pb is stricter than
the environment. This file is committed and read by everyone who clones the
project, which makes it documented surface rather than a convenience. A
misspelled key that was quietly ignored would leave the hub silently wrong,
which is the kind of thing somebody loses an afternoon to.
Where your source is, it already knows¶
There is no key for this. If your project keeps its modules in src/, or your
build backend has been told to look somewhere else, pb reads the same setting
your backend does and looks for
a program's imports there.
| Backend | What it reads |
|---|---|
| uv | [tool.uv.build-backend] module-root |
| setuptools | package-dir, or [tool.setuptools.packages.find] where |
| hatchling | [tool.hatch.build.targets.wheel] packages, sources or only-include |
| poetry | [tool.poetry] packages = [{include = "...", from = "..."}] |
| pdm | [tool.pdm.build] package-dir |
| maturin | [tool.maturin] python-source |
None of that is standard — where a project keeps its source is left to the
build backend, and every backend spells it differently — but they all agree on
src/, so a project with a src/ directory needs no configuration at all.
It does not have to be a Python project¶
pyproject.toml is where Python projects keep their tool settings, and pb is
a Python tool, so that is where it looks. A file holding nothing but the two
lines above is a perfectly good way to mark the top of a robot project that is
mostly LEGO.