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.90: fp editor cold-start — retry the PM plugin menu tier AFTER launching the PM (tier order bug)
5 files changed
+41−8
BRIDGE_VERSION+1−1@@ -1 +1 @@-0.9.89+0.9.90
adom-bridge-kicad-manifest.json+5−5@@ -1,15 +1,15 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.89",- "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.89/adom-bridge-kicad-v0.9.89.zip",- "sha256": "b87fcfd194b84814d8530441d0cf827bc13741275e98207159558419c5044f70",- "size": 384185,+ "version": "0.9.90",+ "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.90/adom-bridge-kicad-v0.9.90.zip",+ "sha256": "c7a69fa43582c41d071b8d4168f5696f0ab9e736e90351b737babc43c8ab4171",+ "size": 384541, "verbPrefixes": [ "kicad_" ], "healthEndpoint": "/status",- "released_at": "2026-08-14T18:35:39Z",+ "released_at": "2026-08-14T18:37:30Z", "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png", "languages": [ "Python",
adom-bridge-kicad-v0.9.90.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.89",+ "version": "0.9.90", "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-bridge", "author": "Adom Inc.",
handlers/open_footprint_editor.py+34−1@@ -616,6 +616,39 @@ def handle_open_footprint_editor(kicad_info: dict, args: dict) -> dict: except Exception as e: # pylint: disable=broad-except pathways_tried.append(f"uia-error:{type(e).__name__}") + # Tier 1.75 (v0.9.90, cold-start fix): the plugin tier (WM_COMMAND 20013)+ # ran BEFORE the project manager existed, so on a cold box it never got a+ # chance. The PM we just launched binds its plugin within seconds+ # (kicad.exe is the one process that reliably does — issue #21), so WAIT+ # for it and retry the menu command.+ if not fp_hwnd:+ try:+ from handlers.bridge_client import _resolve_plugin, try_wm_command_via_bridge+ deadline = time.monotonic() + 20.0+ info = None+ while time.monotonic() < deadline:+ info, err = _resolve_plugin("kicad")+ if err is None and info:+ break+ time.sleep(1.0)+ if info:+ t175 = try_wm_command_via_bridge(+ exe_name="kicad", menu_id=KICAD_FOOTPRINT_EDITOR_CMD_ID, frame_index=0,+ )+ pathways_tried.append(+ "plugin-postlaunch" if t175.get("success")+ else f"plugin-postlaunch-failed:{t175.get('errorCode','')}")+ if t175.get("success"):+ for _ in range(16):+ time.sleep(0.5)+ fp_hwnd = _find_footprint_editor()+ if fp_hwnd:+ break+ else:+ pathways_tried.append("plugin-postlaunch-no-plugin")+ except Exception as e: # pylint: disable=broad-except+ pathways_tried.append(f"plugin-postlaunch-error:{type(e).__name__}")+ # Tier 2: legacy launcher-icon click — DISABLED BY DEFAULT. It MOVES the # user's mouse cursor (SetCursorPos) and needs the manager foregrounded, so # it hijacks the desktop mid-work. The bridge must never do that (John,@@ -634,7 +667,7 @@ def handle_open_footprint_editor(kicad_info: dict, args: dict) -> dict: else: pathways_tried.append("icon_click_skipped_background_mode") - if not opened:+ if not opened and not fp_hwnd: return { "success": False, "error": "Could not open the Footprint Editor via the background (plugin) path.",