← Commit history

SKILL: schematic edit, autoroute, rescan, progress and the native build documented; house style

John Lauer ·1c85c262a5 ·27d ago ·parent 31bf8c3
1 file changed +79−45
SKILL.md+79−45
@@ -4,7 +4,7 @@ public: true description: "Launch and drive KiCad on the user's laptop (KiCad 7/8/9/10 supported, multi-version side-by-side) from this container via the adom-bridge CLI. Open schematics/boards/symbols/footprints, run DRC, install sym-lib-table / fp-lib-table libraries, show the 3D viewer, capture KiCad window screenshots, send keyboard shortcuts and click coordinates. Trigger words: kicad, open schematic, open board, open pcb, open symbol, open footprint, KiCad symbol editor, KiCad footprint editor, KiCad 3D viewer, run DRC, install KiCad library, sym-lib-table, fp-lib-table, KiCad screenshot, kicad_send_key, kicad_click, kicad_window_info, kicad_screenshot_all, close KiCad, kicad versions, kicad_list_versions, KiCad bridge." --- -# adom-bridge — KiCad bridge+# adom-bridge: KiCad bridge  All commands dispatch to the KiCad Python bridge running alongside the desktop app. Invoke from this container via Bash: @@ -14,15 +14,15 @@ adom-bridge kicad_<action> '<json_args>'  The leading `kicad_` routes the call to the KiCad plugin; the `<action>` names below are the plugin-side command names. -## FIRST-TIME / COLD-START — read before you panic+## FIRST-TIME / COLD-START: read before you panic -A fresh machine can be missing KiCad, or the reverse-bridge plugin auto-installs on your first call. These states are **EXPECTED** — don't declare defeat. Branch on the stable `errorCode` (not the prose), and relay the returned `_hint` to the user verbatim.+A fresh machine can be missing KiCad, or the reverse-bridge plugin auto-installs on your first call. These states are **EXPECTED**: don't declare defeat. Branch on the stable `errorCode` (not the prose), and relay the returned `_hint` to the user verbatim.  | Signal (`errorCode` / field) | What it means | What YOU do | |---|---|---|-| `host_app_not_installed` (generic; `hostApp:"KiCad"`. Legacy alias `kicad_not_installed` in `errorCodeLegacy`) | KiCad (the user's host app) isn't on this machine. Bridge detects host apps but never auto-installs them. | **Don't send the user to download it.** Offer to install it, then run `kicad_upgrade '{}'` — the agent installs the official build from scratch. Then retry. |+| `host_app_not_installed` (generic; `hostApp:"KiCad"`. Legacy alias `kicad_not_installed` in `errorCodeLegacy`) | KiCad (the user's host app) isn't on this machine. Bridge detects host apps but never auto-installs them. | **Don't send the user to download it.** Offer to install it, then run `kicad_upgrade '{}'`: the agent installs the official build from scratch. Then retry. | | `kicad_version_not_installed` | The `kicadVersion` you asked for isn't installed. | Run `kicad_list_versions '{}'`; retry with an installed version or omit `kicadVersion` to use the newest. |-| `pluginAutoInstall` present in a response | Your first `kicad_*` call auto-installed the reverse-bridge plugin into KiCad (idempotent). | Nothing — expected. Subsequent calls are near-zero cost. |+| `pluginAutoInstall` present in a response | Your first `kicad_*` call auto-installed the reverse-bridge plugin into KiCad (idempotent). | Nothing, expected. Subsequent calls are near-zero cost. | | bridge not responding on the first call | Bridge is lazy-spawning the bridge (+ ~9s KiCad detection). | Wait a beat and retry; it binds once and stays up. |  **After a timeout (from 0.9.349):** ab's `_timeoutHint` says to poll `kicad_status`. Its@@ -33,21 +33,21 @@ never started: keep polling, never resend a mutation blindly. `plugins[]` on the plugin liveness, not progress.  **Readiness before you drive:**-- `kicad_readiness '{}'` — read-only, zero side effects: is KiCad installed/ready? (`{detected, ready, versionCount, defaultVersion}`.) There's **no prewarm** — KiCad is a host app you install on request via `kicad_upgrade`, not a downloaded runtime asset.-- `kicad_describe '{}'` — the full machine-readable verb catalog (the completeness escape hatch; the per-call `_hint`s are what carry you in practice).-- `kicad_launch '{}'` — cold-start KiCad's project manager when nothing is running (idempotent, opens in the background). NOTE: `kicad_open_editors` only LISTS editors in a running KiCad — it never launches; use `kicad_launch` for "open KiCad".-- `kicad_uninstall '{}'` — remove every artifact the bridge created on this machine (plugin, Adom libraries, mesa fallback, caches). Part of Adom Bridge's uninstall cascade; `dryRun:true` previews.+- `kicad_readiness '{}'`: read-only, zero side effects: is KiCad installed/ready? (`{detected, ready, versionCount, defaultVersion}`.) There's **no prewarm**: KiCad is a host app you install on request via `kicad_upgrade`, not a downloaded runtime asset.+- `kicad_describe '{}'`: the full machine-readable verb catalog (the completeness escape hatch; the per-call `_hint`s are what carry you in practice).+- `kicad_launch '{}'`: cold-start KiCad's project manager when nothing is running (idempotent, opens in the background). NOTE: `kicad_open_editors` only LISTS editors in a running KiCad, it never launches; use `kicad_launch` for "open KiCad".+- `kicad_uninstall '{}'`: remove every artifact the bridge created on this machine (plugin, Adom libraries, mesa fallback, caches). Part of Adom Bridge's uninstall cascade; `dryRun:true` previews. - For **"what EDA tools do I have"** across all bridges, use Bridge's `bridge_readiness` (see below).  ## Installing KiCad on a fresh machine (hard-won, v0.9.26+)  `kicad_upgrade` downloads the official downloads.kicad.org installer and silent-installs it. Two things that WILL bite on a truly fresh machine, both handled for you now: -- **Install scope is mandatory in silent mode.** KiCad 10's installer is NsisMultiUser: bare `/S` exits instantly with **`rc=666660`** ("invalid command-line parameters") and installs nothing. The bridge auto-picks the scope: **`/allusers`** when the Bridge process is elevated (installs to Program Files), else **`/currentuser`** (installs to `%LOCALAPPDATA%\Programs\KiCad` — **no admin, no UAC prompt at all**). Force it with `kicad_upgrade '{"scope":"user"}'` — that's your answer to *"install KiCad without a UAC prompt."* (Elevation note: on a VM/kiosk the Bridge process may already be elevated even though nobody clicked UAC — an elevated installer that launches the app hands down its admin token. `kicad_upgrade '{"diagnoseOnly":true}'` reports the real token/UAC facts.)-- **Library installs work before KiCad's first launch.** `%APPDATA%/kicad/<ver>/` (the per-user lib tables) doesn't exist until KiCad's first GUI run, so `kicad_install_library`/`_footprint` used to fail *"config directory not found."* The bridge now bootstraps that config (seeding the lib tables from the install template) automatically — installs just work on a never-launched KiCad.+- **Install scope is mandatory in silent mode.** KiCad 10's installer is NsisMultiUser: bare `/S` exits instantly with **`rc=666660`** ("invalid command-line parameters") and installs nothing. The bridge auto-picks the scope: **`/allusers`** when the Bridge process is elevated (installs to Program Files), else **`/currentuser`** (installs to `%LOCALAPPDATA%\Programs\KiCad`: **no admin, no UAC prompt at all**). Force it with `kicad_upgrade '{"scope":"user"}'`: that's your answer to *"install KiCad without a UAC prompt."* (Elevation note: on a VM/kiosk the Bridge process may already be elevated even though nobody clicked UAC, an elevated installer that launches the app hands down its admin token. `kicad_upgrade '{"diagnoseOnly":true}'` reports the real token/UAC facts.)+- **Library installs work before KiCad's first launch.** `%APPDATA%/kicad/<ver>/` (the per-user lib tables) doesn't exist until KiCad's first GUI run, so `kicad_install_library`/`_footprint` used to fail *"config directory not found."* The bridge now bootstraps that config (seeding the lib tables from the install template) automatically, installs just work on a never-launched KiCad.   - From 0.9.278: handed a single-part `.kicad_sym`, it still succeeds but returns `singlePartFile: true` and a hint naming `kicad_install_symbol {"filePath": ...}`, because that call registers the PART as its own library and leaves Adom untouched (wiki #72). -**GPU-less hosts (VM/RDP/server):** KiCad pops a blocking *"Could not use OpenGL"* dialog and the heavy editors may not render. The bridge auto-expires that dialog and switches KiCad to the Cairo software canvas — see **[kicad-interaction](skills/kicad-interaction/SKILL.md)** for the dialog/canvas details.+**GPU-less hosts (VM/RDP/server):** KiCad pops a blocking *"Could not use OpenGL"* dialog and the heavy editors may not render. The bridge auto-expires that dialog and switches KiCad to the Cairo software canvas, see **[kicad-interaction](skills/kicad-interaction/SKILL.md)** for the dialog/canvas details.  ## Multi-version (KiCad 9 + KiCad 10 side-by-side) @@ -62,7 +62,7 @@ adom-bridge kicad_list_versions '{}' Every `kicad_open_*` (and `install_*`, `run_drc`) command accepts an optional **`kicadVersion`** arg to pin a specific install:  ```bash-# Open in KiCad 10 (newest — default if you omit kicadVersion)+# Open in KiCad 10 (newest: default if you omit kicadVersion) adom-bridge kicad_open_board '{"filePath":"C:/designs/foo.kicad_pcb"}'  # Open in KiCad 9 explicitly (e.g. to check that an older project still works)@@ -71,49 +71,49 @@ adom-bridge kicad_open_board '{"filePath":"C:/designs/foo.kicad_pcb","kicadVersi  If you pass a version that's not installed, the bridge returns a hint listing the installed versions. The success response includes `kicadVersionUsed` so you can confirm which install actually ran. -> **Note on libraries / config**: each KiCad version has its own `sym-lib-table` and `fp-lib-table` (in `%APPDATA%/kicad/<version>/`). `kicad_install_library` writes to the table of whichever version was selected — so if the user installs a library and then asks "open it in KiCad 9", you may need to install it under both versions.+> **Note on libraries / config**: each KiCad version has its own `sym-lib-table` and `fp-lib-table` (in `%APPDATA%/kicad/<version>/`). `kicad_install_library` writes to the table of whichever version was selected, so if the user installs a library and then asks "open it in KiCad 9", you may need to install it under both versions. -## "What EDA tools do I have?" — readiness & host-app detection+## "What EDA tools do I have?": readiness & host-app detection -**KiCad is the user's HOST APP. Adom Bridge *detects* it — it won't silently auto-install it as a prewarm/dependency** (Bridge v1.9.47+). But if KiCad isn't found, **do NOT hand the user a manual download** — offer to install it for them and run `kicad_upgrade '{}'`. That verb installs the latest stable from the official downloads.kicad.org installer (silent `/S`, Windows only; may raise a UAC prompt) and **installs from scratch, not just upgrades**. The distinction: Bridge-core never auto-installs a host app, but a user-requested, agent-run install is exactly right.+**KiCad is the user's HOST APP. Adom Bridge *detects* it, it won't silently auto-install it as a prewarm/dependency** (Bridge v1.9.47+). But if KiCad isn't found, **do NOT hand the user a manual download**: offer to install it for them and run `kicad_upgrade '{}'`. That verb installs the latest stable from the official downloads.kicad.org installer (silent `/S`, Windows only; may raise a UAC prompt) and **installs from scratch, not just upgrades**. The distinction: Bridge-core never auto-installs a host app, but a user-requested, agent-run install is exactly right. -- To answer **"what EDA tools / host apps do I have?"** across every bridge, call the Bridge-level verb **`adom-bridge bridge_readiness '{}'`** — Bridge aggregates each bridge's host-app detection (KiCad, Fusion 360, …) into one report. Start here for any "do I have X installed?" question.+- To answer **"what EDA tools / host apps do I have?"** across every bridge, call the Bridge-level verb **`adom-bridge bridge_readiness '{}'`**: Bridge aggregates each bridge's host-app detection (KiCad, Fusion 360, …) into one report. Start here for any "do I have X installed?" question. - For **KiCad specifically**, `adom-bridge kicad_readiness '{}'` is a zero-side-effect read-only probe: `{hostApp, detected, ready, versionCount, defaultVersion, versions[]}`. It does not install the plugin or spawn subprocesses, and works even when KiCad is absent (`detected:false`). Use `kicad_list_versions` when you need the full per-version detail (paths, IPC API, lib tables).  ## Commands  | CLI form | Action | Purpose | Key args | |---|---|---|---|-| `kicad_list_versions` | `list_versions` | Enumerate every installed KiCad version with paths and which one is the default | — |-| `kicad_readiness` | `readiness` | Read-only host-app detection: is KiCad installed/ready? Zero side effects (no plugin load, no subprocess); works even when KiCad is absent. For cross-bridge "what do I have", use Bridge's `bridge_readiness` | — |-| `kicad_check_for_updates` | `check_for_updates` | Read-only: installed KiCad vs latest STABLE (from downloads.kicad.org / KiCad GitLab tags); flags when the install predates the modern IPC/kipy automation API and should be upgraded | — |-| `kicad_upgrade` | `upgrade` | Download the **official** KiCad installer from downloads.kicad.org and silent-install it (`/S`) — **not winget** (winget lags the real release). May raise a UAC prompt to approve | optional `version`, `force` |+| `kicad_list_versions` | `list_versions` | Enumerate every installed KiCad version with paths and which one is the default |: |+| `kicad_readiness` | `readiness` | Read-only host-app detection: is KiCad installed/ready? Zero side effects (no plugin load, no subprocess); works even when KiCad is absent. For cross-bridge "what do I have", use Bridge's `bridge_readiness` |: |+| `kicad_check_for_updates` | `check_for_updates` | Read-only: installed KiCad vs latest STABLE (from downloads.kicad.org / KiCad GitLab tags); flags when the install predates the modern IPC/kipy automation API and should be upgraded |: |+| `kicad_upgrade` | `upgrade` | Download the **official** KiCad installer from downloads.kicad.org and silent-install it (`/S`), **not winget** (winget lags the real release). May raise a UAC prompt to approve | optional `version`, `force` | | `kicad_open_schematic` | `open_schematic` | Open a `.kicad_sch` in the Schematic Editor | `filePath`, optional `kicadVersion` | | `kicad_open_board` | `open_board` | Open a `.kicad_pcb` in the PCB Editor | `filePath`, optional `kicadVersion` | | `kicad_open_symbol_editor` | `open_symbol_editor` | Launch Symbol Editor (optional: open specific library/symbol) | `libraryName`, `symbolName`, optional `kicadVersion` | | `kicad_open_footprint_editor` | `open_footprint_editor` | Launch Footprint Editor | `libraryName`, `footprintName`, optional `kicadVersion` |-| `kicad_open_3d_viewer` | `open_3d_viewer` | Show the board (or footprint) in 3D viewer | `editor` ("auto"/"pcb"/"fp" — "auto" prefers the board when both editors are open, no need to close sub-editors), optional `kicadVersion` |-| `kicad_close_symbol_editor` | `close_symbol_editor` | Close Symbol Editor | — |-| `kicad_close_footprint_editor` | `close_footprint_editor` | Close Footprint Editor | — |-| `kicad_close_3d_viewer` | `close_3d_viewer` | Close 3D viewer | — |+| `kicad_open_3d_viewer` | `open_3d_viewer` | Show the board (or footprint) in 3D viewer | `editor` ("auto"/"pcb"/"fp", "auto" prefers the board when both editors are open, no need to close sub-editors), optional `kicadVersion` |+| `kicad_close_symbol_editor` | `close_symbol_editor` | Close Symbol Editor |: |+| `kicad_close_footprint_editor` | `close_footprint_editor` | Close Footprint Editor |: |+| `kicad_close_3d_viewer` | `close_3d_viewer` | Close 3D viewer |: | | `kicad_close` | `close` | Close KiCad (all editors). From 0.9.347 an editor with unsaved work is NOT killed: the reply says errorCode unsaved_changes with the dialog text. `discardChanges:true` presses Discard for the caller; `force:true` is the only kill | optional `discardChanges`, `force` |-| `kicad_window_info` | `window_info` | Enumerate open KiCad windows (HWND, title, bounds, editor type) | — |+| `kicad_window_info` | `window_info` | Enumerate open KiCad windows (HWND, title, bounds, editor type) |: | | `kicad_install_library` | `install_library` | Register a `.kicad_sym` + `.pretty/` pair in sym-lib-table + fp-lib-table | `libraryPath`, `libraryType`, `libraryName`, optional `kicadVersion` | | `kicad_install_symbol` | `install_symbol` | Add a single symbol to an existing library | `fileName`, `fileContent`, optional `kicadVersion` | | `kicad_install_footprint` | `install_footprint` | Add a single footprint to an existing library | `library`, `footprint_path`, optional `kicadVersion` | | `kicad_run_drc` | `run_drc` | Run DRC on the current board, return violations | `filePath`, optional `kicadVersion` |-| `kicad_fix_keyboard` | `fix_keyboard` | Workaround stuck-modifier bug after screen lock | — |-| `kicad_screenshot_all` | `screenshot_all` | Capture every open KiCad window (lossless PNGs) | — |-| `kicad_send_key` | `send_key` | Single key to an EXACT `hwnd` (e.g. Enter/Escape to a dialog). For modifier CHORDS ("ctrl+s", "alt+3") use Bridge's `desktop_press_key` — don't route chords here. | `hwnd`, `key` |+| `kicad_fix_keyboard` | `fix_keyboard` | Workaround stuck-modifier bug after screen lock |: |+| `kicad_screenshot_all` | `screenshot_all` | Capture every open KiCad window (lossless PNGs) |: |+| `kicad_send_key` | `send_key` | Single key to an EXACT `hwnd` (e.g. Enter/Escape to a dialog). For modifier CHORDS ("ctrl+s", "alt+3") use Bridge's `desktop_press_key`: don't route chords here. | `hwnd`, `key` | | `kicad_click` | `click` | Send a click at (x, y) in a KiCad window | `hwnd`, `x`, `y` |-| `kicad_adom_library_status` | `adom_library_status` | Report whether the Adom shared library is registered | — |+| `kicad_adom_library_status` | `adom_library_status` | Report whether the Adom shared library is registered |: | | `kicad_adom_library_heal` | `adom_library_heal` | Reconcile the Adom library: `mode` merge (default) / repoint / prune; `dryRun` previews. From 0.9.279 `prune` drops symbols KiCad refuses | `mode`, `dryRun` | | `kicad_rescan_libraries` | `rescan_libraries` | Make parts installed while an editor was open visible: refreshes the editor library tree in place (seconds, no restart). Pass `footprints:["Adom:NAME"]` to have each loaded in the Footprint Editor as proof (`verified`). `force:true` is the KiCad process restart, last resort | optional `footprints`, `force` | | `kicad_ipc_api` | `ipc_api` | Read or flip KiCad's IPC API server switch that live routing needs (`{}` reports, `{"enable":true}` writes kicad_common.json, backup kept). KiCad reads it at start: close KiCad, enable, relaunch | optional `enable` | | `kicad_model_check` | `model_check` | Read-only 3D model diagnostics (from 0.9.350): per (model ...) reference, where KiCad looks, whether the file exists and holds geometry, hidden flags, scale; coded warnings with hints. `kicad_show_3d_chip` / `show_3d_board {filePath}` attach a `models` summary and `_modelHint`. renderVerified is always false: the 3D frame is the render proof. A bare relative model path is never looked up next to the .kicad_mod | `library` + `footprintName`, or `boardPath` | | `kicad_list_footprints` | `list_footprints` | Footprints per library, read from the fp-lib-table with URIs expanded like KiCad does (stock Resistor_SMD and friends included, from 0.9.343) | optional `library` | -## The `show_*` family — START HERE for "show me X"+## The `show_*` family: START HERE for "show me X"  **These are the verbs a user's words map onto, and they were missing from this skill entirely until 2026-08-27.** When someone says *"show me the board in@@ -129,7 +129,7 @@ frame, so a single call is both the action and the proof. | `kicad_show_3d_board` | The whole board in 3D | `filePath` | the 3D render self-raises late on slow boxes; the focus guardian handles it | | `kicad_show_3d_chip` | A single part in 3D (the footprint's 3D view) | `libraryName`, `footprintName` | software-OpenGL boxes render slowly; the window can self-raise late (guarded) | | `kicad_show_symbol` | A schematic symbol in the Symbol Editor | `libraryName`, `symbolName` | the symbol must be in an INSTALLED sym-lib-table library |-| `kicad_show_footprint` | A footprint in the Footprint Editor | `libraryName`, `footprintName` | a cold Footprint Editor spawns a fresh pcbnew and loads every fp lib — allow 20-30s |+| `kicad_show_footprint` | A footprint in the Footprint Editor | `libraryName`, `footprintName` | a cold Footprint Editor spawns a fresh pcbnew and loads every fp lib, allow 20-30s | | `kicad_show_library` | A symbol/footprint library, no part loaded | `libraryName` | the library must be registered in the sym-/fp-lib-table |  Two things that are true of every `show_*` verb and are worth knowing once:@@ -141,7 +141,7 @@ Two things that are true of every `show_*` verb and are worth knowing once:   Check `resolvedSymbol` / the returned frame before you tell a user what they   are looking at, especially in a batch. -## Understanding a schematic — netlist & connectivity (0.9.262)+## Understanding a schematic: netlist & connectivity (0.9.262)  Read-only intelligence about the DESIGN itself, not the GUI. All four derive from one headless `kicad-cli` netlist export, so they work with KiCad closed.@@ -154,7 +154,7 @@ from one headless `kicad-cli` netlist export, so they work with KiCad closed. | `kicad_analyze_connections` | Overview: suspected-unconnected pins, power nets, highest-fanout nets and components | `filePath` |  Unlabeled nets are auto-named (`Net-(R1-Pad2)`, `unconnected-(C1-Pad1)`); single-node-nets are usually a missed wire but can be intentional — `kicad_run_erc` is the+nets are usually a missed wire but can be intentional, `kicad_run_erc` is the authoritative check and knows about no-connect flags.  ## Live routing (from 0.9.340)@@ -285,6 +285,40 @@ For optional presentation and recordings, see [demo/routing/README.md](demo/rout They refuse an open board, preserve a `.adom-bak` by default, and never invoke File > Revert. Use the live verbs above for anything the user should watch. +## Schematic edit in place (native build, 1.0.0+)++KiCad 10 has no schematic API, so these verbs edit the `.kicad_sch` file on disk the way eeschema writes it, keep a `.bak` beside it, run ERC before and after through kicad-cli, and report the delta. The open Schematic Editor keeps its in-memory copy: the response's `reloadHint` names the reload (`kicad_close` on the file, then `kicad_open_schematic`), and saving from a stale editor overwrites the edit.++| Verb | What | Args |+|---|---|---|+| `kicad_sch_place_symbol` | Place a library symbol with its pins and instances block; returns the new `uuid` | `filePath`, `libId` ("Device:R"), `reference`, `at` [x, y] mm, `rotation`?, `unit`?, `value`?, `footprint`?, `libraryPath`? |+| `kicad_sch_wire` | A polyline wire | `filePath`, `points` [[x, y], ...] |+| `kicad_sch_label` | A label | `filePath`, `text`, `at`, `kind` local, global, hierarchical, power, `rotation`? |+| `kicad_sch_move` | Move a placed symbol by reference | `filePath`, `reference`, `to` [x, y] |+| `kicad_sch_set_property` | Change or add a property (Value, Footprint, ...) | `filePath`, `reference`, `name`, `value` |+| `kicad_sch_delete` | Delete any item by uuid | `filePath`, `uuid` |++Every response: `success`, `output`, `path`, `backup`, `uuid`, `erc {ran, before, after, delta}`, `reloadHint`. When the KiCad 11 schematic API lands the same verbs switch to it and the reload step disappears.++## Autorouting: `kicad_autoroute` (native build, 1.0.0+)++`{"filePath": B, "engine": "ai" | "freerouting", "nets"?: [...], "dryRun"?: true}`. Without `engine` it answers `engine_required` with both engines described: ask the user which they want before routing.++- **`ai` is the recommendation.** It returns a plan request (pads, nets with their pads, the live routing state when the PCB editor has the board open) and mutates nothing; you then route with `kicad_route_net`, one native undo step per trace, DRC-checked per step, and you can explain every trace. Frontier models route real boards this way (the recorded Astra runs on the adom/codex page rebuilt a 94-footprint board to zero unconnected items).+- **`freerouting`** is reserved for the user who wants a deterministic pass; it answers `not_implemented` (phase 2b) until it ships.++## Rescan after installs: `kicad_rescan_libraries`++Install N parts, call this once, then show them all (wiki #51). It reloads every open editor's library tree in place (seconds, nothing closed) and, given `footprints: ["Lib:Name", ...]`, loads each in the Footprint Editor as proof (`verified`, `probed[]`). `force: true` is the process restart and refuses while KiCad runs unless `confirmRestart: true`.++## Progress and operations++`kicad_progress {}` returns `active[]` frames (phase, stepLabel, percent, ETA, confidence, a `stepShot` of the phase's window) while a slow verb runs; `kicad_status.operations` lists active and recent runs (`yours` filters to your thread); `kicad_verb_times {}` gives per-verb timing stats (count, p50, p90, failures). The native bridge serves these on their own worker threads, so a poll answers in tens of milliseconds during a long open or a routing commit.++## The native build (1.0.0+)++From 1.0.0 the bridge is one Windows executable with no runtime to provision: `kicad_readiness.platform` reports what this build can do (`windowControl`, `uiAutomation`, `dialogSweep`, `focusEtiquette`, `ipcApi`, `silentInstall`) and a verb the OS cannot serve yet answers `not_supported_on_platform` with the owner named. Every window verb reports the rung it used as `mechanism` (`menu`, `uia`, `post`, `spawn`, `existing`, `ipc`). Two facts worth knowing: KiCad runs one IPC API server per machine and the first KiCad process takes it, so a standalone PCB editor opened beside the project manager has none (`no_pcb_frame` says so and names the remedy); and the in-KiCad Python plugin is retired (`kicad_bridge_status`, `kicad_bridge_call`, `kicad_install_plugin` answer `retired: true`), which is what keeps this bridge working when KiCad 11 removes SWIG scripting.+ ## Exports, linting and settings  | CLI form | Purpose | Key args |@@ -301,7 +335,7 @@ File > Revert. Use the live verbs above for anything the user should watch. | `kicad_lint_library` | Lint a symbol/footprint library. From 0.9.279 `kicadParser` is KiCad's OWN verdict (`kicad-cli sym export svg`, read-only); `ok:false` when KiCad refuses a file the structural check passed | `libraryPath` | | `kicad_run_erc` | Run ERC on a schematic (read-only) | `filePath` | | `kicad_format_upgrade` | Upgrade a file to the current KiCad file format | `filePath` |-| `kicad_get_settings` | Read the bridge's user-visible settings (overlay badges, ...) | — |+| `kicad_get_settings` | Read the bridge's user-visible settings (overlay badges, ...) |: | | `kicad_set_settings` | Change bridge settings; applies immediately to live windows | settings keys | | `kicad_place_footprint` | Deterministically place a footprint into a board preview | `fileName`, `fileContent`, `footprintName`, `x`, `y`, `open` | | `kicad_board_pads` | Pads in board coordinates with their nets: the input for routing | `filePath` |@@ -314,14 +348,14 @@ File > Revert. Use the live verbs above for anything the user should watch.  | CLI form | Purpose | |---|---|-| `kicad_status` | Bridge/host-app status — the verb Bridge polls after a non-terminal timeout |+| `kicad_status` | Bridge/host-app status, the verb Bridge polls after a non-terminal timeout | | `kicad_progress` | Structured progress for a long-running background job | | `kicad_verb_times` | Measured per-verb timing history for THIS machine | | `kicad_diagnostics` | Read-only self-inspection (env, detection breakdown, processes, path probe) | | `kicad_plugin_diagnose` | Why is the reverse-bridge plugin not loading? One call, every artifact | | `kicad_install_plugin` | Install the reverse-bridge plugin into KiCad (idempotent) | | `kicad_bridge_status` | Probe running KiCad plugin instances (multi-instance health) |-| `kicad_bridge_call` | Low-level IPC into a live pcbnew/eeschema — `bridge_status` FIRST to find a live instance |+| `kicad_bridge_call` | Low-level IPC into a live pcbnew/eeschema, `bridge_status` FIRST to find a live instance | | `kicad_demo` | Six-beat showcase tour: staged, or a background job with percent/ETA progress |  ## Quick examples@@ -352,24 +386,24 @@ adom-bridge kicad_show_3d_chip '{"libraryName":"Adom","footprintName":"QFN-56-1E  ## Error shape -Every failing response includes a `_hint` field with a human-readable next step — surface it to the user verbatim when a KiCad command fails.+Every failing response includes a `_hint` field with a human-readable next step, surface it to the user verbatim when a KiCad command fails. -## Bridge architecture (v1.8.31+) — you don't need to know any port+## Bridge architecture (v1.8.31+): you don't need to know any port -Earlier versions of the KiCad bridge listened on hardcoded port `8772`. **As of v1.8.31, bridges use OS-assigned ephemeral ports** — every spawn gets a new free port. You never need to know it.+Earlier versions of the KiCad bridge listened on hardcoded port `8772`. **As of v1.8.31, bridges use OS-assigned ephemeral ports**: every spawn gets a new free port. You never need to know it.  - The CLI (`adom-bridge kicad_*`) automatically routes through adom-desktop's direct API (default port 47200 as of v1.8.33, with auto-fallback to 47201-47209 if 47200 is taken). adom-bridge then forwards to the bridge's actual runtime port.-- The bridge port is internal plumbing and can change every spawn. `bridge_list` reports it as `spawn.runtimePort` for debugging only — do NOT hardcode that anywhere.+- The bridge port is internal plumbing and can change every spawn. `bridge_list` reports it as `spawn.runtimePort` for debugging only, do NOT hardcode that anywhere. - Why: this lets adom-bridge coexist with Hydrogen (which used to claim 8772 itself) and any other tool that grabs ports in the 8000 range. Side-by-side bridges from different apps no longer collide.-- The relay path (Docker → wss proxy → Windows GUI) is unchanged — same `adom-bridge kicad_*` verbs, same JSON shape.+- The relay path (Docker → wss proxy → Windows GUI) is unchanged, same `adom-bridge kicad_*` verbs, same JSON shape.  If you ever find yourself wanting to talk directly to the KiCad bridge process: don't. Go through the verb dispatch. If the verb you need doesn't exist, request a feature in `adom-inc/adom-desktop`.  ## Related -- `adom-desktop-discovery` (gallia) — ensures the CLI + relay are installed.-- `adom-desktop-fusion` — sibling bridge for Fusion 360.-- `adom-desktop-direct-api` — the direct API contract (port 47200 + 47201-47209 fallback, discovery file at `~/.adom/direct-api-port`).+- `adom-desktop-discovery` (gallia), ensures the CLI + relay are installed.+- `adom-desktop-fusion`: sibling bridge for Fusion 360.+- `adom-desktop-direct-api`: the direct API contract (port 47200 + 47201-47209 fallback, discovery file at `~/.adom/direct-api-port`). - Repo: `adom-inc/adom-desktop/plugins/kicad/`  ## KiCad's verdict vs the bridge's reader (from 0.9.279)