Skip to main content
Package versions identify immutable source snapshots. A dependency on component-lib@0.3.2 selects the same source for every build until the manifest changes.

Version policy

PCB packages use semantic versions with hardware-specific compatibility rules:
Per the Semantic Versioning specification, pre-1.0 packages have no stable public API. PCB therefore treats 0.3.x and 0.4.x as separate compatibility families.
Versions within one family must remain compatible:
When a dependency graph requires several versions from one family, resolution selects the highest required version in that family. Authors must not publish a breaking change within a family. PCB combines Minimal Version Selection (MVS) with hydrated pcb.toml manifests for reproducible builds. pcb sync records the selected dependency graph, including immutable pseudo-versions for branch and commit dependencies. Build commands then reuse that recorded graph without selecting newly published versions.

Workspace package discovery

Starting at the workspace root, pcb searches at most eight directory levels and treats each descendant directory containing pcb.toml as a package. [workspace].exclude controls discovery:
pcb does not search inside an excluded directory. It also skips generated and cache directories such as .git, .pcb, vendor, target, node_modules, and fork.

Coexisting versions

A build can contain multiple incompatible families of one package. For example:
The resolver retains separate copies of component-lib@0.3.x and component-lib@1.x for their respective dependents. This permits incremental migration and diamond dependencies. Values from the two families have distinct types and cannot be passed across the compatibility boundary.

Minimal Version Selection

PCB uses MVS, based on Go modules. For each package family, MVS selects the lowest version that satisfies every explicit minimum in the dependency graph. Newly published versions do not change the result unless a manifest requires them.

How MVS works

Consider this dependency graph:
The board requires component-lib >= 0.3.0, while regulator requires component-lib >= 0.3.2. MVS therefore selects 0.3.2, even if 0.3.9 exists. Require a newer version explicitly when the project is ready to test it:
MVS is deterministic and does not backtrack. Within each compatibility family, the selected version is the highest minimum requested by any dependent.

Resolution algorithm

  1. Seed: Collect direct dependencies from all workspace packages. Group by package path and compatibility family. Initialize each family to the highest version explicitly required.
  2. Discover: Fetch manifests for selected versions. For each transitive dependency, if it requires a higher version within an existing family, upgrade. Repeat until the selected graph no longer changes.
  3. Build closure: Trace the dependency graph from workspace roots using final versions. This filters out any versions that were superseded during discovery.
For multiple compatibility families:
Both versions remain in the build because they belong to different families.

Import paths as identity

Import paths serve as globally unique package identifiers:
The path identifies the package owner and source repository without a central namespace. A file’s imports also state which packages its source requires. Import paths omit versions. The pcb.toml manifest declares which version of each package to use:
This separation keeps import statements stable across upgrades and confines version changes to manifests. The same source file can use different selected versions in different workspaces.

Hydrated manifests

Workspaces store resolved dependency state in pcb.toml. pcb sync updates:
  • [dependencies]: direct dependencies the package imports or explicitly owns.
  • [dependencies.indirect]: the tool-managed MVS closure needed to build it.
The @1 suffix is a compatibility lane. It allows multiple incompatible versions of the same package path to coexist while keeping the selected version exact. Do not edit [dependencies.indirect] by hand. Commit hydrated pcb.toml files.

Vendoring ([workspace].vendor)

Vendoring policy is controlled by the root workspace manifest:
  • pcb publish uses [workspace].vendor patterns when staging release sources.
  • pcb sync vendors packages matched by [workspace].vendor.
  • pcb vendor without --all uses [workspace].vendor.
  • pcb vendor --all vendors everything.
  • Read commands such as pcb build, pcb layout, pcb test, pcb open, and pcb bom do not change vendor/ or rewrite dependency manifests.

Workspace name ([workspace].name)

Workspace manifests can override the Diode workspace name used for board release uploads:
If name is omitted, pcb publish derives the workspace name from the first path segment of [workspace].repository. For example, anything.com/XYZ/boards/MyBoard uses XYZ.

