etchy: A PCB Diff You Can Trust

View on GitHub

Table of contents

Overview

You’ve spun rev B of a board, sent it to the fab, and somewhere between rev A and rev B something changed on a copper layer. Which pad? How much? Did that last-minute clearance nudge actually land, or did it quietly not? Staring at two Gerber renders side by side is how mistakes get to production.

etchy points at two revisions of a board’s fabrication output (Gerber, Excellon drill, pick-and-place) and shows and measures exactly what changed. It’s the ground-up Rust successor to my Python Gerber-Diff-Tool, and as of v0.1 it is public and usable. Dual-licensed MIT / Apache-2.0.

etchy old/ new/     # terminal summary; exit 0 = no diff, 1 = diff, 2 = error

Why “trustworthy” is the whole point

A diff tool that occasionally misses a change is worse than no tool, because it teaches you to trust it and then lets you down on the one board that mattered. So the design is built around not lying to you:

The limits are written down too, in the repo’s trust document: what etchy guarantees and what it deliberately doesn’t.

One computation, three outputs

Everything comes from a single per-layer polygon boolean diff (added = B - A, removed = A - B), computed once and presented three ways:

  1. A resolution-independent SVG overlay: the classic red/green added/removed view, but as vectors, so it stays crisp at any zoom. Also available as one self-contained HTML report.
  2. A change heatmap for the question “where do I even look?” on boards where the diff is a handful of pads in a sea of unchanged copper.
  3. Magnitudes: changed area (mm²) and region count as JSON, so CI can gate on how much changed, not just whether anything did.

Moved, rotated, added and removed components show up as placement markers, and schematic PDFs get a page-by-page pixel diff.

CI-first, viewer second

etchy lives in a pipeline first and on your desktop second. It has proper exit codes, per-layer thresholds, git refs (etchy v1.0 HEAD fab/ diffs two commits with no checkout) and JSON output. A GitHub Action posts a sticky per-layer table on every pull request that touches Gerbers:

- uses: Cimos/etchy@v0.1.1
  with:
    old: fab/rev-a
    new: fab/rev-b
    comment: true

Gating is by magnitude and location, so silkscreen churn can be ignored while copper changes over 0.5 mm² fail the build:

etchy old/ new/ --gate-layers copper --fail-on-area 0.5

It ships as small static binaries and an ~11 MB distroless container.

For poking around a diff by hand there’s a native egui desktop viewer (Windows, macOS, Linux) with overlay, before/after, split and swipe modes, plus a web build. It’s a separate binary that never gets compiled into the headless builds, so CI stays lean.

Try it

The repo ships two revisions of a real board, my open Mad_RP2040, so there’s something to diff straight away:

etchy crates/etchy-gui/assets/demo/old crates/etchy-gui/assets/demo/new --html diff.html
# 10 of 13 layers changed

Binaries, installers and the container are on the releases page.

Non-goals and what’s next

etchy deliberately does not do net or connectivity diff, BOM diff or DRC. It diffs fabrication output, trustworthily, and stops there. The other jobs have other tools (kitium covers a chunk of the KiCad-side CI story).

Next up is reading KiCad .kicad_pcb files directly, so you can diff the design and not just the fab output, with a list of changed objects alongside the layer diff. Altium .PcbDoc follows.

-SM

Related