DESIGN.md@doc · git:20261017.6615543 · 2026-10-17 · sha256 a586c6a2a3efb6ec
DESIGN.md@doc git:20261017.6615543A
Immutable. This exact content never changes and is served at /api/v1/blob/a586c6a2a3efb6ec.
# Design — KiCad agent skill pack
Goal: an agent manipulates ANY KiCad project through small, definitive,
individually-verifiable operations — with visual feedback (renders, diffs)
flowing back to the agent at every step.
## 1. Architecture
```
kicad_lib/
sexp.py lossless quote-aware s-expression parse/serialize (own impl;
kiutils' fixed dataclass schema breaks on new format versions,
kicad-skip is REPL-oriented; we need format-version tolerance);
byte-identical for sch/sym/mod AND pcb (two pts dialects +
col-72 token wrap, mirrors KiCad's shared prettifier)
geom.py 1.27 mm grid, rotation/mirror math, pin world positions
(model.py was folded into cli.probe + sexp helpers — no module)
verify.py geometric verifier — hard rules, run before every write
index.py component index: flatpak libs + project libs → sqlite FTS
source.py internet sourcing: easyeda2kicad (LCSC), SnapEDA/UL zip
import, sym-lib-table/fp-lib-table registration
diff.py triple diff: pixel (render A/B → red/green composite),
semantic (tree diff: symbols/nets added/moved/removed),
ERC set-diff vs baseline
live.py backend adapter: file (KiCad ≤10 sch, lock-file aware;
refuses .kicad_pcb writes under a GUI lock) |
kipy IPC (pcb @ KiCad 9+, sch @ KiCad 11+) | kipy headless
regen.py round-trip for GENERATED schematics: per-sheet snapshot
sidecars, diff vs disk → absorb GUI edits into overrides
(or refuse), netlist connectivity gate
ipc_discovery.py stdlib socket + api.enable_server discovery; also
piped to `ssh H python3 -` for the remote side
live_ops.py live schematic ops (v11) + committed(): one undo step
live_pcb.py live board ops (summary/move/rotate/flip/place/show/
refill/undo/save), validate → commit → read back
live_remote.py ssh unix-socket forward to a GUI on another host
live_headless.py Xvfb + flatpak pcbnew for tests (KiCad 10 has no
GUI-less API server)
cli.py `kx` entry point
```
## 2. Skill pack (workflow-derived, forum-informed)
Pain-point ranking from forums: (1) library/part management, (2) BOM/fab
outputs, (3) review/diff confidence, (4) layout effort, (5) simulation.
| skill | covers |
|-----------------|-----------------------------------------------------------|
| kicad-project | state machine, env detection, lib tables, git hygiene |
| kicad-component | index/search local libs, fetch from internet, register |
| kicad-schematic | atomic schematic ops (evolved current skill) |
| kicad-pcb | footprint staging, placement, DRC |
| kicad-layout | meta-skill: schematic → placed+routed board (freerouting |
| | DSN/SES loop), iterate against DRC + renders |
| kicad-review | visual diff, ERC/DRC set-diff, rule-canon checklist |
| kicad-fab | BOM (grouped, LCSC/JLC columns), gerbers, pos, jobsets |
| kicad-emsim | openEMS via gerber2ems: EM field sim, field-slice PNGs |
| | rendered back to the agent as feedback |
## 3. Project state machine (per manipulation session)
```
CLEAN ──probe──▶ PROBED ──ops──▶ STAGED ──verify──▶ VERIFIED
▲ │ fail: fix or revert
│ ▼
COMMITTED ◀──commit── REVIEWED ◀──render+diff── RENDERED
```
- CLEAN: git clean or checkpoint-committed; lock files checked.
- PROBED: uuids, refs, occupancy, pin geometry, libs read.
- STAGED: edits exist only in memory / scratch copy.
- VERIFIED: geometric verifier 0 violations; paren balance OK.
- RENDERED: SVG→PNG produced; ERC run.
- REVIEWED: pixel+semantic+ERC diff vs baseline judged by agent
against the rule canon; only then write/commit.
- Skills MUST NOT skip states (codifies "the loop" of the v1 skill).
## 4. Atomic operation set (the small definitive steps)
probe · find · fetch · place · move · wire · label · junction ·
set_prop · delete · annotate · erc/drc · render · diff · netcheck ·
stage_fp · route · export
Each op: precondition (state, lock, refs unique) → action → postcondition
(grid, verifier, balance). Each op is diffable and commit-sized.
## 5. Rule canon (distilled from forums; two tiers)
Machine-checked (verify.py): grid 1.27 mm; no diagonal wires; junction
dots at every T/cross connection; no cross-net touch/overlap; every pin
claimed by exactly one net; refs unique project-wide; ERC delta vs
baseline = ∅; netlist members == design intent.
Render-judged (kicad-review checklist): signal flow L→R; V+ up, GND down;
power symbols not long wires; text horizontal; decoupling caps adjacent
to their IC; descriptive UPPERCASE net names; polarity marks visible;
every IC pin accounted for; notes for non-obvious choices; title block
filled; no text collisions.
## 6. Real-time strategy (VALIDATED on nightly 10.99.0 / kipy master)
Schematic IPC is real in the v11 nightly: get_schematic → read items,
create_items/remove_items inside begin/push_commit (= GUI undo steps).
live.py picks backend by probing KICAD_API_SOCKET + `kicad-cli version`
(+ /usr/bin/kicad-cli-nightly; 10.99 counts as v11). File mode: refuse
writes while `~*.lck` present. Known nightly gap: standalone frames
lack the common handler (no save/revert/run_action over IPC) — user
saves; tests/test_live_ipc.py re-maps the gap on every run. kipy from
PyPI is broken for schematics; tools/bootstrap_kipy.sh builds master
(.tools/kicad-python + protoc 29.x + protol + .pth). Do NOT fork/patch
KiCad C++ — consume the nightly (apt PPA `ppa:kicad/kicad-dev-nightly`).
Board IPC on KiCad 10.0.7 (flatpak, kipy 0.8.0 = API 10.0.6) VALIDATED
end to end: get_board/footprints/nets/netclasses/layers, update_items
in a commit (one undo step), flip_items (its OWN undo step even inside
an open commit; setting the layer instead leaves pads on F.Cu),
add_to_selection + run_action common.Control.zoomFitSelection,
refill_zones (one undo step), save, run_action common.Interactive.undo.
The flatpak socket is ~/.var/app/org.kicad.KiCad/cache/tmp/kicad/
api.sock (sandbox TMPDIR=/var/tmp). Remote GUI = ssh -L local.sock:
remote.sock; nng ipc rides it unchanged.
## 7. Testing policy
Everything is exercised on fixtures in tests/ and a dedicated scratch
project (tests/fixtures/testproj/). Real user projects are read-only
inputs for round-trip/parse soak tests. CI gate: round-trip token
equality, verifier mutation tests, ERC-delta on fixture edits.
## 8. Key sources
- IPC API: https://dev-docs.kicad.org/en/apis-and-binding/ipc-api/
- kipy docs: https://docs.kicad.org/kicad-python-main/kicad.html
- kicad-skip: https://github.com/psychogenic/kicad-skip
- kiutils: https://github.com/mvnmgrx/kiutils
- KiRI (visual diff prior art): https://github.com/leoheck/kiri
- easyeda2kicad: https://github.com/uPesy/easyeda2kicad.py
- gerber2ems (openEMS PCB sim): https://github.com/antmicro/gerber2ems
- freerouting: https://github.com/freerouting/freerouting
- Rule canon sources: schemalyzer 30 rules, EEVblog #1129, Hackaday
library-management best practices, KiCad forum threads.