Projects, BOMs, and Build Orders
Projects represent things you build — a PCB, a kit, a product. Each project has a BOM (Bill of Materials) listing the parts and quantities needed. Build orders consume the BOM, deducting stock from your inventory.
Creating Projects
tray project add "Synth VCO" --description "Voltage-controlled oscillator module"
tray project add "LED Matrix Clock"
tray project list
Building a BOM
Add parts to a project’s BOM with quantities and reference designators:
tray project bom-add 1 NE555 --qty 2 --refs "U1,U2"
tray project bom-add 1 "10k Resistor" --qty 8 --refs "R1-R8"
tray project bom-add 1 "100nF Cap" --qty 4 --refs "C1-C4"
If you add the same part twice, the quantity is updated (not duplicated).
View the BOM with availability info:
tray project show 1
Output:
Project: Synth VCO [active]
BOM (3 line items):
part_name quantity_required reference_designators stock_available sufficient
------------- ----------------- --------------------- --------------- ----------
NE555 2 U1,U2 25 yes
10k Resistor 8 R1-R8 100 yes
100nF Cap 4 C1-C4 50 yes
Checking Availability
Before building, check if you have enough stock:
# Can I build 1 unit?
tray project check 1
# Can I build 10 units?
tray project check 1 --qty 10
If stock is insufficient:
Can build 10 unit(s): NO
Shortages:
part_name required available short
--------- -------- --------- -----
NE555 20 15 5
Building
A build order deducts stock for every BOM line, multiplied by the build quantity:
# Create and immediately complete a build of 5 units
tray project build 1 --qty 5 --complete
This deducts:
- NE555: 2 * 5 = 10 units
- 10k Resistor: 8 * 5 = 40 units
- 100nF Cap: 4 * 5 = 20 units
The build will fail if any part has insufficient stock. Stock is not partially deducted — it’s all or nothing.
Without --complete, the build order is created in draft status for later completion.
Importing a KiCad BOM
If you design PCBs in KiCad, you can export a BOM CSV and import it directly:
# Export BOM from KiCad (File -> Fabrication Outputs -> BOM)
# Then import into a Tray project:
tray bom-import 1 kicad-bom.csv
Output:
BOM import complete:
Matched: 12 parts
Unmatched: 3 parts (not in inventory)
C5: 100pF (Capacitor_SMD:C_0402_1005Metric)
U3: ATmega328P (Package_QFP:TQFP-32_7x7mm_P0.8mm)
J1: USB_C (Connector_USB:USB_C_Receptacle_GCT_USB4085)
Tip: Add missing parts with 'tray add', then re-import.
Tray matches BOM entries to parts by the Value column. Unmatched parts are reported so you can add them and re-import.
Purchase Orders
When you need to replenish stock, create a purchase order:
# Create a PO for a supplier (by name or ID)
tray po create --supplier "Mouser" --notes "Synth VCO restock"
# Add lines -- parts are resolved to the supplier automatically.
# If no supplier_part link exists, one is auto-created.
# Prices auto-fill from existing price breaks.
tray po add 1 "NE555" --qty 100
tray po add 1 "LM7805" --qty 50 --price 0.45
# Review the PO
tray po show 1
# Edit a PO line (update quantity, price, or both atomically)
tray po edit-line 1 --qty 100 --price 0.0412
tray po edit-line 2 --currency EUR
# Mark as ordered (after placing the order on the supplier's website)
tray po submit 1
# Receive items when they arrive
tray po receive 1 --location "Shelf A" # receive all outstanding
tray po receive 1 --line 3 --qty 50 --location "Bin" # receive a specific line
# List POs, optionally filtered by status
tray po list
tray po list --status ordered
# Cancel a PO
tray po cancel 1
The PO workflow:
- Create a PO for a supplier (
draft) - Add PO lines by part name — supplier links and pricing are handled automatically
- Mark as
orderedwhen you place the order - Receive items as they arrive — stock is added automatically
- PO transitions to
partialthenreceivedas lines are fulfilled
Receiving a PO line automatically creates stock lots for the corresponding part, so your inventory stays current. Partial receiving is fully supported — receive what arrived and leave the rest.
Full Workflow Example
# 1. Add parts to inventory
tray add "ATmega328P" --category "ICs/MCU" --stock 5
tray add "16MHz Crystal" --category "Passives/Crystals" --stock 20
tray add "22pF Cap" --category "Passives/Capacitors" --stock 100
# 2. Create project
tray project add "Arduino Clone"
# 3. Define BOM
tray project bom-add 1 ATmega328P --qty 1 --refs "U1"
tray project bom-add 1 "16MHz Crystal" --qty 1 --refs "Y1"
tray project bom-add 1 "22pF Cap" --qty 2 --refs "C1,C2"
# 4. Check availability for 3 units
tray project check 1 --qty 3
# 5. Build
tray project build 1 --qty 3 --complete
# 6. Verify stock deducted
tray list
# ATmega328P: 5 - 3 = 2
# 16MHz Crystal: 20 - 3 = 17
# 22pF Cap: 100 - 6 = 94