💡 Inspiration

Each one of us has been the new person on a hardware project. You sit down at the bench, look at a breadboard full of wires, and there is no commit history to read, no diff to pull up, no PR to review. You don't understand exactly where or how to contribute, or what has been done. Meanwhile the teammate who built it is unavailable until next week.

We come from computer engineering, computer science, cybersecurity, and IT: four people who've each spent time on a hardware team and felt the same absence. Software collaboration is solved. You clone the repo, read the history, open a PR. Hardware collaboration is still "ask whoever built it." That asymmetry is why good hardware projects stay stuck in one person's head, and why student teams fall apart the moment someone gets sick, changes their schedule, or just wants to hand off what they made.

benchlog is the layer that was missing.


⚙️ What it does

One command: benchlog init opens a hardware project to collaboration the same way git init opens a codebase. From that point on, every change to the physical circuit is scannable, reviewable, committable, and shareable.

A webcam reads the breadboard and proposes what changed (every wire added, moved, or removed), confirmed against the microcontroller's own pins, not just the image. The team reviews the proposed changes, commits the circuit state alongside the firmware, and runs deterministic electrical checks before anything lands. Push it, open a real PR, and the same checks run in GitHub Actions.

But the feature built for student collaboration specifically is the Build Guide: any commit in the timeline can be annotated as a step, with a label and a note. The result is a living, executable tutorial embedded directly in the project, not a PDF someone forgot to update, not a Notion doc that diverged from reality three weeks ago. A beginner joins the team, runs benchlog serve, opens the Build Guide tab, and watches the circuit come together commit by commit, with the wiring at every checkpoint exactly as it was when the person who built it was sitting at the bench.

That's mentorship that scales past the room and past the hackathon.


🛠️ How we built it

We split the system into four layers so all four of us could ship in parallel without conflicts:

Layer What's inside
Core package Pydantic circuit model, breadboard netlist, git wrapper, Typer CLI
Checks & GitHub Rule engine for electrical faults, pins.h generation, GitHub Actions CI
Frontend React + TypeScript, SVG breadboard diagrams, diff highlighting, commit timeline, Build Guide
Computer vision OpenCV, hole-occupancy detection

Every layer writes and reads the same circuit.json: one canonical, stable-key JSON file so a plain git diff stays human-readable.

The camera and the ESP32 feed a reconciler independently. The camera proposes what changed from the image; the ESP32 confirms it electrically by reading its own pins over serial. Agreement means the change is trusted automatically. Disagreement routes it to the reviewer. That two-signal design is what makes Benchlog safe for beginners: the board itself catches the mistake the camera can't see, before it becomes a burned component or a frustrated teammate wondering why nothing works.

🏗️ System Architecture

   ┌──────────────┐      ┌──────────────┐
   │  📷 Camera   │      │  🔌 ESP32    │
   │  USB webcam  │      │ agent (USB)  │
   └──────┬───────┘      └──────┬───────┘
          │ frames              │ pin states + I2C
   ┌──────▼───────┐      ┌──────▼───────┐
   │   Vision     │      │   Serial     │
   │ OpenCV diff  │      │ probes, I2C  │
   └──────┬───────┘      └──────┬───────┘
          └──────────┬──────────┘
            ┌────────▼────────┐        ┌─────────────┐
            │   Reconciler    │◀──────▶│  🖥️ Web app │
            │ camera × serial │        │   (React)   │
            └────────┬────────┘        └─────────────┘
            ┌────────▼────────┐        ┌─────────────┐
            │  Circuit model  │◀──────▶│  ⌨️ CLI     │
            │  circuit.json   │        │   (Typer)   │
            └───┬─────────┬───┘        └─────────────┘
       ┌────────▼──┐   ┌──▼────────┐
       │ ✅ Checker │   │ 🌿 Git    │
       │ rule set  │   │  layer    │
       └────────┬──┘   └──┬────────┘
            ┌───▼─────────▼───┐
            │ 📁 Project folder│
            │ circuit.json · .git │
            └─────────────────┘

The whole loop: scan → camera proposes, ESP32 verifies → you accept → circuit.json updates → checks run → commit → merge

🔌 Physical inputs

Component What it does
📷 Camera Overhead USB webcam. Takes a snapshot on each scan, not a stream
🔌 ESP32 agent Our read-only firmware. Answers PROBE, I2C, READ, PING over serial with one line of JSON. Never drives a pin

How the ESP32 senses wiring: it flips each safe pin's internal pull-up, then pull-down, and watches whether the pin follows.

Pull-up Pull-down Result
HIGH LOW floating: nothing attached
LOW LOW pulled_low: tied to GND
HIGH HIGH pulled_high: tied to 3V3

🌐 On the hosted site, Chrome's Web Serial API reads the ESP32 from the user's laptop and sends the readings with each scan.

🧠 FastAPI backend (Python)

