Monorepos
Last updated on August 14, 2026
A TofuPilot project holds one procedure or many, so a monorepo is the right layout when you want to share instrument drivers, calibration sequences, and finalizer phases across procedures. The patterns below scale from a single procedure on a laptop up to a fleet of related products that ship from the same repo.
Single procedure
When a project covers a single procedure, everything lives next to one procedure .yaml file. Phases, plugs, and the environment all sit in the same folder so you do not have to think about paths.
Multiple procedures
When a second product joins the repo, lift the reusable code into shared/ and keep each procedure under procedures/<name>/ with its own .yaml file. Each procedure then references shared code by relative path, so you keep one canonical copy of every driver and helper.
Each procedure .yaml file resolves Python references against its own directory, so shared modules are reached either via relative paths (../../shared/phases/save_to_mes) or by adding shared/ to PYTHONPATH from .env.local.
Sharing a plug across procedures
Define each plug once under shared/plugs/ and reference it from every procedure .yaml file that needs it, so a single file holds the canonical driver.
name: Laptop Battery Functional
plugs:
- name: Power Supply
python: ../../shared/plugs/RigolDP832:RigolDP832
main:
- name: Test Cell Voltage
python: phases.test_cell_voltageWhen the driver changes, every procedure picks up the new version on the next run, so you do not have to remember to bump versions across the repo.
Deploying each procedure from the same repo
Each TofuPilot procedure maps to its own subdirectory through two settings, set once per procedure with tofupilot procedures update or from the procedure's settings page:
- Root directory: the path within the repo to the directory holding the procedure's
pyproject.tomlandprocedure.yaml. For the layout above:procedures/laptop-battery-functional. - Entry point: which file to run inside that directory, when the default does not fit. A
.yamlentry point is the only way to run a procedure file with a custom name (for examplebattery-functional.yamlinstead ofprocedure.yaml); a.pyentry point points OpenHTF procedures at a file other thanmain.py.
tofupilot procedures update --id <functional-id> --root-directory procedures/laptop-battery-functional
tofupilot procedures update --id <burnin-id> --root-directory procedures/laptop-battery-burninWith Git deployments, one push then builds every procedure from its own directory, with no per-procedure checkouts and no renaming.
How is this guide?
Station
Run the TofuPilot CLI as a station service on the factory floor, with deployed procedures, a live operator UI, and automatic report upload.
OpenHTF
Learn how to run existing OpenHTF suites through TofuPilot so phase outcomes, measurements, logs, and attachments upload to the dashboard automatically.