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
99f5cc8
12d ago
name: kicad-schematic-and-board-edits description: >- Build and change a KiCad design through the KiCad Bridge without touching the GUI: create a project, draw a schematic (place, rotate, move, wire pin to pin, labels and net stubs, junctions, buses and bus entries, hierarchical sheets and sheet pins, annotate, replace a symbol, reset fields, update from library, batches), read it back (components, pins, items, trace a point, check, design review, PNG render), make symbols and footprints, and edit the board (add, edit, flip, align, delete footprints, mounting holes, outline, layer count, graphics and SVG logos, 3D models, netclasses, board and custom rules, modify or copy tracks, diff pairs, refill, save, update the PCB from the schematic) plus fab outputs (DXF, GenCAD, IPC-2581, IPC-D-356, ODB++, one-zip fab package, fab pre-flight, cost). Trigger words: run python in kicad, pcbnew script, eval, kicad license, bring kicad to front, which dialogs were closed, simulate the circuit, spice simulation, ngspice, transient analysis, AC sweep, frequency response, bode plot, operating point, export spice netlist, draw a schematic, wire these pins, add a net label, add a bus, hierarchical sheet, annotate, replace symbol, create a symbol, create a footprint, new kicad project, add a footprint to the board, flip a part, align parts, mounting hole, board outline, import a logo, netclass, design rules, update pcb from schematic, odb++, ipc-2581, fab package, pcb cost estimate, design review.
Schematic and board edits
Every verb here edits files or the live board the way KiCad would, answers what it did, and refuses with a named
errorCode and a _hint when it cannot. kicad_describe has each verb's exact inputs; the README lists them all.
Schematic (kicad_sch_*, edits the .kicad_sch on disk)
- Build:
sch_create(a new sheet, optionally inside a project),sch_page(paper, title block),sch_place_symbol,sch_connect_pins(a wire from pin to pin, e.g.R1.2toR2.2),sch_connect_to_net(a stub and a label, or a power symbol),sch_wire,sch_label,sch_junction,sch_text,sch_bus,sch_bus_entry,sch_connect_to_bus,sch_no_connect,sch_sheetandsch_sheet_pinsfor hierarchy. - Change:
sch_move,sch_move_region,sch_rotate,sch_split_wire,sch_delete_wire,sch_edit_label,sch_annotate(the standard'sannotate),sch_replace_symbol,sch_reset_fields,sch_update_from_library,sch_fix_connectivity(a dry run first),sch_batch(many of these as one write). - Read and check:
sch_components,sch_pins,sch_items,sch_trace_point,sch_hierarchy,sch_check,design_review(decoupling, I2C pull-ups, reset and enable pins, LED resistors, regulator caps),render_schematic(PNG, with visual baselines),kicad_netlist({net: [Ref.Pin]}and anexpectcheck). - Coordinates are sheet millimetres, y down, on KiCad's 1.27 mm grid; a pin is named
Ref.Number. - Every write keeps a
.bakand reports the ERC change. An open Schematic Editor does not see a file edit until it reloads the sheet: close it first, or reload after.
Simulation (SPICE, headless)
kicad_simulate {schPath, analysis, probes} runs the sheet through ngspice, the simulator KiCad itself uses
(KiCad's own ngspice.dll on Windows), in a child process so a bad circuit cannot take the bridge down:
analysisin the EDA Bridge Standard's form:{type: "ac", sweep: "dec", points: 20, start: 10, stop: 1e6},{type: "tran", step: 1e-5, stop: 5e-3},{type: "dc", source: "V1", start, stop, step},{type: "op"}, or{type: "raw", text: ".noise ..."}; SPICE text (".tran 10u 5m") works too. Without it, the analysis the schematic carries runs.probes:[{net: "OUT"}, {current: "V1"}](or"V(/OUT)"); without them every node and branch comes back (24 at most).availablelists this run's vectors.signals[{signal, x, y, xUnit, yUnit, phase?}]is the answer: each probe's own points, at mostpoints(200) of them with the first, last and extreme points always kept; AC as dB with unwrapped phase in degrees.enginenames the ngspice and KiCad versions;csvPathholds the points.
Every part needs a SPICE model: R, C and L work from their values, sources come from the Simulation_SPICE
library (VSIN, VDC, VPULSE...), ICs need a model file (their Sim.Library field). kicad_export_spice writes
KiCad's netlist (.cir, dialect: ngspice) and says what it holds. Checked: an RC of 1k and 100n is -3 dB at 1.58 kHz, -45 deg.
KiCad's own Python, headless
kicad_eval {code, filePath?} runs a Python snippet with KiCad's bundled Python and its pcbnew module; with
filePath the board is loaded as board, and whatever the snippet sets result to comes back as JSON
(result = sorted(f.GetReference() for f in board.GetFootprints())). kicad_run_script {script, args} runs a
.py of your own the same way. Both read the file, not an open editor's unsaved edits; nothing is saved unless
the code calls board.Save() (close the board in KiCad first). kicad_license_status answers the licence
question plainly (GPL, no seat); kicad_foreground {reason} brings a KiCad window to the person, captioned,
and is refused without a reason; kicad_dialog_log lists the dialogs the bridge dismissed.
Board (kicad_* on a .kicad_pcb)
Parts:
add_footprint(from a library, a .kicad_mod or a copy of a placed part),edit_footprint(value, reference, fields, DNP, attributes),flip_footprint,align_footprints,delete_footprint,update_footprints_from_library,footprint_graphics,footprint_models,place_decoupling.Board:
board_outline,set_layer_count,add_mounting_hole,import_svg(logos),delete_graphics,refill_zones(the standard'srepour),save_board(save),update_pcb_from_schematic(update_pcb).Copper and rules:
modify_track,copy_routing,route_diff_pair(route_pair),plan_fanout,netclasses(net_classes),board_rules,custom_rules(add_rule),check_clearance,score_placement.Open or closed: with the board open in the PCB editor (IPC API on) an edit lands live as one Undo step, guarded by
expectedRevisionand checked by KiCad's DRC first (dryRunchecks without editing). With no editor holding the board it edits the file, keeping a backup. A lock file left by a KiCad that is no longer running is cleared; a lock from another machine is honoured.Adding items to an open board (from 1.0.64). KiCad 10.0.x does not create items from text over its API (checked on 10.0.4 and 10.0.7), so the bridge encodes them as KiCad's protobuf items itself:
board_outlineandimport_svgcreate their shapes live (commit:"create-items", one Undo step);add_footprint(alsoduplicateOfandcount) andadd_mounting_holecreate a part live: KiCad's own encoding is copied when the same library footprint is already on that side of the board, and from 1.0.65 the part is otherwise built from the library's text (pads, graphics, texts, fields, 3D models);- a footprint with custom-shape pads, mask or paste margins or zones inside, and
update_footprints_from_library, refuse withlive_create_unsupported, say why inliveCreateWhyand change nothing: save and close the board (kicad_save_board,kicad_close) and call again, and the file is edited.
Moving, editing, routing and deleting work live. KiCad's API stores every footprint it rebuilds (a move, a field or part edit) without a polygon's repeated closing point; replies name those parts in
closingVerticesDroppedByKiCad(wiki #126).
Libraries and projects
sym_create, sym_info, sym_delete, fp_create, fp_info, fp_edit, search_library (every registered
library, PCM ones included), project_create, project_info, project_rename, project_snapshot.
From 1.0.70, build_schematic {schPath, parts, nets} draws a new sheet (and project) from a netlist with library
symbols: one column per block, a stub and a net label on every connected pin, the title block filled, then KiCad's
own netlist of the sheet compared with the nets pin by pin (mismatches), and ERC. read_sheet_file (1.0.69) reads a
sheet's parts, fields and pins straight from the file.
From 1.0.68, footprint_from_land_pattern builds a footprint from the land pattern a datasheet prints (family
chip, dual, sot, quad or bga; pitch, pad size, span; an exposed pad; the body): pads numbered the IPC way, silkscreen
clear of the copper with a pin-1 dot, a fab outline with a pin-1 chamfer, the courtyard, and a 3D body box (a VRML
file beside the library) when the height is given. The layout is the Altium bridge's, so both tools draw the same
footprint. dryRun returns the pad table (y up, pin 1 top-left) to compare with the datasheet first.
From 1.0.64, the EDA Bridge Standard's library housekeeping:
- Footprint libraries:
copy_footprint,rename_footprint,remove_footprint,xcopy_footprint(across libraries),add_body(a STEP or VRML model onto a library footprint, replacing its models unlesskeepExisting:true). - Symbol libraries:
clone_symbol,rename_symbol(symbols that extend it follow),set_params(fields, the value and the footprint link; a missing field is added hidden),set_visibility,symbol_prims(the drawing, read only). - Sheets and parts:
place_on_sch(library symbols on one new sheet sized to them),doc_params(the title block under the standard's names),sheet_params(the BOM write-back: fields onto placed parts, every unit, on whichever sheet holds each),part_parameters(which fields the parts carry, or one field's values with the parts that lack it). - Checks and channels (1.0.65):
compile(ERC and the netlist, counted by class),list_installed_libraries(every symbol and footprint library KiCad loads, with missing ones flagged),replicate_layout(one channel's placement onto matching channels throughmove_footprint, one Undo step),diff_pairs(the pairs KiCad's router recognises by name, and the net class that sets their width and gap). - The board:
layers(the whole layer set, with what the open editor shows),silk_state(every part's body box, designator and value as placed, and the free silkscreen),ripup_nets(every unlocked track, arc and via of the named nets, live, one Undo step; dry-run first).
Fab outputs
export_fab_package (Gerbers, drill, BOM, CPL, a README, zipped; fab:"jlcpcb" for its columns), export_odb,
export_ipc2581, export_ipc356, export_gencad, export_dxf, validate_for_fab (KiCad's DRC against a fab profile; the standard's fab_check is kicad_fab_check, skill kicad-board-checks),
estimate_cost.
From 1.0.66:
teardrops: adds or removes teardrops with KiCad's own Edit Teardrops dialog on the board open in the PCB editor, counting them before and after and returning the new revision.panelize: steps a rectangular board into a V-score panel as a new board, with nets renamed per copy, rails, V-cuts on Cmts.User, tooling holes and fiducials. Its KiCad DRC is compared with the board's own, sonewErrorscounts only what the panel adds. A shaped board needs mouse bites (KiKit).
The EDA Bridge Standard's shapes (from 1.0.63)
These verbs are in the EDA Bridge Standard (0.3.0), so an AI
that knows the standard can call them under the standard's names and arguments; KiCad's own names and arguments
keep working. kicad_describe marks each one with standardShape.
- Names:
kicad_render_board_3d(render_board),kicad_remove_parts(delete_footprint),kicad_edit_parts(edit_footprint on the board),kicad_align_parts,kicad_remove_graphics,kicad_read_footprint(fp_info),kicad_export_library_part(export_part),kicad_create_part_project(make_part_project, which then refuses to overwrite an existing project unlessoverwrite:true).kicad_edit_footprintwith library arguments (libraryPath+name, noref) edits the LIBRARY footprint (fp_edit), as the standard means it. - Arguments:
sheetandprojectpaths,id/idsfor uuids, mm-named numbers (toleranceMm,gapMm,thresholdMm,widthMm...),bomFieldson IPC-2581,atandboxon import_svg and copy_routing. - Lists are one write:
sch_connect_pins {pairs: [{from, to}]},sch_bus_entry {entries},sch_edit_label {edits},sch_text {texts}andsch_junction {points, remove: [id or [x, y]]}run as onekicad_sch_batch(batchedAssays so).kicad_edit_parts {edits: [{ref, value, dnp...}]}gives each part its own edit in one undo step. - y up:
frame:"standard"takes coordinates with KiCad's y negated. A sheet verb's reply comes back y up too (frame:"standard"in it); a board verb's reply stays in KiCad's frame (inputFrame), andkicad_routing_state {model:"standard"}reads the board back y up. estimate_costnames its pricesource(built-in JLCPCB-style rates, with no recorded check date) and listspricesper quantity.
Every verb here runs in the verb battery on a real Windows box before each release.
---
name: kicad-schematic-and-board-edits
description: >-
Build and change a KiCad design through the KiCad Bridge without touching the GUI: create a project, draw a schematic (place, rotate, move, wire pin to pin, labels and net stubs, junctions, buses and bus entries, hierarchical sheets and sheet pins, annotate, replace a symbol, reset fields, update from library, batches), read it back (components, pins, items, trace a point, check, design review, PNG render), make symbols and footprints, and edit the board (add, edit, flip, align, delete footprints, mounting holes, outline, layer count, graphics and SVG logos, 3D models, netclasses, board and custom rules, modify or copy tracks, diff pairs, refill, save, update the PCB from the schematic) plus fab outputs (DXF, GenCAD, IPC-2581, IPC-D-356, ODB++, one-zip fab package, fab pre-flight, cost). Trigger words: run python in kicad, pcbnew script, eval, kicad license, bring kicad to front, which dialogs were closed, simulate the circuit, spice simulation, ngspice, transient analysis, AC sweep, frequency response, bode plot, operating point, export spice netlist, draw a schematic, wire these pins, add a net label, add a bus, hierarchical sheet, annotate, replace symbol, create a symbol, create a footprint, new kicad project, add a footprint to the board, flip a part, align parts, mounting hole, board outline, import a logo, netclass, design rules, update pcb from schematic, odb++, ipc-2581, fab package, pcb cost estimate, design review.
---
# Schematic and board edits
Every verb here edits files or the live board the way KiCad would, answers what it did, and refuses with a named
`errorCode` and a `_hint` when it cannot. `kicad_describe` has each verb's exact inputs; the README lists them all.
## Schematic (`kicad_sch_*`, edits the .kicad_sch on disk)
- **Build**: `sch_create` (a new sheet, optionally inside a project), `sch_page` (paper, title block),
`sch_place_symbol`, `sch_connect_pins` (a wire from pin to pin, e.g. `R1.2` to `R2.2`), `sch_connect_to_net`
(a stub and a label, or a power symbol), `sch_wire`, `sch_label`, `sch_junction`, `sch_text`, `sch_bus`,
`sch_bus_entry`, `sch_connect_to_bus`, `sch_no_connect`, `sch_sheet` and `sch_sheet_pins` for hierarchy.
- **Change**: `sch_move`, `sch_move_region`, `sch_rotate`, `sch_split_wire`, `sch_delete_wire`, `sch_edit_label`,
`sch_annotate` (the standard's `annotate`), `sch_replace_symbol`, `sch_reset_fields`, `sch_update_from_library`,
`sch_fix_connectivity` (a dry run first), `sch_batch` (many of these as one write).
- **Read and check**: `sch_components`, `sch_pins`, `sch_items`, `sch_trace_point`, `sch_hierarchy`, `sch_check`,
`design_review` (decoupling, I2C pull-ups, reset and enable pins, LED resistors, regulator caps),
`render_schematic` (PNG, with visual baselines), `kicad_netlist` (`{net: [Ref.Pin]}` and an `expect` check).
- Coordinates are sheet millimetres, y down, on KiCad's 1.27 mm grid; a pin is named `Ref.Number`.
- Every write keeps a `.bak` and reports the ERC change. An open Schematic Editor does not see a file edit until
it reloads the sheet: close it first, or reload after.
## Simulation (SPICE, headless)
`kicad_simulate {schPath, analysis, probes}` runs the sheet through ngspice, the simulator KiCad itself uses
(KiCad's own ngspice.dll on Windows), in a child process so a bad circuit cannot take the bridge down:
- `analysis` in the EDA Bridge Standard's form: `{type: "ac", sweep: "dec", points: 20, start: 10, stop: 1e6}`,
`{type: "tran", step: 1e-5, stop: 5e-3}`, `{type: "dc", source: "V1", start, stop, step}`, `{type: "op"}`,
or `{type: "raw", text: ".noise ..."}`; SPICE text (`".tran 10u 5m"`) works too. Without it, the analysis
the schematic carries runs.
- `probes`: `[{net: "OUT"}, {current: "V1"}]` (or `"V(/OUT)"`); without them every node and branch comes back
(24 at most). `available` lists this run's vectors.
- `signals[{signal, x, y, xUnit, yUnit, phase?}]` is the answer: each probe's own points, at most `points`
(200) of them with the first, last and extreme points always kept; AC as dB with unwrapped phase in degrees.
`engine` names the ngspice and KiCad versions; `csvPath` holds the points.
Every part needs a SPICE model: R, C and L work from their values, sources come from the `Simulation_SPICE`
library (VSIN, VDC, VPULSE...), ICs need a model file (their Sim.Library field). `kicad_export_spice` writes
KiCad's netlist (`.cir`, `dialect: ngspice`) and says what it holds. Checked: an RC of 1k and 100n is -3 dB at 1.58 kHz, -45 deg.
## KiCad's own Python, headless
`kicad_eval {code, filePath?}` runs a Python snippet with KiCad's bundled Python and its `pcbnew` module; with
`filePath` the board is loaded as `board`, and whatever the snippet sets `result` to comes back as JSON
(`result = sorted(f.GetReference() for f in board.GetFootprints())`). `kicad_run_script {script, args}` runs a
.py of your own the same way. Both read the file, not an open editor's unsaved edits; nothing is saved unless
the code calls `board.Save()` (close the board in KiCad first). `kicad_license_status` answers the licence
question plainly (GPL, no seat); `kicad_foreground {reason}` brings a KiCad window to the person, captioned,
and is refused without a reason; `kicad_dialog_log` lists the dialogs the bridge dismissed.
## Board (`kicad_*` on a .kicad_pcb)
- **Parts**: `add_footprint` (from a library, a .kicad_mod or a copy of a placed part), `edit_footprint` (value,
reference, fields, DNP, attributes), `flip_footprint`, `align_footprints`, `delete_footprint`,
`update_footprints_from_library`, `footprint_graphics`, `footprint_models`, `place_decoupling`.
- **Board**: `board_outline`, `set_layer_count`, `add_mounting_hole`, `import_svg` (logos), `delete_graphics`,
`refill_zones` (the standard's `repour`), `save_board` (`save`), `update_pcb_from_schematic` (`update_pcb`).
- **Copper and rules**: `modify_track`, `copy_routing`, `route_diff_pair` (`route_pair`), `plan_fanout`,
`netclasses` (`net_classes`), `board_rules`, `custom_rules` (`add_rule`), `check_clearance`, `score_placement`.
- **Open or closed**: with the board open in the PCB editor (IPC API on) an edit lands live as one Undo step,
guarded by `expectedRevision` and checked by KiCad's DRC first (`dryRun` checks without editing). With no editor
holding the board it edits the file, keeping a backup. A lock file left by a KiCad that is no longer running
is cleared; a lock from another machine is honoured.
- **Adding items to an open board (from 1.0.64).** KiCad 10.0.x does not create items from text over its API
(checked on 10.0.4 and 10.0.7), so the bridge encodes them as KiCad's protobuf items itself:
- `board_outline` and `import_svg` create their shapes live (`commit:"create-items"`, one Undo step);
- `add_footprint` (also `duplicateOf` and `count`) and `add_mounting_hole` create a part live: KiCad's own
encoding is copied when the same library footprint is already on that side of the board, and from 1.0.65
the part is otherwise built from the library's text (pads, graphics, texts, fields, 3D models);
- a footprint with custom-shape pads, mask or paste margins or zones inside, and
`update_footprints_from_library`, refuse with `live_create_unsupported`, say why in `liveCreateWhy` and
change nothing: save and close the board (`kicad_save_board`, `kicad_close`) and call again, and the file
is edited.
Moving, editing, routing and deleting work live. KiCad's API stores every footprint it rebuilds (a move, a
field or part edit) without a polygon's repeated closing point; replies name those parts in
`closingVerticesDroppedByKiCad` (wiki #126).
## Libraries and projects
`sym_create`, `sym_info`, `sym_delete`, `fp_create`, `fp_info`, `fp_edit`, `search_library` (every registered
library, PCM ones included), `project_create`, `project_info`, `project_rename`, `project_snapshot`.
From 1.0.70, `build_schematic {schPath, parts, nets}` draws a new sheet (and project) from a netlist with library
symbols: one column per block, a stub and a net label on every connected pin, the title block filled, then KiCad's
own netlist of the sheet compared with the nets pin by pin (`mismatches`), and ERC. `read_sheet_file` (1.0.69) reads a
sheet's parts, fields and pins straight from the file.
From 1.0.68, `footprint_from_land_pattern` builds a footprint from the land pattern a datasheet prints (family
chip, dual, sot, quad or bga; pitch, pad size, span; an exposed pad; the body): pads numbered the IPC way, silkscreen
clear of the copper with a pin-1 dot, a fab outline with a pin-1 chamfer, the courtyard, and a 3D body box (a VRML
file beside the library) when the height is given. The layout is the Altium bridge's, so both tools draw the same
footprint. `dryRun` returns the pad table (y up, pin 1 top-left) to compare with the datasheet first.
From 1.0.64, the EDA Bridge Standard's library housekeeping:
- **Footprint libraries:** `copy_footprint`, `rename_footprint`, `remove_footprint`, `xcopy_footprint` (across
libraries), `add_body` (a STEP or VRML model onto a library footprint, replacing its models unless
`keepExisting:true`).
- **Symbol libraries:** `clone_symbol`, `rename_symbol` (symbols that extend it follow), `set_params` (fields,
the value and the footprint link; a missing field is added hidden), `set_visibility`, `symbol_prims` (the
drawing, read only).
- **Sheets and parts:** `place_on_sch` (library symbols on one new sheet sized to them), `doc_params` (the title
block under the standard's names), `sheet_params` (the BOM write-back: fields onto placed parts, every unit, on
whichever sheet holds each), `part_parameters` (which fields the parts carry, or one field's values with the
parts that lack it).
- **Checks and channels (1.0.65):** `compile` (ERC and the netlist, counted by class), `list_installed_libraries`
(every symbol and footprint library KiCad loads, with missing ones flagged), `replicate_layout` (one channel's
placement onto matching channels through `move_footprint`, one Undo step), `diff_pairs` (the pairs KiCad's
router recognises by name, and the net class that sets their width and gap).
- **The board:** `layers` (the whole layer set, with what the open editor shows), `silk_state` (every part's body
box, designator and value as placed, and the free silkscreen), `ripup_nets` (every unlocked track, arc and via
of the named nets, live, one Undo step; dry-run first).
## Fab outputs
`export_fab_package` (Gerbers, drill, BOM, CPL, a README, zipped; `fab:"jlcpcb"` for its columns), `export_odb`,
`export_ipc2581`, `export_ipc356`, `export_gencad`, `export_dxf`, `validate_for_fab` (KiCad's DRC against a fab profile; the standard's `fab_check` is `kicad_fab_check`, skill kicad-board-checks),
`estimate_cost`.
From 1.0.66:
- `teardrops`: adds or removes teardrops with KiCad's own Edit Teardrops dialog on the board open in the PCB editor,
counting them before and after and returning the new revision.
- `panelize`: steps a rectangular board into a V-score panel as a new board, with nets renamed per copy, rails,
V-cuts on Cmts.User, tooling holes and fiducials. Its KiCad DRC is compared with the board's own, so `newErrors`
counts only what the panel adds. A shaped board needs mouse bites (KiKit).
## The EDA Bridge Standard's shapes (from 1.0.63)
These verbs are in the [EDA Bridge Standard](https://wiki.adom.inc/adom/eda-bridge-standard) (0.3.0), so an AI
that knows the standard can call them under the standard's names and arguments; KiCad's own names and arguments
keep working. `kicad_describe` marks each one with `standardShape`.
- **Names**: `kicad_render_board_3d` (render_board), `kicad_remove_parts` (delete_footprint), `kicad_edit_parts`
(edit_footprint on the board), `kicad_align_parts`, `kicad_remove_graphics`, `kicad_read_footprint` (fp_info),
`kicad_export_library_part` (export_part), `kicad_create_part_project` (make_part_project, which then refuses
to overwrite an existing project unless `overwrite:true`). `kicad_edit_footprint` with library arguments
(`libraryPath` + `name`, no `ref`) edits the LIBRARY footprint (fp_edit), as the standard means it.
- **Arguments**: `sheet` and `project` paths, `id`/`ids` for uuids, mm-named numbers (`toleranceMm`, `gapMm`,
`thresholdMm`, `widthMm`...), `bomFields` on IPC-2581, `at` and `box` on import_svg and copy_routing.
- **Lists are one write**: `sch_connect_pins {pairs: [{from, to}]}`, `sch_bus_entry {entries}`,
`sch_edit_label {edits}`, `sch_text {texts}` and `sch_junction {points, remove: [id or [x, y]]}` run as one
`kicad_sch_batch` (`batchedAs` says so). `kicad_edit_parts {edits: [{ref, value, dnp...}]}` gives each part its
own edit in one undo step.
- **y up**: `frame:"standard"` takes coordinates with KiCad's y negated. A sheet verb's reply comes back y up
too (`frame:"standard"` in it); a board verb's reply stays in KiCad's frame (`inputFrame`), and
`kicad_routing_state {model:"standard"}` reads the board back y up.
- `estimate_cost` names its price `source` (built-in JLCPCB-style rates, with no recorded check date) and lists
`prices` per quantity.
Every verb here runs in the verb battery on a real Windows box before each release.