← Commit history

Publish 1.0.4

John Lauer ·e9ff5f0c42 ·3mo ago ·parent bcec34d
4 files changed +351−339
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-desktop-kicad-bridge",-  "version": "1.0.3",+  "version": "1.0.4",   "type": "app",   "description": "KiCad bridge for Adom Desktop.",   "tags": [
page.json+1−1
@@ -4,7 +4,7 @@   "slug": "adom-desktop-kicad-bridge",   "title": "Adom Desktop - 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.3",+  "version": "1.0.4",   "tags": [     "kicad",     "pcb",
skills/kicad-3d-models/SKILL.md+184−184
@@ -1,184 +1,184 @@-----name: kicad-3d-models-description: Add standard KiCad 3D models to a .kicad_pcb file (especially tscircuit exports that ship without model references), open the 3D viewer in KiCad on the user's desktop, and screenshot to verify. Trigger words — 3d models in kicad, kicad 3d viewer, alt+3, no 3d chips, missing 3d models, add 3d models, kicad 3d screenshot, show me 3d in kicad, prove 3d works, kicad models missing.------# kicad-3d-models--**Prerequisite: Read `kicad-interaction` skill first.** It covers state checks, window management, and dialog handling that this skill depends on.--Add KiCad-standard 3D model references to `.kicad_pcb` files, push to the user's desktop, open the 3D viewer, and screenshot to prove it worked.--## When to use--- User opens a tscircuit-exported `.kicad_pcb` in KiCad and sees no 3D models (Alt+3 shows bare board)-- User asks to add 3D models to a KiCad PCB-- User wants to see/screenshot the KiCad 3D viewer--## Why tscircuit exports lack 3D models--`tsci export -f kicad_pcb` produces valid PCB layouts (pads, traces, silkscreen, board outline) but does **not** inject `(model ...)` entries into footprint blocks. KiCad's 3D viewer needs those entries to know which `.step`/`.wrl` file to render for each component.--## Step 1 — Discover the KiCad 3D model environment variable--KiCad versions use version-specific env vars. Query `service-kicad` to get the correct one:--```bash-service-kicad fp fetch Resistor_SMD R_0402_1005Metric 2>&1 | grep "model"-```--This returns something like:-```-(model "${KICAD10_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0402_1005Metric.step"-```--The `${KICAD10_3DMODEL_DIR}` prefix is what you need. Adjust for the KiCad version on the user's desktop.--## Step 2 — Map footprint types to 3D models--List the unique footprint types in the `.kicad_pcb`:--```bash-grep -A1 "(footprint" board.kicad_pcb | grep '"tscircuit:' | sort -u-```--Then build a mapping. Common tscircuit footprint → KiCad 3D model mappings:--| tscircuit footprint | KiCad 3D model path |-|---|---|-| `tscircuit:resistor_0402` | `Resistor_SMD.3dshapes/R_0402_1005Metric.step` |-| `tscircuit:resistor_0603` | `Resistor_SMD.3dshapes/R_0603_1608Metric.step` |-| `tscircuit:resistor_0805` | `Resistor_SMD.3dshapes/R_0805_2012Metric.step` |-| `tscircuit:capacitor_0402` | `Capacitor_SMD.3dshapes/C_0402_1005Metric.step` |-| `tscircuit:capacitor_0603` | `Capacitor_SMD.3dshapes/C_0603_1608Metric.step` |-| `tscircuit:capacitor_0805` | `Capacitor_SMD.3dshapes/C_0805_2012Metric.step` |-| `tscircuit:led_0603_color(...)` | `LED_SMD.3dshapes/LED_0603_1608Metric.step` |-| `tscircuit:TYPE-C-31-M-12` | `Connector_USB.3dshapes/USB_C_Receptacle_HRO_TYPE-C-31-M-12.step` |-| `tscircuit:chip` (machine pins) | Skip or use a small placeholder |--For non-standard footprints, use `service-kicad fp fetch <library> <name>` to look up the model path. Common KiCad 3D model libraries:--- `Resistor_SMD`, `Resistor_THT`-- `Capacitor_SMD`, `Capacitor_THT`-- `LED_SMD`, `LED_THT`-- `Connector_USB`, `Connector_PinHeader`-- `Package_SO`, `Package_QFP`, `Package_BGA`, `Package_DFN_QFN`--## Step 3 — Inject model entries--Write a Python script that:-1. Reads the `.kicad_pcb` file-2. For each `(footprint ...)` block, identifies the footprint type from the line after `(footprint`-3. Finds the closing `)` of the footprint block (by tracking paren depth)-4. Inserts a `(model ...)` block before the closing paren--Model block format:-```-    (model "${KICAD10_3DMODEL_DIR}/Library.3dshapes/ModelName.step"-      (offset (xyz 0 0 0))-      (scale (xyz 1 1 1))-      (rotate (xyz 0 0 0))-    )-```--Verify the result:-```bash-grep "KICAD.*3DMODEL" board.kicad_pcb | sort | uniq -c-```--## Step 4 — Send to desktop and open in KiCad--**CRITICAL: Close all existing KiCad windows BEFORE opening the updated file.** Opening the same file twice creates "File Open Warning" dialogs and leaves stale editors around.--```bash-# Always close first-adom-desktop kicad_close '{}'--# Send files (send PCB and any sidecar STEP/WRL separately if >1MB total to avoid 413)-adom-desktop send_files '{"filePaths":["/path/to/board.kicad_pcb"],"category":"kicad"}'-adom-desktop send_files '{"filePaths":["/path/to/USB_C_model.wrl"],"category":"kicad"}'--# Open fresh-adom-desktop kicad_open_board '{"filePath":"C:/Users/john/Downloads/board.kicad_pcb"}'-```--Wait for the PCB editor to load, then check for dialogs:-```bash-adom-desktop kicad_window_info '{}'-```--## Step 5 — Open the 3D viewer and screenshot--```bash-# Open the 3D viewer (equivalent to Alt+3)-adom-desktop kicad_open_3d_viewer '{"hwnd": <pcb_editor_hwnd>}'--# Wait for rendering, then check the viewer window appeared-sleep 5-adom-desktop kicad_window_info '{}'--# Screenshot the 3D viewer window-adom-desktop desktop_screenshot_window '{"hwnd": <3d_viewer_hwnd>}'-```--The screenshot saves to `/tmp/adom-desktop-screenshots/`. The file is already on Docker — read it with the Read tool to verify the 3D models rendered correctly.--## Handling missing models (e.g. manufacturer-specific USB-C connectors)--Some footprints reference 3D models that aren't in KiCad's standard `packages3D` distribution. Common case: `USB_C_Receptacle_HRO_TYPE-C-31-M-12` ships in the KiCad footprint library but has no matching STEP in packages3D.--**Fix: relative path + ship the STEP alongside the PCB.**--1. Find a visually similar model that IS available:-   ```bash-   service-kicad model fetch "Connector_USB.3dshapes/USB_C_Receptacle_GCT_USB4105-xx-A_16P_TopMnt_Horizontal.step" --out /tmp/usbc-standin.step-   ```-2. Rename it to match the expected filename and place it next to the `.kicad_pcb`-3. Change the model reference in the PCB to a relative path:-   ```-   (model "./USB_C_Receptacle_HRO_TYPE-C-31-M-12.step" ...)-   ```-4. Send BOTH the `.kicad_pcb` and the `.step` file to the desktop (send separately if the STEP triggers a 413 payload-too-large error)--Test with `service-kicad model fetch` first — if it 404s, the model isn't in packages3D and needs this workaround.--**CRITICAL: WRL unit conversion.** KiCad interprets WRL/VRML coordinates as **inches**. If you convert an OBJ/GLB/STL (which are typically in mm) to WRL, you MUST divide all vertex coordinates by 25.4. Without this, the model renders 25.4x too large. STEP files don't have this problem — KiCad reads STEP as mm natively.--## Up-axis rotation convention--STEP files are authored with different up-axis conventions. KiCad uses Z-up. When injecting `(model ...)` references, read `chosen_up_axis` from chip-fetcher's `info.json` to determine the correct rotation:--| `chosen_up_axis` | Source convention | KiCad rotation needed |-|---|---|---|-| `z` | Z-up (KiCad native) | `(rotate (xyz 0 0 0))` |-| `y` | Y-up (Fusion 360, many vendors) | `(rotate (xyz -90 0 0))` |--If `info.json` says `chosen_up_axis: "y"` and you use `(rotate (xyz 0 0 0))`, the model will render sideways or upside-down in KiCad. chip-fetcher's dashboard shows the orientation visually (Z-up/Y-up thumbnail icons) -- check it BEFORE writing the model reference.--See the [`board-building-pipeline`](../board-building-pipeline/SKILL.md) skill for the full up-axis table and how `chosen_up_axis` flows through the entire pipeline (chip-fetcher -> step2glb -> chiplinter -> chipfit -> KiCad footprint writer).--## Footprint source matters (CRITICAL)--When injecting a model reference for a non-standard component, the STEP model and the footprint MUST come from the same source:--- The STEP model from chip-fetcher was designed to match the chip-fetcher footprint (.kicad_mod), **NOT** the tscircuit-exported footprint-- If you source a STEP from SnapMagic/Mouser/manufacturer, you must ALSO use the footprint from that same source-- Replace the entire footprint block in the .kicad_pcb, preserving only the board placement coordinates `(at X Y rot)`--**Why this matters:** A tscircuit footprint and a SnapMagic footprint for the same component (e.g. USB-C HRO TYPE-C-31-M-12) have completely different pad positions and mounting hole locations. Bolting the SnapMagic STEP onto the tscircuit footprint causes pads to be misaligned even though the STEP renders in the 3D viewer -- the model just floats above the wrong pad locations.--**How to replace a footprint block:**-1. Open the chip-fetcher .kicad_mod file for the component-2. Find the matching `(footprint ...)` block in the .kicad_pcb-3. Note the `(at X Y rot)` line from the original block (board placement)-4. Replace the entire footprint block with the chip-fetcher version-5. Update the `(at ...)` line to use the original board placement coordinates-6. Ensure the `(model ...)` reference points to the STEP from the same source--## Checklist before reporting success--- [ ] Model count matches expected component count-- [ ] Screenshot shows 3D component packages (not a bare green board)-- [ ] USB-C connector visible if present-- [ ] LED packages visible and arranged in expected pattern-- [ ] No error dialogs in KiCad+---
+name: kicad-3d-models
+description: Add standard KiCad 3D models to a .kicad_pcb file (especially tscircuit exports that ship without model references), open the 3D viewer in KiCad on the user's desktop, and screenshot to verify. Trigger words — 3d models in kicad, kicad 3d viewer, alt+3, no 3d chips, missing 3d models, add 3d models, kicad 3d screenshot, show me 3d in kicad, prove 3d works, kicad models missing.
+---
+
+# kicad-3d-models
+
+**Prerequisite: Read `kicad-interaction` skill first.** It covers state checks, window management, and dialog handling that this skill depends on.
+
+Add KiCad-standard 3D model references to `.kicad_pcb` files, push to the user's desktop, open the 3D viewer, and screenshot to prove it worked.
+
+## When to use
+
+- User opens a tscircuit-exported `.kicad_pcb` in KiCad and sees no 3D models (Alt+3 shows bare board)
+- User asks to add 3D models to a KiCad PCB
+- User wants to see/screenshot the KiCad 3D viewer
+
+## Why tscircuit exports lack 3D models
+
+`tsci export -f kicad_pcb` produces valid PCB layouts (pads, traces, silkscreen, board outline) but does **not** inject `(model ...)` entries into footprint blocks. KiCad's 3D viewer needs those entries to know which `.step`/`.wrl` file to render for each component.
+
+## Step 1 — Discover the KiCad 3D model environment variable
+
+KiCad versions use version-specific env vars. Query `service-kicad` to get the correct one:
+
+```bash
+service-kicad fp fetch Resistor_SMD R_0402_1005Metric 2>&1 | grep "model"
+```
+
+This returns something like:
+```
+(model "${KICAD10_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0402_1005Metric.step"
+```
+
+The `${KICAD10_3DMODEL_DIR}` prefix is what you need. Adjust for the KiCad version on the user's desktop.
+
+## Step 2 — Map footprint types to 3D models
+
+List the unique footprint types in the `.kicad_pcb`:
+
+```bash
+grep -A1 "(footprint" board.kicad_pcb | grep '"tscircuit:' | sort -u
+```
+
+Then build a mapping. Common tscircuit footprint → KiCad 3D model mappings:
+
+| tscircuit footprint | KiCad 3D model path |
+|---|---|
+| `tscircuit:resistor_0402` | `Resistor_SMD.3dshapes/R_0402_1005Metric.step` |
+| `tscircuit:resistor_0603` | `Resistor_SMD.3dshapes/R_0603_1608Metric.step` |
+| `tscircuit:resistor_0805` | `Resistor_SMD.3dshapes/R_0805_2012Metric.step` |
+| `tscircuit:capacitor_0402` | `Capacitor_SMD.3dshapes/C_0402_1005Metric.step` |
+| `tscircuit:capacitor_0603` | `Capacitor_SMD.3dshapes/C_0603_1608Metric.step` |
+| `tscircuit:capacitor_0805` | `Capacitor_SMD.3dshapes/C_0805_2012Metric.step` |
+| `tscircuit:led_0603_color(...)` | `LED_SMD.3dshapes/LED_0603_1608Metric.step` |
+| `tscircuit:TYPE-C-31-M-12` | `Connector_USB.3dshapes/USB_C_Receptacle_HRO_TYPE-C-31-M-12.step` |
+| `tscircuit:chip` (machine pins) | Skip or use a small placeholder |
+
+For non-standard footprints, use `service-kicad fp fetch <library> <name>` to look up the model path. Common KiCad 3D model libraries:
+
+- `Resistor_SMD`, `Resistor_THT`
+- `Capacitor_SMD`, `Capacitor_THT`
+- `LED_SMD`, `LED_THT`
+- `Connector_USB`, `Connector_PinHeader`
+- `Package_SO`, `Package_QFP`, `Package_BGA`, `Package_DFN_QFN`
+
+## Step 3 — Inject model entries
+
+Write a Python script that:
+1. Reads the `.kicad_pcb` file
+2. For each `(footprint ...)` block, identifies the footprint type from the line after `(footprint`
+3. Finds the closing `)` of the footprint block (by tracking paren depth)
+4. Inserts a `(model ...)` block before the closing paren
+
+Model block format:
+```
+    (model "${KICAD10_3DMODEL_DIR}/Library.3dshapes/ModelName.step"
+      (offset (xyz 0 0 0))
+      (scale (xyz 1 1 1))
+      (rotate (xyz 0 0 0))
+    )
+```
+
+Verify the result:
+```bash
+grep "KICAD.*3DMODEL" board.kicad_pcb | sort | uniq -c
+```
+
+## Step 4 — Send to desktop and open in KiCad
+
+**CRITICAL: Close all existing KiCad windows BEFORE opening the updated file.** Opening the same file twice creates "File Open Warning" dialogs and leaves stale editors around.
+
+```bash
+# Always close first
+adom-desktop kicad_close '{}'
+
+# Send files (send PCB and any sidecar STEP/WRL separately if >1MB total to avoid 413)
+adom-desktop send_files '{"filePaths":["/path/to/board.kicad_pcb"],"category":"kicad"}'
+adom-desktop send_files '{"filePaths":["/path/to/USB_C_model.wrl"],"category":"kicad"}'
+
+# Open fresh
+adom-desktop kicad_open_board '{"filePath":"C:/Users/john/Downloads/board.kicad_pcb"}'
+```
+
+Wait for the PCB editor to load, then check for dialogs:
+```bash
+adom-desktop kicad_window_info '{}'
+```
+
+## Step 5 — Open the 3D viewer and screenshot
+
+```bash
+# Open the 3D viewer (equivalent to Alt+3)
+adom-desktop kicad_open_3d_viewer '{"hwnd": <pcb_editor_hwnd>}'
+
+# Wait for rendering, then check the viewer window appeared
+sleep 5
+adom-desktop kicad_window_info '{}'
+
+# Screenshot the 3D viewer window
+adom-desktop desktop_screenshot_window '{"hwnd": <3d_viewer_hwnd>}'
+```
+
+The screenshot saves to `/tmp/adom-desktop-screenshots/`. The file is already on Docker — read it with the Read tool to verify the 3D models rendered correctly.
+
+## Handling missing models (e.g. manufacturer-specific USB-C connectors)
+
+Some footprints reference 3D models that aren't in KiCad's standard `packages3D` distribution. Common case: `USB_C_Receptacle_HRO_TYPE-C-31-M-12` ships in the KiCad footprint library but has no matching STEP in packages3D.
+
+**Fix: relative path + ship the STEP alongside the PCB.**
+
+1. Find a visually similar model that IS available:
+   ```bash
+   service-kicad model fetch "Connector_USB.3dshapes/USB_C_Receptacle_GCT_USB4105-xx-A_16P_TopMnt_Horizontal.step" --out /tmp/usbc-standin.step
+   ```
+2. Rename it to match the expected filename and place it next to the `.kicad_pcb`
+3. Change the model reference in the PCB to a relative path:
+   ```
+   (model "./USB_C_Receptacle_HRO_TYPE-C-31-M-12.step" ...)
+   ```
+4. Send BOTH the `.kicad_pcb` and the `.step` file to the desktop (send separately if the STEP triggers a 413 payload-too-large error)
+
+Test with `service-kicad model fetch` first — if it 404s, the model isn't in packages3D and needs this workaround.
+
+**CRITICAL: WRL unit conversion.** KiCad interprets WRL/VRML coordinates as **inches**. If you convert an OBJ/GLB/STL (which are typically in mm) to WRL, you MUST divide all vertex coordinates by 25.4. Without this, the model renders 25.4x too large. STEP files don't have this problem — KiCad reads STEP as mm natively.
+
+## Up-axis rotation convention
+
+STEP files are authored with different up-axis conventions. KiCad uses Z-up. When injecting `(model ...)` references, read `chosen_up_axis` from chip-fetcher's `info.json` to determine the correct rotation:
+
+| `chosen_up_axis` | Source convention | KiCad rotation needed |
+|---|---|---|
+| `z` | Z-up (KiCad native) | `(rotate (xyz 0 0 0))` |
+| `y` | Y-up (Fusion 360, many vendors) | `(rotate (xyz -90 0 0))` |
+
+If `info.json` says `chosen_up_axis: "y"` and you use `(rotate (xyz 0 0 0))`, the model will render sideways or upside-down in KiCad. chip-fetcher's dashboard shows the orientation visually (Z-up/Y-up thumbnail icons) -- check it BEFORE writing the model reference.
+
+See the [`board-building-pipeline`](../board-building-pipeline/SKILL.md) skill for the full up-axis table and how `chosen_up_axis` flows through the entire pipeline (chip-fetcher -> step2glb -> chiplinter -> chipfit -> KiCad footprint writer).
+
+## Footprint source matters (CRITICAL)
+
+When injecting a model reference for a non-standard component, the STEP model and the footprint MUST come from the same source:
+
+- The STEP model from chip-fetcher was designed to match the chip-fetcher footprint (.kicad_mod), **NOT** the tscircuit-exported footprint
+- If you source a STEP from SnapMagic/Mouser/manufacturer, you must ALSO use the footprint from that same source
+- Replace the entire footprint block in the .kicad_pcb, preserving only the board placement coordinates `(at X Y rot)`
+
+**Why this matters:** A tscircuit footprint and a SnapMagic footprint for the same component (e.g. USB-C HRO TYPE-C-31-M-12) have completely different pad positions and mounting hole locations. Bolting the SnapMagic STEP onto the tscircuit footprint causes pads to be misaligned even though the STEP renders in the 3D viewer -- the model just floats above the wrong pad locations.
+
+**How to replace a footprint block:**
+1. Open the chip-fetcher .kicad_mod file for the component
+2. Find the matching `(footprint ...)` block in the .kicad_pcb
+3. Note the `(at X Y rot)` line from the original block (board placement)
+4. Replace the entire footprint block with the chip-fetcher version
+5. Update the `(at ...)` line to use the original board placement coordinates
+6. Ensure the `(model ...)` reference points to the STEP from the same source
+
+## Checklist before reporting success
+
+- [ ] Model count matches expected component count
+- [ ] Screenshot shows 3D component packages (not a bare green board)
+- [ ] USB-C connector visible if present
+- [ ] LED packages visible and arranged in expected pattern
+- [ ] No error dialogs in KiCad
skills/kicad-interaction/SKILL.md+165−153
@@ -1,153 +1,165 @@-----name: kicad-interaction-description: Foundational rules for interacting with KiCad on the user's desktop via adom-desktop. Read BEFORE any kicad_open_board, kicad_open_3d_viewer, kicad_send_key, or kicad_screenshot_all call. Covers state checks, window management, dialog handling, file updates, and the 3D viewer workflow. Trigger words — open in kicad, kicad desktop, send to kicad, kicad 3d viewer, kicad screenshot, kicad dialog, kicad file warning, open board in kicad, kicad pcb editor.------# kicad-interaction--Read this skill BEFORE any KiCad desktop operation. It prevents the most common mistakes: duplicate windows, unhandled dialogs, and blind file pushes.--## Rule 1 — Always check state first--Before ANY KiCad operation, run:--```bash-adom-desktop kicad_window_info '{}'-```--This returns all open editors, 3D viewers, and modal dialogs with their hwnds. Parse the response and decide your next action based on what's already running.--**If the board is already open and you're pushing an updated file:**-```bash-adom-desktop kicad_close '{}'        # close everything-sleep 2-adom-desktop kicad_open_board '{"filePath":"C:/Users/john/Downloads/board.kicad_pcb"}'-```--**If the board is already open and you just need the 3D viewer:**-```bash-# Reuse the existing editor — get its hwnd from window_info-adom-desktop kicad_open_3d_viewer '{"hwnd": <existing_pcb_editor_hwnd>}'-```--**If KiCad is not running:**-```bash-adom-desktop kicad_open_board '{"filePath":"C:/Users/john/Downloads/board.kicad_pcb"}'-```--Never call `kicad_open_board` without checking `kicad_window_info` first.--## Rule 2 — Never open duplicate instances--Opening the same `.kicad_pcb` file twice triggers a "File Open Warning" dialog about interleaved saves. This is always wrong. The correct pattern when updating a file:--1. `kicad_window_info` — see what's open-2. `kicad_close` — close everything-3. `send_files` — push the updated file-4. `kicad_open_board` — open fresh--Do NOT open a second instance and then dismiss the warning. Close first, open once.--## Rule 3 — Always check for dialogs after operations--After `kicad_open_board`, `kicad_open_3d_viewer`, or any operation that might trigger a dialog:--```bash-sleep 3-adom-desktop kicad_window_info '{}'-```--Check `hasModalDialogs`. If true:-1. Screenshot the dialog: `desktop_screenshot_window '{"hwnd": <dialog_hwnd>}'`-2. Read the screenshot to understand the dialog-3. Dismiss with `kicad_send_key '{"key": "Enter", "hwnd": <dialog_hwnd>}'` or `"Escape"` as appropriate-4. Re-check `kicad_window_info` to confirm it cleared--## Rule 4 — File transfer before open--KiCad runs on Windows. The `.kicad_pcb` file lives on Docker. Always send first, then open:--```bash-# Send files (send large files like STEP/WRL separately to avoid 413)-adom-desktop send_files '{"filePaths":["/docker/path/board.kicad_pcb"],"category":"kicad"}'--# Files land in C:/Users/john/Downloads/ by default-adom-desktop kicad_open_board '{"filePath":"C:/Users/john/Downloads/board.kicad_pcb"}'-```--If you also have sidecar files (STEP/WRL models referenced with relative paths), send those too — they must land in the same directory as the PCB.--## Rule 5 — 3D viewer workflow--```bash-# 1. Check state-adom-desktop kicad_window_info '{}'--# 2. Open 3D viewer from the PCB editor (use hwnd from step 1)-adom-desktop kicad_open_3d_viewer '{"hwnd": <pcb_editor_hwnd>}'--# 3. Wait for render + confirm viewer appeared-sleep 5-adom-desktop kicad_window_info '{}'--# 4. Screenshot the 3D viewer window-adom-desktop desktop_screenshot_window '{"hwnd": <3d_viewer_hwnd>}'--# 5. Read the screenshot to verify models rendered-```--### Edge-mount connectors (USB-C, micro-USB, barrel jacks)--USB-C, micro-USB, barrel jacks, and other connectors that users plug cables into must overhang the board edge. After placing the footprint, verify in the 3D viewer that the connector mouth extends past the Edge.Cuts outline. If it doesn't, adjust the footprint Y position using the fab-layer board-edge alignment line.--**Verification workflow:**-1. Open the 3D viewer after placing an edge-mount connector-2. Screenshot and check that the connector body sticks out past the board edge-3. If it's flush or recessed, the user cannot plug in a cable -- adjust the footprint Y coordinate-4. The footprint's fab layer typically includes a line marking where the board edge should intersect the component--## Rule 6 — Available KiCad commands--```-kicad_open_board          Open a .kicad_pcb in the PCB Editor-kicad_open_3d_viewer      Open 3D viewer from a PCB Editor (needs hwnd)-kicad_close_3d_viewer     Close the 3D viewer-kicad_close               Close all KiCad windows-kicad_window_info         List all open editors, viewers, and dialogs-kicad_send_key            Send a keystroke to a specific window (needs hwnd)-kicad_screenshot_all      Screenshot all KiCad windows-kicad_adom_library_status Check Adom library installation-kicad_install_symbol      Install a symbol to KiCad's library-kicad_install_footprint   Install a footprint to KiCad's library-kicad_install_library     Install a full library-kicad_run_drc             Run Design Rule Check-desktop_screenshot_window Screenshot a specific window by hwnd-desktop_bring_to_front    Focus a window by hwnd-```--## Rule 7 — Pup-over-webview preference for tool dashboards--User prefers tool dashboards (chip-fetcher, chiplinter, etc.) in **pup windows**, not Hydrogen webview tabs. The canonical pattern is two pup windows:--- **Dashboard pup window** (`sessionId: "chip-fetcher-dashboard"` or `"<tool>-dashboard"`) — the live status / card view. Never navigate this mid-batch.-- **Scrape / work pup window** (`sessionId: "chip-fetcher-scrape"` or `"<tool>-scrape"`) — where vendor pages, logins, and downloads happen.--Both windows MUST use the same `profile` (e.g. `profile: "chip-fetcher"`) so cookies and logins persist. Only the `sessionId` varies. This two-pup pattern keeps the user's view of progress (dashboard) completely isolated from the active scraping / interaction window.--## Rule 8 — Desktop connection prerequisite--Before any KiCad command, verify the desktop is connected:--```bash-adom-desktop ping-```--If disconnected, start the relay:-```bash-if ! curl -sf http://127.0.0.1:8766/health >/dev/null 2>&1; then-  nohup adom-desktop serve > /tmp/adom-desktop-relay.log 2>&1 &-  disown-  sleep 3-fi-adom-desktop ping-```+---
+name: kicad-interaction
+description: Foundational rules for interacting with KiCad on the user's desktop via adom-desktop. Read BEFORE any kicad_open_board, kicad_open_3d_viewer, kicad_send_key, or kicad_screenshot_all call. Covers state checks, window management, dialog handling, file updates, and the 3D viewer workflow. Trigger words — open in kicad, kicad desktop, send to kicad, kicad 3d viewer, kicad screenshot, kicad dialog, kicad file warning, open board in kicad, kicad pcb editor.
+---
+
+# kicad-interaction
+
+Read this skill BEFORE any KiCad desktop operation. It prevents the most common mistakes: duplicate windows, unhandled dialogs, and blind file pushes.
+
+## Dialogs: the bridge auto-expires the pointless ones, and tells you what it closed (v0.9.29+)
+
+KiCad throws blocking modal dialogs constantly (OpenGL fallback notices, "older file format" warnings, save prompts, config nags). A blocking dialog **stalls every other verb** — an editor open can't complete, a screenshot captures only the dialog. The bridge now handles this **programmatically** so you rarely babysit it:
+
+- **`kicad_window_info` auto-expires *benign* dialogs by default.** It scans EVERY window owned by any running KiCad process (matched by PID — reliable, never misses one), clicks OK on the harmless ones (e.g. *"Could not use OpenGL, falling back to software rendering"*), and reports them in `data.autoDismissed[]` + `data._autoDismissHint`. Pass `{"autoDismiss": false}` to inspect without touching them.
+- **A NON-benign dialog is left up and reported** in `data.modalDialogs[]` with its `body` text (read from the dialog's Static controls — no screenshot needed) so YOU decide: read `body`, then dismiss with `kicad_send_key {hwnd, key:"return"}` (OK) / `"escape"` (Cancel), or surface it to the user.
+- **`kicad_dismiss_dialogs`** — force-clear on demand. `{}` = benign only; `{"all": true}` = clear EVERY KiCad dialog (use after you've read a modal you want gone). It **screenshots each dialog before expiring it** (returned in `dismissed[].screenshot`) so you can show the user what was auto-closed and let them decide what it meant. Returns `dismissed[]`, `remaining[]`, hints.
+
+**GPU-less hosts (VMs / RDP / servers):** KiCad tries OpenGL, fails, and pcbnew/3D may not render. When the bridge expires the OpenGL notice it also persists `graphics.canvas_type=2` (Cairo software) to `kicad_common.json` so future launches skip OpenGL — or force it up front with `kicad_dismiss_dialogs {"forceSoftwareCanvas": true}` then reopen the editor. (Note: a truly headless VM with no usable graphics stack still may not render the heavy editors even in Cairo — that's the hardware, not the bridge.)
+
+**Pattern:** `open_* → window_info (auto-clears benign) → screenshot_all`. If an open "fails," a benign modal was almost certainly blocking it — call `window_info` or `kicad_dismiss_dialogs` and retry.
+
+## Rule 1 — Always check state first
+
+Before ANY KiCad operation, run:
+
+```bash
+adom-desktop kicad_window_info '{}'
+```
+
+This returns all open editors, 3D viewers, and modal dialogs with their hwnds. Parse the response and decide your next action based on what's already running.
+
+**If the board is already open and you're pushing an updated file:**
+```bash
+adom-desktop kicad_close '{}'        # close everything
+sleep 2
+adom-desktop kicad_open_board '{"filePath":"C:/Users/john/Downloads/board.kicad_pcb"}'
+```
+
+**If the board is already open and you just need the 3D viewer:**
+```bash
+# Reuse the existing editor — get its hwnd from window_info
+adom-desktop kicad_open_3d_viewer '{"hwnd": <existing_pcb_editor_hwnd>}'
+```
+
+**If KiCad is not running:**
+```bash
+adom-desktop kicad_open_board '{"filePath":"C:/Users/john/Downloads/board.kicad_pcb"}'
+```
+
+Never call `kicad_open_board` without checking `kicad_window_info` first.
+
+## Rule 2 — Never open duplicate instances
+
+Opening the same `.kicad_pcb` file twice triggers a "File Open Warning" dialog about interleaved saves. This is always wrong. The correct pattern when updating a file:
+
+1. `kicad_window_info` — see what's open
+2. `kicad_close` — close everything
+3. `send_files` — push the updated file
+4. `kicad_open_board` — open fresh
+
+Do NOT open a second instance and then dismiss the warning. Close first, open once.
+
+## Rule 3 — Always check for dialogs after operations
+
+After `kicad_open_board`, `kicad_open_3d_viewer`, or any operation that might trigger a dialog:
+
+```bash
+sleep 3
+adom-desktop kicad_window_info '{}'
+```
+
+Check `hasModalDialogs`. If true:
+1. Screenshot the dialog: `desktop_screenshot_window '{"hwnd": <dialog_hwnd>}'`
+2. Read the screenshot to understand the dialog
+3. Dismiss with `kicad_send_key '{"key": "Enter", "hwnd": <dialog_hwnd>}'` or `"Escape"` as appropriate
+4. Re-check `kicad_window_info` to confirm it cleared
+
+## Rule 4 — File transfer before open
+
+KiCad runs on Windows. The `.kicad_pcb` file lives on Docker. Always send first, then open:
+
+```bash
+# Send files (send large files like STEP/WRL separately to avoid 413)
+adom-desktop send_files '{"filePaths":["/docker/path/board.kicad_pcb"],"category":"kicad"}'
+
+# Files land in C:/Users/john/Downloads/ by default
+adom-desktop kicad_open_board '{"filePath":"C:/Users/john/Downloads/board.kicad_pcb"}'
+```
+
+If you also have sidecar files (STEP/WRL models referenced with relative paths), send those too — they must land in the same directory as the PCB.
+
+## Rule 5 — 3D viewer workflow
+
+```bash
+# 1. Check state
+adom-desktop kicad_window_info '{}'
+
+# 2. Open 3D viewer from the PCB editor (use hwnd from step 1)
+adom-desktop kicad_open_3d_viewer '{"hwnd": <pcb_editor_hwnd>}'
+
+# 3. Wait for render + confirm viewer appeared
+sleep 5
+adom-desktop kicad_window_info '{}'
+
+# 4. Screenshot the 3D viewer window
+adom-desktop desktop_screenshot_window '{"hwnd": <3d_viewer_hwnd>}'
+
+# 5. Read the screenshot to verify models rendered
+```
+
+### Edge-mount connectors (USB-C, micro-USB, barrel jacks)
+
+USB-C, micro-USB, barrel jacks, and other connectors that users plug cables into must overhang the board edge. After placing the footprint, verify in the 3D viewer that the connector mouth extends past the Edge.Cuts outline. If it doesn't, adjust the footprint Y position using the fab-layer board-edge alignment line.
+
+**Verification workflow:**
+1. Open the 3D viewer after placing an edge-mount connector
+2. Screenshot and check that the connector body sticks out past the board edge
+3. If it's flush or recessed, the user cannot plug in a cable -- adjust the footprint Y coordinate
+4. The footprint's fab layer typically includes a line marking where the board edge should intersect the component
+
+## Rule 6 — Available KiCad commands
+
+```
+kicad_open_board          Open a .kicad_pcb in the PCB Editor
+kicad_open_3d_viewer      Open 3D viewer from a PCB Editor (needs hwnd)
+kicad_close_3d_viewer     Close the 3D viewer
+kicad_close               Close all KiCad windows
+kicad_window_info         List all open editors, viewers, and dialogs
+kicad_send_key            Send a keystroke to a specific window (needs hwnd)
+kicad_screenshot_all      Screenshot all KiCad windows
+kicad_adom_library_status Check Adom library installation
+kicad_install_symbol      Install a symbol to KiCad's library
+kicad_install_footprint   Install a footprint to KiCad's library
+kicad_install_library     Install a full library
+kicad_run_drc             Run Design Rule Check
+desktop_screenshot_window Screenshot a specific window by hwnd
+desktop_bring_to_front    Focus a window by hwnd
+```
+
+## Rule 7 — Pup-over-webview preference for tool dashboards
+
+User prefers tool dashboards (chip-fetcher, chiplinter, etc.) in **pup windows**, not Hydrogen webview tabs. The canonical pattern is two pup windows:
+
+- **Dashboard pup window** (`sessionId: "chip-fetcher-dashboard"` or `"<tool>-dashboard"`) — the live status / card view. Never navigate this mid-batch.
+- **Scrape / work pup window** (`sessionId: "chip-fetcher-scrape"` or `"<tool>-scrape"`) — where vendor pages, logins, and downloads happen.
+
+Both windows MUST use the same `profile` (e.g. `profile: "chip-fetcher"`) so cookies and logins persist. Only the `sessionId` varies. This two-pup pattern keeps the user's view of progress (dashboard) completely isolated from the active scraping / interaction window.
+
+## Rule 8 — Desktop connection prerequisite
+
+Before any KiCad command, verify the desktop is connected:
+
+```bash
+adom-desktop ping
+```
+
+If disconnected, start the relay:
+```bash
+if ! curl -sf http://127.0.0.1:8766/health >/dev/null 2>&1; then
+  nohup adom-desktop serve > /tmp/adom-desktop-relay.log 2>&1 &
+  disown
+  sleep 3
+fi
+adom-desktop ping
+```