KiCad - the KiCad Bridge
Public Made by Adomby adom
Reference implementation of the KiCad bridge — multi-instance Python server, forward path via kicad-cli, reverse path via in-process plugin. Most complex of the three bundled bridges.
Releases 18
Standalone per-platform binaries to download and run, no tools needed. The newest is pinned on top.
All releases
Naming sweep per adom/definitions: every surviving bare AD/HD abbreviation in hints, docs and skills now says Bridge (ab) / Hydrogen (ah). No functional change.
Plugin payload 0.9.1: select_and_load now orchestrates on the RPC worker thread — hop 1 sets the search filter, a 0.8s worker-side sleep lets KiCad's LIB_TREE debounce fire on the UI thread, hop 2 activates the pre-selected match (fixed the DataViewEvent constructor to the 3-arg overload). Verified live on AdomLapper: the Symbol Editor title goes to 'Adom:AdomDemo_IC' with zero focus/keyboard/cursor theft. open_symbol_editor now tries this plugin path first and falls back to the PowerShell navigate only when no plugin instance is alive.
Plugin payload v0.9.0: select_and_load's default transport is now background_activate — after the filter pre-selects the best match, it takes dvc.GetSelection() (avoiding the v0.6.0 whole-model walk that segfaulted) and activates it via a posted DATAVIEW_ITEM_ACTIVATED event plus a native VK_RETURN PostMessage to the tree's own hwnd. Zero focus theft, zero cursor movement, zero global keyboard input. useSendInput:true remains as the explicit noisy fallback.
Demo hardening from the live AdomLapper run: _prepare deletes stale KiCad .lck lockfiles in the demo project dir (a force-killed KiCad leaves them; the next open then hits a modal File Open Warning and the sheet stays untitled), and warm-up is idempotent (an existing Schematic+PCB editor pair is reused instead of spawning duplicates on every call).
Three bugs caught in the first live end-to-end demo run on a real laptop: (1) kicad_demo and kicad_export_molecule were missing from the dispatcher's window-spawning verb sets, so the background/focus-restore machinery skipped them and demo windows landed on top of the user's work — both now get capture/restore with the long 16s guard; (2) the demo's self-screenshot helper passed an empty kicad_info to screenshot_all and silently captured nothing; (3) the symbol beat now verifies the part actually loaded onto the canvas instead of narrating over a '[no symbol loaded]' editor.
Rename cut-over (Adom Desktop -> Adom Bridge, page adom/adom-desktop-kicad-bridge -> adom/kicad-bridge). bridge.json updateManifestUrl, docs, homepage and hero now point at the new slug, restoring auto-update (the old API manifest path 404s). The Mesa llvmpipe download URL moved to the new release store. User-facing copy and the KiCad-visible Adom library descriptions now say Adom Bridge; Hydrogen replaces HD. No verb, env, port, or protocol changes.
The caller-identity capture read the wrong place. On a relay call AD delivers the caller in args.caller.aiThread (from the --ai-thread flag or an explicit caller), not the X-Adom-Caller-* headers my 0.9.67 code read - so logging and window-labeling never fired. set_from_request() now reads args.caller first and headers as a fallback (headers remain the outbound direct-API format). Verified against the real wire shape from a live 1.9.183 desktop.
Window labeling for caller identity now locates the raised editor window by its title (Symbol/Footprint/PCB/Schematic Editor, 3D Viewer) instead of needing each open handler to return an hwnd, so desktop_set_window_identity fires for every open verb. Still best-effort and non-blocking.
AD 1.9.180/1.9.183 caller identity. The bridge now captures the X-Adom-Caller-* headers on every request and logs the owning thread in each per-verb log line (caller="chip-fetcher tab 3"), so concurrent-agent interference is reconstructable. New caller_identity module: forward_headers() echoes the three headers and adds X-Adom-Caller-Delegate:kicad, and ad_callback() makes an outbound AD call that carries the identity through (self_caller() for the bridge's own polls). Best-effort desktop_set_window_identity labeling of a raised KiCad window with the owning thread, gated on an hwnd being present. Values are self-asserted: logging/UX only, never authorization.
Watcher description no longer sends users to AD's Settings -> KiCad panel, which was removed in AD 1.9.117. Points at the set_project_watch / trigger_project_watch verbs instead; config keys remain honored.
kicad_demo now returns the SAME shape as fusion_demo (stage, done, narrate, screenshots[{label,path}], steps, _hint), so the AI that HD's installer runs speaks one vocabulary for both bridges. The verb now CAPTURES its own screenshots per beat (labels schematic/board_2d/board_3d match Fusion's) instead of asking the caller to hunt window titles. A beat that cannot open no longer fails the demo: it narrates the skip and moves on ('never end a demo on an error screen'). The not-installed path narrates KiCad's honest advantage — free, open source, no trial clock or feature tier — and installs it on acceptance.
The bridge no longer takes over the user's screen. navigate_symbol.ps1 previously did an Alt-key foreground trick, SetForegroundWindow, SetCursorPos (moving the user's physical mouse) and SendKeys typing — so if you were working, it typed on top of you. It now sets the search box via UIA ValuePattern (no focus) with a WM_SETTEXT fallback and commits with PostMessage. kicad_send_key and kicad_click now PostMessage directly to the target window by default: no focus theft, no cursor movement, and keys can never leak into the user's active app. Modifier chords and canvas clicks that genuinely need real input return errorCode foreground_required with a hint to WARN the user (~5s) and opt in via allowForeground. launch_editor.ps1 de-foregrounded (UIA Invoke needs no focus).
kicad_demo: a first-class, narrated six-step showcase (symbol, its footprint, that part in 3D, a schematic, the 2D board, the 3D board). Generates every asset in code (ships no sample files) and borrows KiCad's own bundled 3D models. If KiCad is missing it OFFERS to install it: kicad_demo {installKiCad:true} installs silently then runs the tour. Each step returns say/pointOut/window so the AI can narrate and screenshot.
Runtime zip slimmed 31%: removed skills/ (already shipped by the container pkg), demo/, README/CONTRIBUTING/plugin-prompt docs, hero fonts and all images. Keeps code, certs/cacert.pem, .ps1 UIA scripts, templates/blank-board.kicad_pcb and the runtime SKILL.md. No functional change.
kicad_export_molecule: one-shot desktop half of the Adom molecule pipeline (STEP export + silkscreen top/bottom renders + sibling sch/pro discovery + exact container next-steps for step2glb -> adom-molecule). capabilities.py grounds schematic-IPC as a KiCad 11 feature (kipy get_schematic).
Publishing hygiene (SDK re-audit #84): runtime zip is now a Release /download/ asset (not a /files blob); manifest repointed + updateManifestUrl added. enable_software_opengl now fetches Mesa llvmpipe from the Release /download/ asset instead of a /files blob.
Legacy-footprint placement + robust background FP-editor 3D. (1) place_footprint now accepts legacy (module ...) footprints (KiCad<=5 / EAGLE-imported / most chip-fetcher parts): the wrapper is normalized to (footprint ...) so the part splices into a preview board cleanly. (2) The Footprint Editor's 3D viewer opens through the embedded plugin instead of an Alt+3 keystroke: the FP editor is a frame inside the pcbnew process, so the bridge resolves that frame index and posts the live-resolved '3D Viewer' menu id to it — no focus theft, and it fixes an UnboundLocalError (VK_MENU) that broke the path entirely. (3) kicad_click rejects out-of-range coords when relative=True instead of clicking far off-screen (which could hit another window's controls and crash KiCad).