# Fusible
> **The fuse for your firmware.** An electronic linter and tscircuit project manager in Rust:
> it reads the Circuit JSON generated by [tscircuit](https://tscircuit.com), checks the
> electrical and physical rules of the board — and when a rule fails, **the
> fuse blows**: the process exits with an error and firmware code generation
> never happens.
Fusible unifies hardware and firmware into a single monorepo contract using `fusible.yml`,
wrapping tscircuit development servers, viewers, artifact exports, and hardware compilation.
## Project status
| 1 (MVP) | CLI, Circuit JSON parser, rules engine, diagnostics | ✅ shipped |
| 1.1 | `fusible.yml` manifest, tscircuit CLI wrapper (`dev`, `export`, `build`, `init`) | ✅ shipped |
| 2 | `mcu::` — pin-muxing validation against the silicon target | 🔜 |
| 2 | `codegen::` — `pins.rs` generation for Embassy (fuse intact only) | 🔜 |
## Prerequisites
Fusible requires **`tscircuit`** (`tsci` CLI) to compile `.tsx` circuits, run the live dev previewer (`fusible dev`), and export manufacturing deliverables. Install it globally or locally in your workspace:
```sh
# Using bun (recommended):
bun add -g tscircuit
# Or using npm:
npm install -g tscircuit
```
Inspect toolchain health anytime with `fusible doctor` (or run `fusible doctor --install` to automatically provision it).
## Installation
```sh
cargo install fusible
# or build from source:
# cargo install --path .
```
## Quick Start (Monorepo)
Initialize a new hardware + firmware project:
```sh
fusible init --name sensor-node
```
This creates a minimal `fusible.yml`:
```yaml
name: sensor-node
hardware:
entry: hardware/index.tsx
out_dir: dist
port: 3020
mcu:
chip: stm32g431
firmware:
path: firmware
framework: embassy
pins_rs: firmware/src/pins.rs
build_cmd: cargo build
```
## Commands
### 1. Electrical Linter (`check`)
```sh
fusible check # uses fusible.yml entry
fusible check hardware/index.tsx # compiles .tsx on the fly and lints
fusible --input circuit.json # direct Circuit JSON input
```
Clean circuit (exit code 0):
```
✅ Circuit validated (fuse intact)
```
Rule violated (exit code 1):
```
× the fuse blew: 1 electrical violation(s)
× [unconnected_net] net "I2C_SDA" has only 1 connection(s) (minimum 2): it is floating
help: every net must connect at least two pads/ports — complete the routing in tscircuit
```
### 2. Live Interactive Viewer (`dev` / `view` / `webview`)
Starts the local tscircuit development server with interactive schematic, PCB layout, and 3D preview:
```sh
fusible dev
fusible view --port 3020
```
### 3. Build (`build`)
Evaluates the board, lints the circuit, and compiles firmware only if the fuse is intact:
```sh
fusible build
```
### 4. Fuse-Gated Deliverables (`export`)
Exports fabrication-ready Gerbers, KiCad projects, SVGs, 3D models (STEP/GLB), or documentation.
All exports are **fuse-gated**: electrical rules are verified first. If a rule fails, the fuse blows and no artifacts are produced.
```sh
# Presets:
fusible export --preset fab # Gerbers (.zip) + Circuit JSON
fusible export --preset cad # KiCad project (.zip) + 3D STEP (.step)
fusible export --preset docs # Schematic SVG + PCB SVG + Schematic PDF
fusible export --preset all # Generates all export bundles
# Specific format exports:
fusible export -f gerbers -o dist/gerbers.zip
fusible export -f pcb-svg
fusible export -f step
fusible export -f kicad_zip
# Bypass verification (for debugging/drafts):
fusible export --preset fab --skip-lint
```
### 5. Hardware Package Management (`add`, `install`, `search`)
Manage tscircuit packages, community footprints, and components without touching npm or tsci directly:
```sh
# Search footprints and components in the tscircuit registry:
fusible search esp32-s3
# Add a community component or registry footprint to hardware/:
fusible add @tsci/seveibar.smd-resistor
# Install all hardware dependencies:
fusible install
```
### 6. Toolchain Diagnostics (`doctor` / `setup`)
Inspects local toolchain health (bun, node, npm, npx, tsci) and verifies tscircuit runner availability:
```sh
fusible doctor
# Automatically provision tscircuit if missing:
fusible doctor --install
```
## Exit codes
The codes are part of the contract, so CI can tell failures apart:
| `0` | Fuse intact — circuit validated / command succeeded |
| `1` | Electrical violations — the fuse blew, generation is blocked |
| `2` | Tool or usage error (unreadable/malformed input, bad arguments) |
## Architecture
```
src/
├── main.rs # read → parse → lint → verdict, exit codes
├── cli.rs # clap commands: check, dev, build, export, init
├── commands/ # subcommand implementations
│ ├── check.rs # electrical linter + on-the-fly .tsx compilation
│ ├── dev.rs # live viewer wrapper (tsci dev)
│ ├── export.rs # artifact export wrapper
│ ├── build.rs # full build pipeline
│ ├── init.rs # fusible.yml scaffolding
│ └── target.rs # manifest & convention path resolution
├── config/ # fusible.yml / fusible.yaml manifest loader
├── tscircuit/ # runner detection (local/global tsci) & process execution
├── parser/ # Serde Circuit JSON parser
├── linter/ # Rule trait + fail-closed electrical engine
└── netlist/ # graph representation of circuit connectivity
```
## Development
```sh
mise install # installs lefthook (conventional commits)
cargo test # test suite (50+ unit and integration tests)
cargo clippy --all-targets -- -D warnings
filet check . # code quality (https://github.com/FacileStudio/filet)
```
## License
[MIT](LICENSE)