master
Colby Knox Publish 1.0.154 969d5ad 15d ago

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.