KiCadRoutingTools — what's new (June 2026) #28
Replies: 11 comments
Update — June 9Since this post went up: v0.15.7 was released (the PCM packaging described above), and a deep pass on differential-pair routing for boards without fanout stubs — driven by a simple 2-layer LVDS converter board where the diff pairs land directly on SOIC pins and 0805 termination resistors. That path exercised assumptions the BGA-fanout flow never hit, and shook out a chain of fixes: Diff pairs on bare pads
Other fixes since v0.15.7
Docs: the differential-pair internals writeup ( |
Update — June 9 (later): multi-point differential pairsContinuing the bare-pad diff-pair work from the previous update, the router can now handle multi-point differential pairs — pairs whose nets land on 3+ pad-pair terminals (e.g. connector → termination resistor → IC pins), which previously left everything beyond the closest two terminals unrouted. Multi-point diff pairs route as a chainA diff pair can't tap onto the middle of an existing pair of tracks — the tapping leg's P/N would have to cross the existing pair. And each pad-pair terminal has only two usable sides (the ± directions of its escape axis), so the connection topology must be an open chain, not the MST tree used for single-ended multi-point nets. The new
On the LVDS converter test board, Board-edge clearance actually works nowChasing a copper-to-edge DRC report from GUI routing uncovered a chain of issues:
Other fixes
|
Update — June 9 (evening): polarity resolution by shortest routeFollowing up on the multi-point work — polarity mismatches are now resolved by competition between the two available mechanisms, and the result on the LVDS converter board speaks for itself: CLK± spans 4 pad-pair terminals (connector → termination → two IC pin pairs; note the swapped IC pins 6/7), DATA± spans 3 — every leg enters its terminals directly, no detours. What changed
The multi-point regression test now runs five scenarios: each pair with fixing on (asserting the expected length-comparison winner — flip for DATA, pad swap for CLK) and with |
Update — June 10: Claude in the plugin GUI, and a multi-point crossing fixTwo threads today: the plugin grew a full AI assistance layer driving the project's Claude Code skills from inside KiCad (#34, #39, #40, #53 — PR #52), and the multi-point diff-pair work from yesterday shook out one more correctness fix (#56). Claude tab: plan → review → execute (#40)The routing dialog has a new Claude tab that spawns
Per-field "Ask Claude" buttons (#34, #39, #53)Each analysis skill is also wired to the field it feeds, with validation between Claude and the controls (unknown nets/layers dropped with logged notes, garbage rejected):
Analyses run on a temp snapshot of the live board, so unsaved edits are always visible to Claude and the board file is never touched. The button-to-skill map is documented in docs/claude-skills.md. Version bumped to 0.15.10 (release pending). Multi-point diff pairs: crossing legs are now rejected (#56)Field testing the Claude plan flow found a real router bug: a chain leg was only validated against its own P/N crossing — whether it crossed previously committed legs relied on the obstacle map, which deliberately exempts corridors at shared terminals so the opposite-side setback can leave. When a GND stitching via blocked the channel next to a termination resistor, the forced wrap-around leg crossed the earlier legs inside that exemption: committed P/N shorts plus self-crossing loops. Legs are now checked against all committed legs' segments after routing (terminal-pad touches excluded — only proper crossings count); a crossing rejects the leg and the existing alternative-chain-ordering retry takes over. On the repro board: with polarity fixing the pair routes cleanly around the via (zero crossings, ~30mm instead of the looping ~45mm); with Plan ordering: signals before planesThe #56 trigger also reshaped |
Update — June 10 (evening): the Claude tab in action, a 6.4× obstacle-map speedup, and hardeningThe Claude tab, working end to endThe plan → review → execute flow from this morning's update, on the LVDS converter board — Refinements that landed after field use: the transcript and step list (with status marks and check state) persist across dialog reopens and only clear when a new Plan Routing run starts; Review/Diagnose runs append under a separator instead of wiping the log; and analyses run on a temp snapshot of the live board (kipy-style save-a-copy semantics), so unsaved edits are always visible to Claude, the user's file is never touched, and the save-over-open-file crash class is gone. Obstacle map rasterization: 6.4× faster (issue #35)Profiling issue #35's "rayon for base map rasterization" idea found the premise didn't hold: the rasterization was pure Python, calling into the Rust map one cell at a time — 13.1 million Python→Rust FFI crossings per build on a dense board. There was nothing in Rust for rayon to parallelize. The fix was numpy batching into the Rust batch APIs that already existed: base obstacle map builds went from 1.72s → 0.27s on a fully-routed 5,973-segment board (the reroute scenario where it dominates), and the per-net obstacle cache from 0.49s → 0.34s. Equivalence was proven the hard way — the Rust map reference-counts cells, so the batched code emits the exact same multiset of cell additions as the old loops (verified against the legacy implementation across three boards, plus a bit-identical full-board route: same nets, same 1,390,741 A* iterations). Pure Python, so no Rust rebuild ships. The genuine rayon candidates (parallel forward/reverse probes, parallel rip-up evaluation) stay open in #35. Hardening
IPC branch syncedThe All of this is on |
Update — June 22: the real-world stress-test era (v0.15.11 → v0.15.15, 80+ fixes)Since the June 10 update the project has been through one dominant theme: stress-testing the router against 45 real-world open-source KiCad boards and grading every result against the board's own human routing. That program (its own write-up and full per-board scorecards live in discussion #117) has driven 80+ fixes and five releases (v0.15.11 → v0.15.15), and v0.15.15 is now live in the official KiCad PCM (merged via gitlab.com/kicad/addons MR !607), so it installs straight from KiCad's Plugin & Content Manager. Rather than re-list all 80, here are the changelog-level highlights. New capabilities & features
Major bug fixes (grouped)
GUI / Claude tabThe CLI/GUI parity discipline held throughout (documented as a standing rule): the QFN under-pad escape, plane-repair rip-blocker + distant-pad-trace repair, per-step plan-param re-application, and a Full detail and the per-board stress scorecards are in #117; everything above is on |
Update — June 22 (later): DRC settings that match the route, and a sub-clearance grazes sweep
KiCad DRC now matches the clearances the router actually used (#160)The long-standing annoyance: open a freshly-routed board in KiCad, run the DRC, and get hundreds of false positives — because the project file carries KiCad's stock-default design rules, not the floors the board was routed to. Routing now writes the board's DRC design rules back to match: a complete A new grading method, and the sub-clearance grazes it caughtGrading runs now compare at the minimum routed clearance with a whole-set A/B replay tool (
Net effect: the real different-net shorts and via-over-track/edge overlaps that remained on the densest boards (eis, daisho, esp_prog) — down to tens of microns — are caught and cleared (#169/#174). Diff-pair regression fixes & QFN escape
Full per-board detail is in #117; everything here is on |
Update — June 23: decoupling-cap placement repair, and DRC-settings parity everywhereTwo threads landed on Decoupling-cap placement repair (#130)The one residual the dense-BGA under-pad escape (#122) couldn't fix on its own: on a fully-populated array, a decoupling cap sometimes sits exactly where a signal ball wants its via-in-pad, so the via and the cap pad overlap. A new repair pass fixes it by moving the cap instead of the via — after fanout it nudges each near-BGA decoupling cap or resistor off any foreign-net fanout via (and any foreign track on its side) and pulls its pad toward the nearest same-net ball, so a power/GND via dropped there later also lands on the cap. Caps (and resistors) move as little as possible, never overlap each other, and any that still can't clear are reported. Relatedly,
On ulx3s U1 (22×22, 0.8 mm) it takes the fanned board from 4 via-in-pad overlaps to fully DRC-clean, tidying 19 caps toward same-net balls. DRC-settings write-back now covers every routing entry point (#160)The "make KiCad's interactive DRC match what we routed to" auto-fix (from the last update) is now wired through everywhere, not just
Both front-ends share the same target-computing logic and only differ in how they apply it ( Full per-board detail is in #117; everything here is on |
Update — June 24: comb-pad geometry, coupled BGA diff pairs, and a routing-speed passA batch landed since the June 23 update — much of it driven by re-running the set-1 stress boards and categorizing what still failed — and it shipped as v0.16.0 (the first release on the 0.16 line), with a follow-up v0.16.1 right behind it (its additions are in the last section). Both bundle a rebuilt Rust router with fresh Linux / macOS (arm64 + x86_64) / Windows binaries on GitHub Releases, so the new Rust-accelerated blocking analysis (below) works in the installed plugin. Real pad geometry: comb/finger custom pads (#188)A power MOSFET's large exposed source/drain pad is a notched comb/finger polygon, but the model kept only its Coupled differential-pair escape under a BGA (#182)The dense-BGA under-pad escape engine (#122) used to route both halves of a diff pair single-ended, so Routing robustness
Layer balance & DRC grading
FasterA routing-speed pass with no behaviour change: five hot Python loops in the DRC / fanout / obstacle paths were vectorized, the plane-tap local-window scan was spatial-indexed, keepout rasterization is clipped to the map window, and the blocking-obstacle analysis was ported to the Rust router (v0.16.1) with a C-level set intersection — large speedups on dense boards. HousekeepingA dead-code sweep removed 24 unused functions and dead imports (#187). The CLI/GUI parity discipline held throughout: the Claude plan tab now carries Also in v0.16.1A few more changes landed in the follow-up release:
Full per-board detail is in #117; everything here is on |
Update — June 26: v0.17.0 — exact swept-capsule clearance and a differential-pair escape rewritev0.17.0 is out (now the latest GitHub Release), bundling a rebuilt Rust core (crate 0.17.0) with fresh Linux / macOS (arm64 + x86_64) / Windows binaries. Exact swept-capsule obstacle clearance (#173 / #156)The biggest change under the hood. The obstacle map and DRC used to model a track or via keep-out as a grid-quantized, over-covered box — which is what the recent "floor-vs-ceiling rounding" and "diagonal margin" graze fixes were all working around. The clearance is now computed against the exact swept capsule of the segment/via at its real width — and the exact keep-out is the default (the old opt-in gate is gone), at Differential-pair escape, rewritten (#195 / #197 / #165)The in-function hybrid escape was replaced by a direct-coupled-middle router: a pair's coupled middle routes on any layer, each leg drops its own escape via, and the terminal legs route point-to-point, so a pair now escapes and fully routes inside
Fanout & routing core
Full per-board detail is in #117; everything here is on |
Update — July 1: v0.17.3 — differential-pair hybrid legs, fab-floor cost tiers, and DRC graded at what you routed tov0.17.3 is out (now the latest GitHub Release), bundling fresh Linux / macOS (arm64 + x86_64) / Windows binaries. This post also folds in the two point releases since the v0.17.0 update that never got their own writeup — v0.17.1 (Rust crate → 0.17.1, forbidden-layer support) and v0.17.2 (a binary rebuild). v0.17.3 itself is Python-only on the 0.17.1 crate. Much of this batch came out of re-running the stress corpus and categorizing what still grazed or disconnected. Differential pairs — the hybrid leg, and coupling that holds clearanceThe direct-coupled escape from 0.17.0 got a lot of follow-through, mostly around the hybrid leg (a pair's coupled middle routes on one layer; each leg then breaks out to its terminal):
Fab floors as cost tiers, and DRC graded at what you routed to
Grazes and cleanup that don't disconnect
Steering — forbidden layers
Fanout & decoupling caps
Robustness & housekeeping
Versions
Full per-board detail is in #117; everything here is on main and released as v0.17.3. |


Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Since the March–May update the big themes are one-click distribution and a set of new ways to steer the router. Highlights below; full history in git log.
Distribution & install — now a Plugin & Content Manager plugin
metadata.json, v0.15.4+). Prebuilt Rust router binaries ship via GitHub Releases for Linux x86_64, macOS arm64 + x86_64, and Windows x86_64, bundled into a single cross-platform PCM zip; a small startup resolver picks the right binary for your machine. No local Rust build required.requirements.txtas the source of truth (scipy,shapely— KiCad already bundlesnumpy/wxPython) and offers a one-click pip install. Fixed a deps-install hang on PCM-installed copies.sys.pathand cause stale-code errors likebatch_route() got an unexpected keyword argument) and moves it aside;--keep-pcmopts out. Also fixed a symlink-overwrite error on--symlinkdev installs.docs/release-pipeline.md(tag → CI builds all four platform binaries → PCM submission), including the gotchas and a smoke-test step.Telling the router where to go — and where not to
New ways to steer routing, both by drawing on a User layer and by honoring native KiCad keepouts:
User.1) and the selected nets are routed to follow it as waypoints — source → along your path → target — getting as close as obstacles allow. It's strictly best-effort: a waypoint it can't follow is dropped, so a guide never makes a route fail or adds needless vias, and multiple nets following the same corridor pack alongside one another without overlapping. Endpoints/MST topology are untouched. CLI--guide-corridor; "Follow User-layer guide path" checkbox.User.2) and routed tracks and vias stay out of those areas, on every copper layer — a hard keepout. It applies across single-ended, multipoint, and differential-pair routing, plus plane via-stitching and plane repair. Useful for analog regions, antenna clearances, or mechanical exclusions. CLI--keepout(route.py/route_diff.py); "Keep out of User-layer polygon(s)" checkbox.(zone … (keepout …))rule areas — the ones you create with KiCad's keepout/rule-area tool on copper layers, not a User-layer sketch. It blocks only the disallowed item (tracks and/or vias) on the keepout's listed layers, with copper-edge clearance, and is automatic whenever the board has one (no flag), across every routing type. Thanks to @bergmorten.Route by selection (#6)
Planes
--skip-existing-zonesflag forroute_planes(PR Add --skip-existing-zones flag to route_planes #26, @bergmorten): preserve an existing same-net/same-layer zone and only add stitching vias, instead of recreating it.Under the hood
Versions
VERSIONmirrors the Rust crate'smajor.minor, and the patch is bumped for Python-only changes.Router tuning, honest reporting & speed (mid-June, through b207590)
--grid-step, so the same knobs behave consistently across grid resolutions (Make routing cost knobs mm-based, independent of grid step #69).np.unique(axis=0)row dedupe with a bitmap dedupe — large speedups on base-map builds (adaptive-grid investigation, Don't print a Claude run's error twice in the transcript #67 / Eliminate Python-side routing bottlenecks: bitmap dedupe + vectorized blocking analysis #68; builds also batched, Rust router: use rayon for parallelism #35 / Batch obstacle-map rasterization: 6.4x faster base map builds #61).All reactions