# KiCad bridge verbs

Drive KiCad 7/8/9/10: open designs, DRC/ERC, libraries, 3D, screenshots, lint.

_Part of the [Adom Desktop verb reference](VERB-REFERENCE.md). Invoke as `adom-desktop <verb> '<json>'`._

> **Note:** All kicad_* commands are forwarded to the KiCad bridge (port 8772). Use kicad_<command> format.

### `kicad_bridge_call`

Generic passthrough: call any RPC method on the adom_bridge plugin running inside a specific KiCad exe. Picks the newest alive instance for that exe automatically (or use pid arg to pin to a specific PID). For export_svg / export_pdf use a larger timeout (default 10s; plot can take 5-15s).

**Args:**
  - `exeName` — required (kicad, pcbnew, eeschema, kicad-cli)
  - `method` — required — see methods list
  - `params` — optional dict — method-specific
  - `pid` — optional int — pin to a specific process PID (multi-instance disambiguation, v1.7.6+)
  - `timeout` — optional float seconds (default 10; bump to 30-60 for exports)

**Returns:** {ok, result:<rpc result>, exeName, pid, port} OR {ok:false, errorCode:"plugin_not_running"|"rpc_error", ...}

**Note:** Methods (v1.7.9): introspection — ping, list_frames, get_menu_ids, wm_command{frame_index,menu_id}, get_board_info / get_schematic_info / get_open_editors. PCB graph (pcbnew only) — get_pcb_footprints, get_pcb_layers, get_pcb_nets, get_pcb_design_rules, get_pcb_tracks (start/end/width/layer/netName), get_pcb_pads (per-footprint pads with position/size/drill/netName), get_pcb_vias (position/diameter/drill/viaType/top+bottom layer), get_pcb_drawings (silk text + edge cuts + dimensions), get_pcb_zones (copper pour inventory with priority/isFilled/layers/boundingBox), get_drc_markers (existing markers from last DRC run, grouped by severity), get_footprint_connections{ref} (net-graph: pin → netName → connected (ref,pin) list). Export (pcbnew only) — export_svg / export_pdf via in-process PLOT_CONTROLLER. Library nav — navigate_symbol{symbolName} / navigate_footprint{footprintName} (filter only — does NOT load). select_and_load_symbol{symbolName, useSendInput?:false} / select_and_load_footprint{footprintName, useSendInput?:false}: filter + Down+Enter keystroke. v0.7.0+ (Phase 2.ac) adds optional useSendInput:true that escalates from wx.PostEvent to real Win32 SendInput — more reliable but briefly steals foreground. v0.8.0+ (Phase 2.ad, bridge bundled in v1.7.17) hardens the foreground acquisition: AttachThreadInput dance + SendInput mouse-click at the search ctrl's screen center, with cursor pos snapshot/restore. Pre-v0.8.0 the naive SetForegroundWindow was frequently downgraded to a taskbar flash and SendInput keystrokes landed in the terminal instead of KiCad. Pair with verify_loaded{kind,expectedName?} to confirm load succeeded (reads frame title). DRC trigger — run_drc_inprocess (posts WM_COMMAND 20088 to PCB Editor; ~2-5s; then poll get_drc_markers). Length-matching — get_track_paths_by_net{netName}. Net graph — get_net_topology{netName} returns components on the net + their other-net bridges (1-hop graph).


### `kicad_bridge_status`

Enumerate every running KiCad GUI process that has the adom_bridge.py reverse-bridge plugin loaded. v1.7.6+ supports multi-instance disambiguation: discovery files are per-PID (adom-kicad-bridge-<exe>-<pid>.json) so two pcbnew windows on two different boards each get their own row. Probes each /status to confirm live + returns the full inventory.

**Args:**
  - `exeName` — optional — filter to one exe (kicad / pcbnew / eeschema / kicad-cli)
  - `pid` — optional int — filter to a specific PID
  - `pruneStale` — optional bool (default false) — delete discovery files whose plugin doesn't respond to /status

**Returns:** {ok, plugins:[{exeName, pid, port, version, endpoint, alive, uptimeMs, requestCount, discoveryFile, pruned?}], summary:{total, alive}, pluginAutoInstall:{...}, _hint}

**Note:** Phase 2 reverse bridge (v1.7.x+). If summary.alive=0 but you expect a running KiCad, the plugin isn't deployed — call kicad_install_plugin to force-deploy. Stale discovery files (process exited mid-session) show alive=false; pass pruneStale:true to clean them up.


### `kicad_click`

Click at coordinates in a KiCad window

**Args:**
  - `hwnd` — required
  - `relative` — optional bool (default true, 0.0-1.0 range)
  - `x` — required
  - `y` — required

**Note:** Relative coords are scale-independent — estimate position as percentage from screenshot.


### `kicad_close`

Close all KiCad windows


### `kicad_close_3d_viewer`

Close 3D Viewer window


### `kicad_close_footprint_editor`

