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.107: kicad_install_footprint gains model (3D .step/.wrl, base64) -> installs to 3dmodels/Adom + wires the footprint's (model) ref; uninstall removes 3dmodels/Adom
6 files changed
+48−8
BRIDGE_VERSION+1−1@@ -1 +1 @@-0.9.106+0.9.107
adom-bridge-kicad-manifest.json+5−5@@ -1,15 +1,15 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.106",- "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.106/adom-bridge-kicad-v0.9.106.zip",- "sha256": "c0a6ab963c2544b796b32184f211d8decddb7786df984994ca91f92362253d98",- "size": 396973,+ "version": "0.9.107",+ "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.107/adom-bridge-kicad-v0.9.107.zip",+ "sha256": "ec2619331181d5a912a7f6e80674215f0695af32002a116346324877f536830b",+ "size": 397599, "verbPrefixes": [ "kicad_" ], "healthEndpoint": "/status",- "released_at": "2026-08-15T10:18:25Z",+ "released_at": "2026-08-15T10:56:53Z", "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png", "languages": [ "Python",
adom-bridge-kicad-v0.9.107.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.106",+ "version": "0.9.107", "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/install_footprint.py+38@@ -35,6 +35,12 @@ def handle_install_footprint(kicad_info: dict, args: dict) -> dict: - fileContent (required): Base64-encoded .kicad_mod file content - footprintName (optional): Specific footprint to open in the editor - openEditor (optional): Whether to open Footprint Editor (default: true)+ - model (optional): {fileName, fileContent} — a 3D model (.step/.wrl,+ base64, binary-safe) installed to Documents/KiCad/<ver>/3dmodels/Adom/+ and wired into the footprint's (model ...) reference (injected if the+ footprint has none), so kicad_show_3d_chip renders the part. Wiki+ component pages ship symbol+footprint+step; without this the step+ was dropped and the 3D view came up empty. Returns: Dict with:@@ -101,6 +107,35 @@ def handle_install_footprint(kicad_info: dict, args: dict) -> dict: pretty_dir = fp_dir / ADOM_FP_DIR_NAME pretty_dir.mkdir(parents=True, exist_ok=True) + # --- Step 2b: optional 3D model (install + wire into the footprint) ---++ model = args.get("model") or {}+ model_installed = ""+ if model.get("fileName") and model.get("fileContent"):+ try:+ model_bytes = base64.b64decode(model["fileContent"])+ except Exception as e:+ return {"success": False, "error": f"Failed to decode model.fileContent: {e}"}+ models_dir = Path(user_dir) / "3dmodels" / "Adom"+ models_dir.mkdir(parents=True, exist_ok=True)+ model_path = models_dir / Path(model["fileName"]).name+ model_path.write_bytes(model_bytes)+ model_installed = str(model_path)+ model_uri = str(model_path).replace("\\", "/")+ if "(model " in footprint_text:+ import re+ footprint_text = re.sub(r'\(model\s+"[^"]*"', f'(model "{model_uri}"',+ footprint_text, count=1)+ else:+ body = footprint_text.rstrip()+ close = body.rfind(")")+ footprint_text = (body[:close]+ + f' (model "{model_uri}"\n'+ + " (offset (xyz 0 0 0))\n"+ + " (scale (xyz 1 1 1))\n"+ + " (rotate (xyz 0 0 0))\n"+ + " )\n)\n")+ # The .kicad_mod file must be named to match the footprint name inside it dest_file = pretty_dir / f"{footprint_name}.kicad_mod" dest_file.write_text(footprint_text, encoding="utf-8")@@ -144,6 +179,8 @@ def handle_install_footprint(kicad_info: dict, args: dict) -> dict: ] if registered: output_parts.append("registered in fp-lib-table")+ if model_installed:+ output_parts.append(f"3D model installed + referenced: {model_installed}") if editor_opened: output_parts.append(f"Footprint Editor: {editor_output}") elif open_editor:@@ -156,4 +193,5 @@ def handle_install_footprint(kicad_info: dict, args: dict) -> dict: "footprintName": footprint_name, "libraryName": ADOM_FP_LIB_NAME, "editorOpened": editor_opened,+ "model3d": model_installed or None, }
handlers/uninstall.py+3−1@@ -18,7 +18,8 @@ What this bridge creates (and this verb removes): 2. Adom symbol lib — Documents/KiCad/<ver>/symbols/Adom.kicad_sym + its "Adom" row in %APPDATA%/kicad/<ver>/sym-lib-table 3. Adom footprints — Documents/KiCad/<ver>/footprints/Adom.pretty/ + its- "Adom" row in fp-lib-table+ "Adom" row in fp-lib-table + Documents/KiCad/<ver>/3dmodels/Adom/+ (3D models delivered via install_footprint's model arg, 0.9.107) 4. Mesa fallback — opengl32.dll / libgallium_wgl.dll / dxil.dll (+ *.local) that kicad_enable_software_opengl dropped into a KiCad bin/ (KiCad never ships these in bin, so presence == our deploy)@@ -155,6 +156,7 @@ def handle_uninstall(kicad_info: dict, args: dict) -> dict: rm_file(f, "plugin pycache") rm_file(ver_dir / "symbols" / "Adom.kicad_sym", "Adom symbol library") rm_tree(ver_dir / "footprints" / "Adom.pretty", "Adom footprint library")+ rm_tree(ver_dir / "3dmodels" / "Adom", "Adom 3D model library") # lib-table rows (sym + fp) in every config version try: