KiCad - the KiCad Bridge
Public Made by Adomby adom
Drive your own KiCad from an AI, in the background: open every editor, read the whole board as data (the EDA Bridge Standard board model), stack-up, part heights, netlists, place, route, pour, DRC and exports.
master
name: kicad-board-model description: >- Read a KiCad board the way every Adom EDA bridge reads one (the EDA Bridge Standard board model): kicad_routing_state {model:"standard"} gives tracks, arcs, vias, pads with sizes, parts, pours, the outline with its arcs, unconnected counted from the copper and a revision that only moves with copper, parts or the outline, in mm with y up, the same shape altium_routing_state and fusion_routing_state answer. Its companions are kicad_layer_stack (stack-up, copper and dielectric thickness, Dk), kicad_pour_state (copper actually poured), kicad_bodies (3D body boxes and part heights from the model files) and kicad_netlist (nets as Ref.Pin, pin electrical types, expect comparison). Works live from the PCB editor or from the .kicad_pcb file without KiCad running. Trigger words: board summary, list nets, list designators, component pins, component data, layers in use, board model, read the whole board, board as data, standard board model, eda bridge standard, routing_state standard, stack-up, layer stack, dielectric thickness, Dk, copper weight, poured copper, filled area, 3d bodies, part heights, tallest part, component height, netlist, pin types, compare the netlist, check the nets, same as altium, cross-tool, frame standard, y up.
The board model: one shape for every EDA tool
kicad_routing_state {"model":"standard"} answers the board as the EDA Bridge Standard defines it
(adom/eda-bridge-standard, schema/board.schema.json). Altium and Fusion answer the same shape from
altium_routing_state and fusion_routing_state, so a check, a planner or an AI that reads one reads
them all. Without model the verb answers its older KiCad shape (segments, pad groups measured by
KiCad), which AI Flow reads: both stay.
Where it reads from
- Live when the PCB editor has the board and KiCad's IPC API server is on (
kicad_ipc_api): the editor's own serialisation, unsaved edits included.filePathmay be left out when one board is open. - The file otherwise (or with
source:"file"): no KiCad needed, but unsaved edits are not in it. The reply says which (source), andlivesays why a live read was not possible.
The rules it keeps
| Rule | What you see |
|---|---|
| Millimetres, absolute, y up | KiCad's y is negated. frame:"kicad" keeps KiCad's y down. Angles are KiCad's own (counterclockwise as seen) in both frames |
| KiCad layer names | F.Cu, In1.Cu..In30.Cu, B.Cu; *.Cu is a pad on every copper layer (a partial set adds layers) |
| Pad shapes | circle, round (KiCad's oval: a stadium), rect, roundrect; kicadShape keeps KiCad's own name when it differs |
| Custom pads are their bounding rectangle | shape:"rect", rotation 0, kicadShape:"custom", anchor = KiCad's anchor (where tracks land), and copperPoints (the real outline) when the copper is one drawn polygon over the anchor; pads drawn from several shapes keep only the rectangle |
| Net-less copper is kept | net:"": free copper shapes, pours on no net; footprint copper carries ref |
| Outline with arcs | outlineEdges (line, or arc with center, radius, angle1 to angle2 counterclockwise), outline = their start points, cutouts for inner loops, keepouts for rule areas |
unconnected from the copper |
pads, tracks, arcs, vias and the poured copper joined where they touch on a shared layer. splitNets names each piece's pads (what to join). An isolated pour island is isolatedCopper ({net, layer, at, areaMm2}), not a connection to make (KiCad's DRC warns about it the same way) |
revision moves only with copper, parts or outline |
silkscreen, text and refills leave it alone; the order KiCad lists items in does not matter |
Checked against KiCad's own DRC on six of KiCad 10's demo boards (StickHub, CM5 Minima, RoyalBlue54L Feather, Tiny Tapeout, pic_programmer, microwave): the same unconnected count on every one.
Editing with it
- Pass
revisionasexpectedRevisiontokicad_route_net,kicad_move_footprint, the zone and silk verbs: they accept it (and their older 64-character revision). A change to copper, parts or the outline since you read it refuses withstale_boardandcurrentRevision, nothing written. After a call made with it, the reply'srevisionis the new standard one. - Pass
frame:"standard"to the edit verbs to give coordinates exactly as the model reports them (y up):kicad_route_net,kicad_move_footprint,kicad_add_zone,kicad_apply_zone_plan,kicad_add_via,kicad_add_track,kicad_route. Without it they take KiCad's y down. Pad names ("U1.3") work in both.
The companions
| Verb | Standard name | What |
|---|---|---|
kicad_layer_stack |
layer_stack | copper layers top to bottom: copperUm, the dielectric BELOW each (dielectricUm, dk1000 = Dk x 1000, material), planes with their net, masks, finish. fromDefaults:true when the board has no stack-up of its own |
kicad_pour_state |
pour_state | every zone per layer: filledMm2 (poured, holes cut), islands, unfilled, filledAreaByLayerMm2; geometry:false for a small reply |
kicad_bodies |
bodies | every part's 3D body as a box: x0..x1, y0..y1 on the board, z0..z1 above its surface, tallest; noBody lists parts a height check cannot see (no model, file missing) |
kicad_netlist |
netlist | {net: ["U1.8", ...]} across every sheet; expect compares pin by pin (mismatches); parts:true gives each part's pins with electrical types for a schematic review |
Quick reads
Views of the same model, by the standard's names, for when the whole board is more than you need:
kicad_board_summary, kicad_list_nets, kicad_list_designators, kicad_copper_layers, kicad_layers_in_use,
kicad_component_data {designator?}, kicad_component_pins {designator}. All in mm in the standard's frame, live or
from the file like the model.
Pitfalls
- A file read sees what was last saved, including the last fill: refill before trusting pour areas.
- 3D heights come from the model files (a STEP's vertices and circular edges, a VRML's points); a
footprint naming
.wrlreads the.stepbeside it, as KiCad 10 does. Embedded models are innoBody. - KiCad 9 wrote some teardrop blocks without an opening parenthesis; the read repairs that one known
case and says so (
repairedOnRead). Any other damaged file is refused with the line where it breaks.
---
name: kicad-board-model
description: >-
Read a KiCad board the way every Adom EDA bridge reads one (the EDA Bridge Standard board model): kicad_routing_state {model:"standard"} gives tracks, arcs, vias, pads with sizes, parts, pours, the outline with its arcs, unconnected counted from the copper and a revision that only moves with copper, parts or the outline, in mm with y up, the same shape altium_routing_state and fusion_routing_state answer. Its companions are kicad_layer_stack (stack-up, copper and dielectric thickness, Dk), kicad_pour_state (copper actually poured), kicad_bodies (3D body boxes and part heights from the model files) and kicad_netlist (nets as Ref.Pin, pin electrical types, expect comparison). Works live from the PCB editor or from the .kicad_pcb file without KiCad running. Trigger words: board summary, list nets, list designators, component pins, component data, layers in use, board model, read the whole board, board as data, standard board model, eda bridge standard, routing_state standard, stack-up, layer stack, dielectric thickness, Dk, copper weight, poured copper, filled area, 3d bodies, part heights, tallest part, component height, netlist, pin types, compare the netlist, check the nets, same as altium, cross-tool, frame standard, y up.
---
# The board model: one shape for every EDA tool
`kicad_routing_state {"model":"standard"}` answers the board as the EDA Bridge Standard defines it
(adom/eda-bridge-standard, `schema/board.schema.json`). Altium and Fusion answer the same shape from
`altium_routing_state` and `fusion_routing_state`, so a check, a planner or an AI that reads one reads
them all. Without `model` the verb answers its older KiCad shape (segments, pad groups measured by
KiCad), which AI Flow reads: both stay.
## Where it reads from
- **Live** when the PCB editor has the board and KiCad's IPC API server is on (`kicad_ipc_api`): the
editor's own serialisation, unsaved edits included. `filePath` may be left out when one board is open.
- **The file** otherwise (or with `source:"file"`): no KiCad needed, but unsaved edits are not in it.
The reply says which (`source`), and `live` says why a live read was not possible.
## The rules it keeps
| Rule | What you see |
|---|---|
| Millimetres, absolute, **y up** | KiCad's y is negated. `frame:"kicad"` keeps KiCad's y down. Angles are KiCad's own (counterclockwise as seen) in both frames |
| KiCad layer names | `F.Cu`, `In1.Cu`..`In30.Cu`, `B.Cu`; `*.Cu` is a pad on every copper layer (a partial set adds `layers`) |
| Pad shapes | `circle`, `round` (KiCad's oval: a stadium), `rect`, `roundrect`; `kicadShape` keeps KiCad's own name when it differs |
| Custom pads are their bounding rectangle | `shape:"rect"`, rotation 0, `kicadShape:"custom"`, `anchor` = KiCad's anchor (where tracks land), and `copperPoints` (the real outline) when the copper is one drawn polygon over the anchor; pads drawn from several shapes keep only the rectangle |
| Net-less copper is kept | `net:""`: free copper shapes, pours on no net; footprint copper carries `ref` |
| Outline with arcs | `outlineEdges` (line, or arc with center, radius, angle1 to angle2 counterclockwise), `outline` = their start points, `cutouts` for inner loops, `keepouts` for rule areas |
| `unconnected` from the copper | pads, tracks, arcs, vias and the poured copper joined where they touch on a shared layer. `splitNets` names each piece's pads (what to join). An isolated pour island is `isolatedCopper` (`{net, layer, at, areaMm2}`), not a connection to make (KiCad's DRC warns about it the same way) |
| `revision` moves only with copper, parts or outline | silkscreen, text and refills leave it alone; the order KiCad lists items in does not matter |
Checked against KiCad's own DRC on six of KiCad 10's demo boards (StickHub, CM5 Minima, RoyalBlue54L
Feather, Tiny Tapeout, pic_programmer, microwave): the same unconnected count on every one.
## Editing with it
- Pass `revision` as `expectedRevision` to `kicad_route_net`, `kicad_move_footprint`, the zone and silk
verbs: they accept it (and their older 64-character revision). A change to copper, parts or the
outline since you read it refuses with `stale_board` and `currentRevision`, nothing written. After a
call made with it, the reply's `revision` is the new standard one.
- Pass `frame:"standard"` to the edit verbs to give coordinates exactly as the model reports them (y up):
`kicad_route_net`, `kicad_move_footprint`, `kicad_add_zone`, `kicad_apply_zone_plan`, `kicad_add_via`,
`kicad_add_track`, `kicad_route`. Without it they take KiCad's y down. Pad names (`"U1.3"`) work in both.
## The companions
| Verb | Standard name | What |
|---|---|---|
| `kicad_layer_stack` | layer_stack | copper layers top to bottom: copperUm, the dielectric BELOW each (dielectricUm, dk1000 = Dk x 1000, material), planes with their net, masks, finish. `fromDefaults:true` when the board has no stack-up of its own |
| `kicad_pour_state` | pour_state | every zone per layer: filledMm2 (poured, holes cut), islands, `unfilled`, `filledAreaByLayerMm2`; `geometry:false` for a small reply |
| `kicad_bodies` | bodies | every part's 3D body as a box: x0..x1, y0..y1 on the board, z0..z1 above its surface, `tallest`; `noBody` lists parts a height check cannot see (no model, file missing) |
| `kicad_netlist` | netlist | `{net: ["U1.8", ...]}` across every sheet; `expect` compares pin by pin (`mismatches`); `parts:true` gives each part's pins with electrical types for a schematic review |
## Quick reads
Views of the same model, by the standard's names, for when the whole board is more than you need:
`kicad_board_summary`, `kicad_list_nets`, `kicad_list_designators`, `kicad_copper_layers`, `kicad_layers_in_use`,
`kicad_component_data {designator?}`, `kicad_component_pins {designator}`. All in mm in the standard's frame, live or
from the file like the model.
## Pitfalls
- A file read sees what was last saved, including the last fill: refill before trusting pour areas.
- 3D heights come from the model files (a STEP's vertices and circular edges, a VRML's points); a
footprint naming `.wrl` reads the `.step` beside it, as KiCad 10 does. Embedded models are in `noBody`.
- KiCad 9 wrote some teardrop blocks without an opening parenthesis; the read repairs that one known
case and says so (`repairedOnRead`). Any other damaged file is refused with the line where it breaks.