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
Publish 1.0.71
7 files changed
+55−32
dashboard/kicad_dashboard.py+17−9@@ -49,17 +49,24 @@ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path from urllib.parse import unquote, urlparse -VERSION = "3.0.1"+VERSION = "3.1.0" AI_THREAD = "kicad-dashboard" DEFAULT_PORT = 8931 UI_DIR = Path(__file__).resolve().parent / "ui" -# The REAL KiCad logo, extracted from the installed kicad.exe (John, 2026-08-18:-# "just go with the logo the user is familiar with and not try to reinvent the-# wheel" - the old favicon was an invented teal square-and-plus mark). It is the-# icon the user already sees on their own taskbar, so the browser tab, the pup-# window tile and the taskbar badge all agree with KiCad itself.-LOGO_PATH = UI_DIR / "kicad-logo.png"+# SUPERSEDED, and worth stating so nobody re-litigates it. John, 2026-08-18,+# told me to ship the REAL KiCad logo ("go with the logo the user is familiar+# with and not try to reinvent the wheel") after I had invented a teal mark.+# John, 2026-08-24, looking at ah's webview tab strip where this blue filled+# tile sat beside white line icons: "this is awful. all of these should be our+# standard type of icon which is just a line drawing in white on a transparent+# background." The later ruling is narrower and explicit about THIS artifact,+# and adom-ui-design 1.10.0's `icons` skill made it fleet law (rule 4: never+# ship the wrapped vendor's mark - off-palette, filled, trademarked, and it+# turns the tab strip into a logo salad). So the identity icon is now our own+# line drawing of what a KiCad user works on; the 08-18 rule survives only in+# its real scope, which was "do not invent a random abstract mark".+LOGO_PATH = UI_DIR / "dock-kicad.svg" # "Say it" (John via the dock thread, 2026-08-23): teach users how to ASK for # this app by its noun, first and foremost, at the top of the dashboard. The@@ -1121,10 +1128,11 @@ class Handler(BaseHTTPRequestHandler): def do_GET(self): path = urlparse(self.path).path.rstrip("/") or "/"- if path.endswith(("/favicon.png", "/favicon.ico", "/favicon.svg", "/kicad-logo.png")):+ if path.endswith(("/favicon.svg", "/favicon.png", "/favicon.ico",+ "/dock-kicad.svg", "/kicad-logo.png")): # endswith: the adom.cloud proxy mounts the app under a sub-path. try:- return self._send(200, "image/png", LOGO_PATH.read_bytes())+ return self._send(200, "image/svg+xml", LOGO_PATH.read_bytes()) except Exception: return self._json({"error": "logo missing"}, 404) if path == "/health":
dashboard/ui/dock-kicad.svgadded+16@@ -0,0 +1,16 @@+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"+ fill="none" stroke="currentColor" stroke-width="1.7"+ stroke-linecap="round" stroke-linejoin="round" role="img" aria-label="KiCad bridge">+ <!-- What the user works on: a board outline with a 45-degree routed trace+ between two through-hole pads. NOT KiCad's badge (icons skill rule 4:+ never ship the wrapped vendor's mark).+ SIZED FOR 16px, not for 256: a pad ring only keeps its hole if the inner+ radius survives one whole pixel at tab size, so r=2.5 with a 1.7 stroke+ (inner 1.65 units ~= 1.1px at 16). The first cut used r=2 and the rings+ closed into blobs in the tab strip - caught by rendering it beside+ chip-fetcher's and fusion's icons rather than judging it large. -->+ <rect x="2" y="4" width="20" height="16" rx="2"/>+ <path d="M7.5 15.5H9.5L16.5 8.5"/>+ <circle cx="7.5" cy="15.5" r="2.5"/>+ <circle cx="16.5" cy="8.5" r="2.5"/>+</svg>
dashboard/ui/index.html+2−2@@ -4,7 +4,7 @@ <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>KiCad Dashboard</title>-<link rel="icon" type="image/png" href="favicon.png">+<link rel="icon" type="image/svg+xml" href="favicon.svg"> <style> :root{ --bg:#0d1117;--surface:#161b22;--elevated:#1c2128;--overlay:#21262d;--border:#30363d;@@ -241,7 +241,7 @@ main a:hover{border-bottom-color:var(--accent)} <body> <header> <div class="brand" id="brand" tabindex="0">- <img src="kicad-logo.png" alt="KiCad" width="18" height="18">+ <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="flex:none"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M7.5 15.5H9.5L16.5 8.5"/><circle cx="7.5" cy="15.5" r="2.5"/><circle cx="16.5" cy="8.5" r="2.5"/></svg> KiCad Dashboard <span style="color:var(--text-2);font-weight:400">· the KiCad bridge</span> </div> <div class="vsep"></div>
docs/img/dock-kicad.svg+15−18@@ -1,19 +1,16 @@-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="KiCad Dashboard">- <defs>- <linearGradient id="b" x1="0" y1="0" x2="1" y2="1">- <stop offset="0" stop-color="#1f6feb"/>- <stop offset="1" stop-color="#194b9e"/>- </linearGradient>- </defs>- <rect x="2" y="2" width="60" height="60" rx="13" fill="url(#b)"/>- <!-- board traces, so the placeholder reads as a PCB tool at 16px -->- <g stroke="#7ee787" stroke-width="3" fill="none" stroke-linecap="round">- <path d="M14 44 L14 30 L26 30"/>- <path d="M26 30 L38 30 L38 18"/>- <path d="M38 44 L50 44"/>- </g>- <g fill="#00b8a9">- <circle cx="14" cy="46" r="4"/><circle cx="38" cy="16" r="4"/><circle cx="52" cy="44" r="4"/>- </g>- <circle cx="26" cy="30" r="3.2" fill="#f0f6fc"/>+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"+ fill="none" stroke="currentColor" stroke-width="1.7"+ stroke-linecap="round" stroke-linejoin="round" role="img" aria-label="KiCad bridge">+ <!-- What the user works on: a board outline with a 45-degree routed trace+ between two through-hole pads. NOT KiCad's badge (icons skill rule 4:+ never ship the wrapped vendor's mark).+ SIZED FOR 16px, not for 256: a pad ring only keeps its hole if the inner+ radius survives one whole pixel at tab size, so r=2.5 with a 1.7 stroke+ (inner 1.65 units ~= 1.1px at 16). The first cut used r=2 and the rings+ closed into blobs in the tab strip - caught by rendering it beside+ chip-fetcher's and fusion's icons rather than judging it large. -->+ <rect x="2" y="4" width="20" height="16" rx="2"/>+ <path d="M7.5 15.5H9.5L16.5 8.5"/>+ <circle cx="7.5" cy="15.5" r="2.5"/>+ <circle cx="16.5" cy="8.5" r="2.5"/> </svg>
install.sh+1−1@@ -27,7 +27,7 @@ APPDIR="$HOME/.local/share/adom/kicad-bridge" BINDIR="$HOME/.local/bin" mkdir -p "$APPDIR/dashboard/ui" "$BINDIR" cp -f "$H/dashboard/kicad_dashboard.py" "$APPDIR/dashboard/kicad_dashboard.py"-for asset in index.html kicad-logo.png; do+for asset in index.html kicad-logo.png dock-kicad.svg; do [ -f "$H/dashboard/ui/$asset" ] && cp -f "$H/dashboard/ui/$asset" "$APPDIR/dashboard/ui/$asset" done # Settings screenshots (real captures) + the shared Adom cog: the whole tree,
package.json+2−1@@ -1,6 +1,6 @@ { "slug": "kicad-bridge",- "version": "1.0.70",+ "version": "1.0.71", "type": "app", "description": "Skills for your container so your AI knows how to drive the KiCad bridge. The bridge runtime itself is the release zip; Adom Bridge loads that.", "tags": [@@ -40,6 +40,7 @@ "dashboard/kicad_dashboard.py", "dashboard/ui/index.html", "dashboard/ui/kicad-logo.png",+ "dashboard/ui/dock-kicad.svg", "dashboard/ui/assets/shots/taskbar-overlay.png", "dashboard/ui/assets/shots/taskbar-both.png", "dashboard/ui/assets/shots/taskbar-flash.png",
page.json+2−1@@ -4,7 +4,7 @@ "slug": "kicad-bridge", "title": "KiCad - the KiCad Bridge", "brief": "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.",- "version": "1.0.70",+ "version": "1.0.71", "tags": [ "kicad", "pcb",@@ -99,6 +99,7 @@ "dashboard/kicad_dashboard.py", "dashboard/ui/index.html", "dashboard/ui/kicad-logo.png",+ "dashboard/ui/dock-kicad.svg", "dashboard/ui/assets/shots/taskbar-overlay.png", "dashboard/ui/assets/shots/taskbar-both.png", "dashboard/ui/assets/shots/taskbar-flash.png",