Endpoint ([workspace].endpoint)

Workspace manifests can override the Diode host suffix used by CLI commands that access Diode services:
  • endpoint = "diode.computer" resolves application and API URLs under app.diode.computer and api.diode.computer.
  • The setting applies to workspace-aware commands such as pcb auth, pcb bom, pcb publish, and routing commands.
  • Authentication is scoped to the resolved endpoint. Authentication for one endpoint does not overwrite tokens for another.

BOM matching ([workspace.bom])

pcb bom availability queries use strict BOM matching by default, requiring exact MPN matches. Workspace manifests can opt out to use fuzzy matching:
Normalized BOM match responses are cached locally for ten minutes. Online commands refresh stale entries and reuse the exact stale response if refresh fails. pcb bom --offline never contacts the API and uses the exact cached response regardless of age; without one, it emits the locally generated BOM without availability data.

Registry search scope

Registry-backed pcb search searches the public Diode registry and the registries configured by [workspace].repository.
  • pcb search --registry code.diode.computer/diode/registry ... overrides the default scope for that invocation.
  • Repeat --registry to search more than one registry.

Pseudo-versions

Pseudo-versions identify unreleased commits while preserving version ordering. The format is v<base>-0.<timestamp>-<commit>.
Resolution produces a version such as:
pcb sync writes the resolved pseudo-version back to the package manifest with the full 40-character commit hash. The base version (0.3.15) is the next patch version after the most recent tag reachable from that commit. This places the pseudo-version after its base tag and before the next release. If the package has never been tagged, pseudo-versions start in the 0.1.1 family (for example 0.1.1-0.<timestamp>-<commit>), one patch above the initial unpublished release version 0.1.0. Pseudo-versions participate fully in MVS. If one package requires component-lib@0.3.14 and another requires the pseudo-version above, MVS selects the pseudo-version (it is higher). This permits testing an unreleased change without retaining a mutable branch reference in the hydrated graph. Use a tagged release for production dependencies when one is available.

Commands

pcb migrate

Runs project migrations using the latest stable pcbc toolchain, regardless of the workspace’s current pcb-version lane. After all migrations succeed, the command updates [workspace].pcb-version in pcb.toml to the target toolchain lane.

pcb sync

Reconciles imports and hydrates package manifests. Run this after adding or removing imports or changing dependency versions.
The command also downloads selected packages into the cache and vendors packages matched by [workspace].vendor. pcb sync --check always verifies the whole workspace, regardless of the current directory, and writes neither pcb.toml nor vendor/. It detects missing or stale vendored package versions; it does not verify the contents of vendored versions that are already present.

pcb add

Adds or upgrades a direct dependency for the package in the current directory.
pcb add rewrites the direct dependency entry and rehydrates the package’s dependency closure.

pcb build

Builds a board or workspace package.
pcb build checks that the hydrated state is sufficient and does not rewrite pcb.toml or vendor/. Use pcb sync or pcb vendor to update dependency state.

pcb list

Lists read-only package dependency information.
pcb list -m -u must be run from a package directory. It reports direct remote dependencies only, showing the latest stable version in the same compatibility lane and the latest newer breaking lane when available. It does not update manifests.

pcb update

pcb update is disabled. Use pcb add -u instead.

pcb publish

Publishes packages by creating annotated git tags. Discovers which packages have changed since their last published version and tags them.
A package requires publication when:
  • No version tag exists.
  • Its content hash differs from the published tag.
  • Its pcb.toml hash differs from the published tag.
Versions are computed automatically:
  • Unpublished: Start at 0.1.0.
  • Published packages: Apply the requested semantic-version bump: patch, minor, or major.
  • --bump=infer: Infer each bump from conventional commits since the last tag, then raise dependent bumps to at least the highest bump among published internal dependencies.
  • -y / --yes: Skip the final confirmation prompt.
Packages are published in dependency order. Packages with no changed dependencies are published first; their dependents follow after manifest updates.

pcb info

Displays workspace and package information.