app
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.
← Commit history
v0.9.68: #12.3 window labeling finds the editor window by title (no hwnd threading) so it fires for every open verb
5 files changed
+31−22
BRIDGE_VERSION+1−1@@ -1 +1 @@-0.9.67+0.9.68
adom-bridge-kicad-manifest.json+5−5@@ -1,15 +1,15 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.67",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-kicad-bridge/0.9.67/adom-bridge-kicad-v0.9.67.zip",- "sha256": "62752964540ef2e2fd5410b6969418da23b2750c4405f0d981a3214301e81c69",- "size": 365363,+ "version": "0.9.68",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-kicad-bridge/0.9.68/adom-bridge-kicad-v0.9.68.zip",+ "sha256": "3ef797c8bf20ce21aaafbc43e5c79baef2fb137242ae392497ca58428f03e382",+ "size": 365433, "verbPrefixes": [ "kicad_" ], "healthEndpoint": "/status",- "released_at": "2026-07-25T13:41:07Z",+ "released_at": "2026-07-25T13:54:24Z", "hero": "https://wiki.adom.inc/blob/app/adom-desktop-kicad-bridge/kicad-hero.png", "languages": [ "Python",
adom-bridge-kicad-v0.9.68.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.67",+ "version": "0.9.68", "description": "Reverse bridge for KiCad \u2014 board/schematic introspection, lint via kicad-cli, plugin install, multi-instance probe, in-process DRC.", "homepage": "https://wiki.adom.inc/adom/adom-desktop", "author": "Adom Inc.",
server.py+24−15@@ -736,23 +736,32 @@ def dispatch_command(command: str, args: dict) -> dict: except Exception: pass - # #12.3: label the KiCad window we just raised with the owning AI thread,- # so the USER's taskbar/Alt-Tab shows which of their ~20 tabs owns it. Uses- # the caller captured in do_POST and forwards it (via kicad) per #13. Best- # effort and non-blocking: if AD is unreachable, or this is a loopback- # caller with no identity, we simply skip — never fail the user's verb.+ # #12.3: label the KiCad window this verb raised with the owning AI thread,+ # so the USER's taskbar/Alt-Tab shows which of their ~20 tabs owns it. We+ # find the window by matching the editor TITLE for the verb (open handlers+ # don't return hwnd, and threading it through ~30 return sites is fragile),+ # then forward the caller identity (via kicad) per #13. Best-effort and+ # non-blocking: no caller, no AD, or window not found -> skip silently,+ # never fail the user's verb. try: _thread = caller_identity.thread_name()- _hwnd = result.get("hwnd") or (result.get("data") or {}).get("hwnd") if isinstance(result, dict) else None- # TODO: open_* handlers don't surface hwnd yet, so this only fires for- # verbs that do (place_footprint). Wire hwnd into the open handlers'- # results to light up labeling for every editor window.- if _thread and _hwnd:- caller_identity.ad_callback("desktop_set_window_identity",- {"hwnd": int(_hwnd), "appName": f"KiCad ({_thread})",- "tooltip": f"KiCad · driven by {_thread}"})- if isinstance(result, dict):- result["_windowLabeledFor"] = _thread+ if _thread and isinstance(result, dict) and result.get("success"):+ _titles = {+ "open_symbol_editor": "Symbol Editor",+ "open_footprint_editor": "Footprint Editor",+ "open_board": "PCB Editor",+ "open_schematic": "Schematic Editor",+ "open_3d_viewer": "3D Viewer",+ }.get(command)+ if _titles:+ from handlers.kicad_ui import _find_all_kicad_windows+ _match = next((w for w in _find_all_kicad_windows()+ if _titles.lower() in (w.get("title") or "").lower()), None)+ if _match:+ caller_identity.ad_callback("desktop_set_window_identity",+ {"hwnd": int(_match["hwnd"]), "appName": f"KiCad ({_thread})",+ "tooltip": f"KiCad {_titles} - driven by {_thread}"})+ result["_windowLabeledFor"] = _thread except Exception: pass