Layer Role
Vision Calibrates the board once so every pixel maps to a hole like A12, then diffs each scan against the last accepted image
Serial Keeps the ESP32 connection open, powers the live status light, snapshots pins right after each camera capture
Reconciler Traces each change holes → breadboard node → ESP32 pin, predicts what the pin should read, and compares it to what the ESP32 actually sensed
Circuit model Reads/writes circuit.json, the single source of truth. The netlist is derived, never stored
Checker Deterministic electrical rules. Failures block merges, never commits
Git layer Commits, branches, fast-forward merges, plus tracking which commit the physical board matches

Reconciler verdicts:

Verdict Meaning
✅ confirmed Camera and ESP32 agree
⚠️ conflict They disagree, e.g. "W3 may not be seated. Press it in and rescan."
➖ camera only No clear electrical expectation (goes through a resistor, LED, etc.)

Checks we run:

Check Catches
⚡ Short 3V3 or 5V wired straight to GND
🚫 Bad pins Flash pins, strapping pins like GPIO12 that stop the ESP32 from booting, outputs on input-only pins
🔍 Serial conflict Camera says connected, ESP32 says floating
📡 I2C missing A declared sensor that didn't answer

🖥️ Interfaces

  • Web app (React): virtual SVG breadboard, verdict badges, commit timeline, before/after PR views, Build Guide
  • CLI (Typer): init · scan · status · diff · commit · log · check · serve
  • Both call the same core functions, so they can never disagree

📁 Storage: no database

my-project/
├── circuit.json    ← the breadboard, versioned
├── project.json    ← name, board, forked_from
├── .git/           ← every past version
└── .benchlog/      ← local only: calibration, board state, checks, PRs

Restart the server and everything is where you left it. Clone the repo and you get the whole design and its history.

🔧 The hardware twist: Git can change your files, but it can't move your wires. So Benchlog tracks which commit the physical board matches, and turns any diff into a rewire guide: "Move W2: GPIO 21 → GPIO 18."

🌐 Live at: https://benchlog.design/


🧗 Challenges we ran into

Making hardware state shareable. A circuit isn't a file you email. Getting to a point where a teammate in a different city could clone the repo, open the timeline, and see the exact board state at any past commit, down to which hole each wire was in, required a stable data model that treated physical layout as a first-class version-controllable artifact.

Camera vs. serial disagreement. Getting the vision pipeline and the ESP32 pin-probe to agree on what changed, and building a review flow for when they don't, took more iteration than the happy-path demo suggests. The disagreement case is where real learning happens: it's the system telling you "something is electrically wrong here" even when it looks right to the eye.

Keeping diffs meaningful. A pixel shift in a scan shouldn't look like a rewritten circuit. We enforced stable component and wire IDs plus canonical JSON ordering so version control on hardware actually reads like version control, not noise.


🏆 Accomplishments that we're proud of

A full loop that actually works end to end: physical change → scan → review → diff → commit → timeline → push → PR → check result. Not a slide. A real repo doing real git operations on a real board.

The Build Guide. The idea that the history of a hardware project, if it's tracked properly, is a tutorial. A beginner can replay how a working circuit was built, checkpoint by checkpoint, with notes from whoever made it. That is hardware knowledge that survives the hackathon, the semester, and the team.

The ESP32 cross-check catching what a camera alone cannot. A strapping pin looks visually identical to any other hole. The board knows the difference. We think that's the right model for teaching hardware safely: catch dangerous mistakes automatically, before they become a setback that drives someone away from building.


📚 What we learned

  • Version control ideas generalize further than code. Diff, commit, PR, CI all work for hardware. The hard part isn't the git mechanics. It's building a trustworthy sensor for physical state, and a collaboration model that makes the knowledge in that state legible to someone who wasn't there when it was made.
  • Two independent signals beat one. Cross-checking vision and electrical readings is more reliable than trusting either alone. That pattern generalizes past breadboards, to any system where physical state and digital state need to agree.
  • Lock the data model first. Agreeing on a shared data model before writing feature code is what let four people ship independently and integrate without conflict. circuit.json as the contract between every layer was the best architectural decision we made.

🚀 What's next for Benchlog

  • Beyond the breadboard. Protoboards and other breadboard form factors: the same scan → diff → commit → check loop working on more than BB830.
  • Fork a circuit. A student finds a working LED project on benchlog.design, forks the repo, and gets not just the code but the full wiring history: every step the original builder took, with the build guide to follow. Hardware becomes as remixable as open source software.
  • Beginner mode. A guided new-project flow that walks a first-time builder through benchlog init step by step: pick your board, place your first component, make your first commit. The same checks that protect experienced builders become teaching moments for beginners: "this pin is a strapping pin; here's what that means."
  • Infrastructure, ports, and packets. The idea that started this project: extend the same version-control loop to network infrastructure, tracking port assignments and cabling the way we track holes and wires. A misconfigured port caught the same way we catch a strapping pin today.

Built With

+ 4 more
Share this project:

Updates

Submission history