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.168: the plugin-dir loader guarded with an ENV VAR, which children inherit - so after one KiCad process ran it, every KiCad it spawned imported the loader and started nothing. Per-process guard + call adom_bridge.start() directly, with a log trail
5 files changed
+45−28
BRIDGE_VERSION+1−1@@ -1 +1 @@-0.9.167+0.9.168
adom-bridge-kicad-manifest.json+5−5@@ -1,15 +1,15 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.167",- "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.167/adom-bridge-kicad-v0.9.167.zip",- "sha256": "124f5d6a01a20d99540b7757debda09b93364b95f70743e648ad7e2ab50ce2e1",- "size": 444653,+ "version": "0.9.168",+ "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.168/adom-bridge-kicad-v0.9.168.zip",+ "sha256": "df470c89ac11371cbbf17a5c8b86c59f04cc74906c81ebb87a1805f5e7beab22",+ "size": 444853, "verbPrefixes": [ "kicad_" ], "healthEndpoint": "/status",- "released_at": "2026-08-18T13:32:28Z",+ "released_at": "2026-08-18T13:52:13Z", "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png", "languages": [ "Python",
adom-bridge-kicad-v0.9.168.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.167",+ "version": "0.9.168", "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.",
plugin_install.py+38−21@@ -142,33 +142,50 @@ except Exception: _PLUGIN_DIR_LOADER = """\ \"\"\"adom_bridge_plugin - Adom KiCad bridge loader, KiCad plugin-dir entry. -THE 10.0.5 FIX (issue #31, root-caused 2026-08-18). The bridge used to be loaded-by usercustomize.py, which only runs if the interpreter performs site's-execusercustomize() step. KiCad 10.0.5's GUI stopped doing that, so the reverse-bridge never started and kicad_bridge_status read 0 alive while KiCad sat there-running.--KiCad DOES still import every .py in its scripting/plugins directory at startup --verified live on 10.0.5: a probe placed here fired inside kicad.exe and reported-site.USER_SITE already pointing at the bridge's deploy directory. So this file is-the reliable entry point, and the payload it loads is unchanged.+THE 10.0.5 FIX (issue #31). usercustomize.py stopped running in 10.0.5 GUI+processes, so the reverse bridge never started. KiCad DOES still import every+.py in its scripting/plugins directory (verified live on 10.0.5), so this is the+entry point that still fires.++0.9.168: start the payload DIRECTLY rather than re-importing usercustomize, and+guard per-PROCESS. The first cut guarded with an environment variable, which+child processes INHERIT - so once any KiCad process had run the loader, every+KiCad it spawned skipped it silently (imported, compiled a .pyc, started+nothing). A module attribute cannot leak across processes. \"\"\"-try:- import os- import sys+import os+import sys+import tempfile - if not os.environ.get("ADOM_KICAD_BRIDGE_LOADED"):- os.environ["ADOM_KICAD_BRIDGE_LOADED"] = "1"- import usercustomize # noqa: F401 - importing it IS the bootstrap-except Exception:++def _log(msg): try:- import tempfile- import traceback with open(os.path.join(tempfile.gettempdir(),- "adom-kicad-plugin-loader.error.log"), "a") as fh:- fh.write(traceback.format_exc() + chr(10))+ "adom-kicad-plugin-loader.log"), "a") as fh:+ fh.write(msg + chr(10)) except Exception: pass+++try:+ if getattr(sys, "_adom_kicad_bridge_loaded", False):+ _log("skip: already loaded in this process")+ else:+ sys._adom_kicad_bridge_loaded = True+ exe = os.path.basename(getattr(sys, "executable", "") or "").lower()+ _log("loading in " + exe)+ import adom_bridge+ started = None+ for name in ("start", "start_server", "main", "ensure_started"):+ fn = getattr(adom_bridge, name, None)+ if callable(fn):+ started = name+ fn()+ break+ _log("adom_bridge." + str(started) + "() called")+except Exception:+ import traceback+ _log(traceback.format_exc()) """