via-pcb-cli 0.1.1

Project-oriented CLI wrapper for via checks, snapshots, BOMs, and exports.
via-pcb-cli-0.1.1 is not a library.

via

Design circuit boards with Rust

via is a Rust-native circuit authoring toolkit. It lets you describe a board as normal Rust data, validate pin maps and nets, and export reviewable KiCad / LCEDA artifacts.

Why via

  • Reusable board modules instead of copy-pasted schematic fragments.
  • Typed nets, rails, pins, footprints, and electrical classes.
  • Validation before export, including pin maps, pad bindings, and connectivity.
  • KiCad and LCEDA Pro export paths for review, hand layout, and iteration.
  • Rust tests for hardware design assumptions.

Get Started

Add via-pcb to your Rust project:

[dependencies]

via = { package = "via-pcb", version = "0.1.1" }

The crates.io package is via-pcb, while the Rust crate name is still via:

use via::prelude::*;

pub fn board() -> Result<Board> {
    let mut d = Design::new("demo")
        .rules(Rules::new())
        .units(Unit::Mm);

    let signal = d.signal("SIGNAL", "3V3");
    let v3v3 = d.rail("3V3").dc(3.3);
    let ground = d.ground("GND");

    let j1 = d.add(
        part("J1", "3-pin header")
            .footprint(fp::pin_1x03())
            .symbol(sym::connector().left(["SIG", "3V3", "GND"]))
            .pin(pin("SIG").logic("3V3").pad("1"))
            .pin(pin("3V3").power("3V3").pad("2"))
            .pin(pin("GND").ground().pad("3")),
    )?;

    d.connect(&signal, [j1.pin("SIG")]);
    d.connect(&v3v3, [j1.pin("3V3")]);
    d.connect(&ground, [j1.pin("GND")]);

    d.check(CheckProfile::Prototype)?;
    d.finish()
}

For exporter workflows, install the CLI package. The package name is via-pcb-cli, and the installed command is via:

cargo install via-pcb-cli
via check <design-name>
via export kicad <design-name>

Alternative Dependency Sources

Use the Git repository directly:

[dependencies]

via = { package = "via-pcb", git = "https://github.com/jz315/via-rs.git" }

For local development, use a path dependency:

[dependencies]

via = { package = "via-pcb", path = "../via-rs/crates/via" }

Workspace

  • via-pcb: user-facing package; its Rust crate name is via and it provides via::prelude::*.
  • via-core: boards, modules, pins, nets, footprints, rules, and diagnostics.
  • via-parts: generic reusable parts such as resistors and capacitors.
  • via-footprint: high-level generated footprint builders.
  • via-footprint-ir: low-level footprint geometry IR for custom generators.
  • via-kicad: KiCad netlist, footprint, schematic, and PCB helpers.
  • via-lceda-pro: LCEDA Pro package export.
  • via-project: via.toml project loading and external design providers.
  • via-examples: generic examples for tests and documentation snippets.
  • via-pcb-cli (crates/via-cli): project-oriented command-line wrapper for checks, snapshots, BOMs, and export. It installs the via binary.

Minimal Example

use via::prelude::*;

pub fn board() -> Result<Board> {
    let mut d = Design::new("modern_api_minimal")
        .rules(Rules::new())
        .units(Unit::Mm);

    let signal = d.signal("SIGNAL", "3V3");
    let v3v3 = d.rail("3V3").dc(3.3);
    let ground = d.ground("GND");

    let input = d.add(
        part("J1", "External 3.3V signal input")
            .footprint(fp::pin_1x03())
            .symbol(sym::connector().left(["SIG", "3V3", "GND"]))
            .pin(pin("SIG").logic("3V3").pad("1"))
            .pin(pin("3V3").power("3V3").pad("2"))
            .pin(pin("GND").ground().pad("3")),
    )?;

    let load = d.add(
        part("U1", "Demo load")
            .footprint(fp::pin_1x03())
            .symbol(sym::module().left(["IN"]).right(["VCC", "GND"]))
            .pin(pin("IN").logic("3V3").pad("1"))
            .pin(pin("VCC").power("3V3").pad("2"))
            .pin(pin("GND").ground().pad("3")),
    )?;

    d.connect(&signal, [input.pin("SIG"), load.pin("IN")]);
    d.connect(&v3v3, [input.pin("3V3"), load.pin("VCC")]);
    d.connect(&ground, [input.pin("GND"), load.pin("GND")]);

    d.check(CheckProfile::Prototype)?;
    d.finish()
}