Close Footprint Editor window


### `kicad_close_symbol_editor`

Close Symbol Editor window


### `kicad_fix_keyboard`

Release stuck modifier keys + unlock foreground focus


### `kicad_format_upgrade`

Upgrade a KiCad file to the current format via kicad-cli. v1.7.13+. Wraps `kicad-cli {pcb,sch,sym,fp} upgrade`. MUTATES the file in place (kicad-cli has no --dry-run). Use kicad_lint_library/board/schematic first for inspection without write.

**Args:**
  - `filePath` — required file or directory
  - `force` — optional bool (default false) — passes --force to resave even when already current
  - `kind` — optional pcb|sch|sym|fp (auto-detected from extension if omitted)

**Returns:** {success, exitCode, kind, stdout, stderr, source_path, _hint}

**Note:** Common use: lint_library reports fileFormatVersions includes old (pre-20231101) entries, surface that to the user, ask permission to upgrade, then call kicad_format_upgrade. After upgrade, ANY OPEN KiCad windows holding this file must be closed + reopened (they have stale in-memory state).


### `kicad_install_library`

Install a symbol or footprint library

**Args:**
  - `kicadVersion` — optional (default = newest installed; library installs into THAT version's sym-lib-table)
  - `libraryName` — optional
  - `libraryPath` — required
  - `libraryType` — required


### `kicad_install_plugin`

Explicitly (re)deploy the Phase 2 reverse-bridge plugin to every detected KiCad version's USER_SITE. Use when auto-install (which runs once per bridge boot) didn't fire or you need to force a fresh deploy after updating the plugin payload.

**Args:**
  - `force` — optional bool (default true). If false, returns the cached auto-install result instead of redoing the work.

**Returns:** {ok, result:{summary, payloadVersion, perVersion:[...], runningKiCad:[...], _hint}, _hint}

**Note:** Idempotent — SHA256 hash compare skips a no-op deploy. If KiCad is currently running when this fires, the running processes still have the OLD plugin in memory until restart — surface result.runningKiCad to the user and tell them to close+reopen KiCad.


### `kicad_install_symbol`

Decode base64 symbol, install as library, open editor

**Args:**
  - `fileContent` — required base64
  - `fileName` — required
  - `kicadVersion` — optional (default = newest installed)


### `kicad_lint_board`

Headless lint pre-flight for a .kicad_pcb via kicad-cli. v1.7.12+. Comprehensive: file-existence + magic-byte + DRC with --severity-all + --all-track-errors + --schematic-parity (default on). USE THIS BEFORE kicad_open_board for any file you didn't just generate — catches DRC errors, parse issues, format-upgrade-needed BEFORE the GUI opens and possibly hangs on a modal dialog.

**Args:**
  - `filePath` — required .kicad_pcb path
  - `schematicParity` — optional bool (default true) — set false if no matching .kicad_sch exists in the project dir

**Returns:** {success, data:{violations[], summary:{total,errors,warnings,info}, fileFormat:{fileVersion}, schematicParityChecked, source_file}, _hint with tiered guidance}

**Note:** Distinct from kicad_run_drc: lint_board adds file-format sanity + schematic-parity + an AI-friendly tiered _hint that EXPLICITLY tells you to proceed / fix / upgrade based on the result. For schematic + board cross-check during a full design pass: kicad_lint_schematic FIRST (catches ERC issues at the source), THEN kicad_lint_board (catches what made it to the board).


### `kicad_lint_library`

Validate a KiCad library file or directory before install. v1.7.13+. Accepts a single .kicad_sym, single .kicad_mod, .pretty directory, or directory containing .kicad_sym files. Parses S-expression structure (no kicad-cli call — sym/fp upgrade has no --dry-run and would rewrite files). USE BEFORE kicad_install_library / kicad_install_symbol / kicad_install_footprint for any file you didn't just generate.

**Args:**
  - `libraryPath` — required path to .kicad_sym / .kicad_mod / .pretty dir / dir with .kicad_sym files

**Returns:** {success, data:{kind, summary:{symbolCount, footprintCount, symFileErrorCount, modFileErrorCount, fileFormatVersions}, symbols:[{name,pinCount,unitCount,fileVersion,generator,path}], footprints:[{name,padCount,layers,fileVersion,generator,path}]}, _hint with tiered guidance}

**Note:** Detects outdated file formats (pre-KiCad-7 versions <20231101) and suggests kicad_format_upgrade. Magic-byte sniff catches wrong-file-type (e.g. .kicad_pcb mis-named .kicad_sym). Failed-parse files surface as _error rows so you can pinpoint which file in a bulk install is broken.


### `kicad_lint_schematic`

Headless lint pre-flight for a .kicad_sch via kicad-cli. v1.7.12+. File-existence + magic-byte + ERC with --severity-all. USE THIS BEFORE kicad_open_schematic for any file you didn't just generate.

**Args:**
  - `filePath` — required .kicad_sch path

**Returns:** {success, data:{violations[], summary:{total,errors,warnings,info}, fileFormat:{fileVersion}, source_file}, _hint with tiered guidance}

**Note:** ERC catches schematic-only errors (unconnected pins, label mismatches, no-driver nets). For board-level validation use kicad_lint_board. Lint schematic FIRST so you fix issues at their source — DRC may surface them differently downstream.


### `kicad_list_versions`

List every installed KiCad version with paths. Returns versions:[{version, base_dir, kicad_exe, default}], default, count.

**Note:** Run this first if you're not sure which versions are installed. Pass the desired version as kicadVersion on any open_* command to override the default (newest).


### `kicad_open_3d_viewer`

Open KiCad 3D Viewer (board or footprint).

**Args:**
  - `editor` — optional: "auto" (default) | "pcb"|"board" (the PCB's 3D view) | "fp"|"footprint". "auto" prefers the PCB/board viewer when BOTH the PCB and Footprint editors are open — so you do NOT need to close sub-editors to see the board in 3D. Pass editor="pcb" to force the board, editor="fp" for the active footprint.
  - `kicadVersion` — optional (default = newest installed)


### `kicad_open_board`

Open .kicad_pcb in PCB editor

**Args:**
  - `filePath` — required
  - `kicadVersion` — optional (e.g. "9.0" or "10.0"; default = newest installed)


### `kicad_open_editors`

Cross-process inventory of every open KiCad editor frame, sourced via the reverse bridge (NOT screen scraping). Hits each alive plugin's get_open_editors method and concatenates. Replaces the kicad_window_info screenshot-poll pattern for the common case.

**Returns:** {ok, editors:[{kind, exeName, pid, frameTitle, hwnd, isShown}], byKind:{schematic_editor:[...], pcb_editor:[...], symbol_editor:[...], footprint_editor:[...], project_manager:[...]}, summary:{totalEditors, probedPlugins, failedPlugins, byKindCounts}, _hint}

**Note:** v1.7.6+. If totalEditors=0 but the user has KiCad open, the plugins likely aren't deployed or KiCad was launched before plugin install. Use kicad_bridge_status to confirm, kicad_install_plugin to deploy, then ask user to restart KiCad.


### `kicad_open_footprint_editor`

Open Footprint Editor

**Args:**
  - `footprintName` — optional
  - `kicadVersion` — optional (default = newest installed)
  - `libraryName` — optional


### `kicad_open_schematic`

Open .kicad_sch in schematic editor

**Args:**
  - `filePath` — required
  - `kicadVersion` — optional (e.g. "9.0" or "10.0"; default = newest installed)


### `kicad_open_symbol_editor`

Open Symbol Editor

**Args:**
  - `kicadVersion` — optional (default = newest installed)
  - `libraryName` — optional
  - `symbolName` — optional


### `kicad_run_drc`

Run Design Rule Check on a PCB via kicad-cli (headless, fast, structured JSON). Equivalent to right-clicking DRC in pcbnew but no GUI. Returns {data:{violations[], summary:{total,errors,warnings}}}.

**Args:**
  - `filePath` — required
  - `kicadVersion` — optional (default = newest installed)

**Note:** v1.7.12+ ships kicad_lint_board with the same DRC + file-format checks + schematic-parity in one structured response — prefer it over kicad_run_drc for new code.


### `kicad_run_erc`

Run Electrical Rule Check on a .kicad_sch via kicad-cli. v1.7.12+. Mirrors kicad_run_drc but for schematics — catches unconnected pins, duplicate references, hierarchical-label mismatches, no-driver nets, etc. Headless, ~1-3s, structured JSON.

**Args:**
  - `filePath` — required .kicad_sch path

**Returns:** {success, data:{violations[], summary:{total,errors,warnings,info}, fileFormat:{fileVersion}, source_file}, _hint guiding next steps}


### `kicad_screenshot_all`

Screenshot all KiCad windows in one shot

**Returns:** Array of {type, title, hwnd, savedTo, sizeKB}

**Note:** Images downscaled to max 1568px. Use relative coords (0.0-1.0) for clicking — they map to actual window size regardless of image scale.


### `kicad_send_key`

Send keystroke to KiCad window. Supports modifier combos.

**Args:**
  - `hwnd` — optional target HWND
  - `key` — required: a named key (enter/escape/tab/space/f1-f12), a single char, OR a modifier combo like "ctrl+s", "alt+3", "shift+f10", "ctrl+shift+s". Modifiers: ctrl/control, alt/menu, shift, win/super. Case-insensitive.

**Note:** Menu hotkeys work via combos (e.g. "alt+3" = View>3D Viewer in pcbnew, "ctrl+s" = save). For dialogs prefer 'enter'/'escape'. Use click only if tab order doesn't reach the button.


### `kicad_window_info`

List all KiCad windows (project manager, editors, dialogs) with HWNDs and rects