Main Ideas

Part is the electrical object in the schematic model. It owns logical pins, electrical classes, symbol placement hints, and the footprint reference.

Symbol is only the schematic drawing style. It decides where logical pins are shown on the generated schematic. It does not create nets or hidden pins.

Footprint is the PCB-side physical model. It names or embeds pads and geometry. A logical pin may map to a physical pad with .pad("1").

Design is the authoring surface. It creates nets, adds components, connects pins, runs checks, and produces a checked Board.

Board is the read-only result used by exporters, snapshots, and tests.

Footprints

Normal users should prefer parts that already carry footprints:

use via::prelude::*;

let r1 = design.add(parts::resistor("R1").value(1.kohm()).fp(fp::r0805()))?;
let c1 = design.add(parts::capacitor("C1").value(100.nf()).voltage(50.v()))?;

For custom parts, attach either an embedded generated footprint or an external KiCad footprint name:

let j1 = design.add(
    part("J1", "Debug header")
        .footprint(fp::pin_1x04())
        .symbol(sym::connector().left(["1", "2"]).right(["3", "4"]))
        .pins(["1", "2", "3", "4"]),
)?;

let u1 = design.add(
    part("U1", "Vendor module")
        .footprint("Vendor_Module_From_KiCad_Library")
        .pins(["VIN", "GND", "OUT"]),
)?;

via-footprint contains only common, generic footprint builders:

  • SMD passives: R_0402, R_0603, R_0805, R_1206, and matching capacitors.
  • Radial capacitors: generic verify builders for D5.0/P2.0, D6.3/P2.50, D8.0/P3.5, and D10.0/P5.0. Downstream projects can bind specific KiCad official footprints through explicit footprint asset metadata.
  • Pin headers and sockets: Pin_1x*, Pin_2x*, Socket_2x08_R12.7.
  • Board connectors: terminal blocks, XH, PH.
  • Debug and mechanical footprints: test pads, fiducials, mounting holes.
  • Small semiconductors: LED, SOD, SOT, SOIC, TSSOP.

Measured dev boards, purchased modules, and product-specific connector drawings belong in downstream part crates.

CLI

A downstream project is driven by via.toml, not by compiled-in examples. The CLI reads a design provider, receives stable BoardIr JSON, then runs checks or exporters. Replace the placeholder values below in your project.

[project]

name = "<project-name>"

version = "<project-version>"

default-design = "<design-name>"



[designs."<design-name>"]

provider = "cargo"

package = "<provider-package>"

command = "<provider-command>"



[outputs.kicad]

dir = "<kicad-output-dir>"

project = "<kicad-project-name>"

footprint-library-name = "<kicad-footprint-library-name>"

footprint-library-path = "<kicad-footprint-library-path>"

footprint-output-dir = "<generated-footprint-output-dir>"



[kicad-footprints]

version = "10.0.4"

source = "github-release"

The provider command prints the board IR:

use via::prelude::*;

fn main() -> Result<()> {
    let board = project_design::board()?;
    via::project::emit_ir(&board)
}

Project commands:

cargo install via-pcb-cli
via ir <design-name> --out <board-ir-json>
via check <design-name>
via check <design-name> --production
via snapshot <design-name> --out <snapshot-json>
via bom <design-name> --format csv --out <bom-csv>
via footprints status
via footprints import --version 10.0.4 --from "<KiCad footprints dir>"
via footprints fetch --url "<cache-bundle-url>" # experimental
via export kicad <design-name>
via export lceda-pro <design-name> --out <lceda-package>
via export pcb <design-name> --layout <layout-json> --out <kicad-pcb> # experimental

Contribution

git clone https://github.com/jz315/via-rs.git
cd via-rs
cargo fmt --check
cargo test --workspace

License

via-pcb is licensed under the Mozilla Public License 2.0.

Official KiCad footprint assets imported or fetched through via-kicad-footprints remain under CC-BY-SA-4.0 WITH KiCad-libraries-exception; see that crate's third-party notices.