Adom Desktop - 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.
name: kicad-bridge-publish user-invocable: false description: DEVELOPER-only PUBLISH skill (user-invocable:false — for maintainers, never offered to everyday users). The exact recipe to ship a new version of the Adom Desktop KiCad bridge to wiki.adom.inc: version lockstep, the zip build, adom-wiki repo push + release create, the skills pkg, pushing to a target AD, and verify steps. Trigger words — publish kicad bridge, release kicad bridge, ship kicad bridge, bump kicad bridge, kicad bridge manifest, kicad bridge pkg.
kicad-bridge-publish
How to cut and publish a KiCad-bridge release. Use the adom-wiki CLI for ALL wiki interactions — never raw curl. Two independent artifacts: the RUNTIME (zip + manifest, on the page /files) and the SKILLS PKG (adom/adom-desktop-kicad-bridge, container-side docs).
1. Version lockstep (bump ALL three together)
bridge.json→"version"BRIDGE_VERSION(plain text)- the manifest JSON →
"version"
They must match. bridge.json also carries updateManifestUrl (durable auto-update), docs (your page), homepage (a wiki.adom.inc URL, NEVER github), detect (host-app paths incl. %LocalAppData%\Programs\KiCad), verbPrefixes, complete verbs[], statusVerb.
2. Build the zip — KEEP IT TINY (it is auto-bundled into AD)
The runtime zip ships inside Adom Desktop for every user, so it carries ONLY what the
bridge needs to RUN. No docs, no images, no skills, no samples. (Audited 2026-07-15: the zip
had grown to 488.9 KB carrying 219 KB of hero fonts, five skills/ trees, demo scripts and
READMEs — none referenced by runtime code. Slimming it to 335.7 KB was a 31% cut with zero
functional change.)
KEEP (runtime-required):
- all
*.py(server +handlers/+plugin_payload/) certs/cacert.pem— AD's portable Python has no CA bundle*.ps1(launch_editor.ps1,navigate_symbol.ps1) — UIA scripts the handlers shell out totemplates/blank-board.kicad_pcb— read byhandlers/place_footprint.pybridge.json,BRIDGE_VERSION,start.bat,start.sh- root
SKILL.mdONLY (the runtime skilladom-desktop-kicad,public: true— AD installs it)
EXCLUDE (everything else):
skills/** (container-side docs — they ship in the PKG, duplicating them here is pure bloat),
demo/**, docs/**, tour*/**, every *.md except root SKILL.md, every image/font
(*.png *.jpg *.svg *.gif *.ttf *.otf *.woff*), every archive/video (*.zip *.tar.gz *.bundle *.mp4 — note mesa-llvmpipe-x64.zip is 22 MB and must NEVER land in the zip),
__pycache__, *.pyc, .git, .github, node_modules, .DS_Store, and the generated
adom-bridge-kicad-manifest.json.
Compute sha256 + byte size for the manifest. Verify before publishing: every local
import resolves inside the zip, and the data files above are all present — then deploy and
call kicad_describe (verb count) + one data-file-dependent verb on a real target.
Manifest fields: manifest_version:1, name:"kicad", version, url (the /blob/app/.../adom-bridge-kicad-v<ver>.zip), sha256, size, verbPrefixes:["kicad_"], healthEndpoint:"/status", released_at, hero, languages.
3. Publish the runtime (CLI)
adom-wiki repo push adom/adom-desktop-kicad-bridge \
--files adom-bridge-kicad-v<ver>.zip adom-bridge-kicad-manifest.json bridge.json \
-m "v<ver>: <what changed>"
adom-wiki release create adom/adom-desktop-kicad-bridge <ver> \
--title "KiCad bridge v<ver>" --changelog "..." \
--binary-path adom-bridge-kicad-v<ver>.zip
repo push writes the files to the page /files (same place AD's bridge_cache fetches from). release create also registers a proper Release (SDK Artifact 1). For a field with no dedicated verb use adom-wiki api -X PUT /api/v1/pages/... --body ..., not curl.
4. Publish the skills pkg (container docs)
The pkg is skills-only — it is NOT the bridge. The pkg teaches a container agent the kicad_*
verbs; the release zip is what AD downloads and runs as the bridge runtime. Users conflate them
constantly, so say it — but say it in ONE LINE.
⚠️ description is rendered inside the page's Install card. Keep it to one or two sentences.
A paragraph there is worse than saying nothing — it buries the install command in a wall of text.
(Learned the hard way 2026-07-19: a 486-char description explaining the whole two-artifact model
turned the Install card into an unreadable block; John: "you're overdoing it with that install
description." Cut to 145 chars.) The full explanation belongs in the README body, not the card.
Canonical description — copy this shape:
Skills for your container so your AI knows how to drive the KiCad bridge. The bridge runtime itself is the release zip — Adom Desktop loads that.
The longer version (the "Two artifacts on this page — which one do you want?" comparison table:
what it is / who loads it / contains / do you install it manually, closing with "The package is
not the bridge.") lives near the TOP of README.md, where there's room for it.
No images in the pkg. The README references page art by ABSOLUTE
https://wiki.adom.inc/blob/app/adom-desktop-kicad-bridge/<name>.png URLs, so the PNGs render on
the page without riding in the install tarball. (Audited 2026-07-15: files[] listed
hero.png + arch.png + verbs.png + outcomes.png = 496 KB downloaded by every
pkg install, referenced by nothing. Removing them took the tarball to 29.5 KB.) Push page art
with repo push, never list it in files[]. Before publishing, stage only the declared
files[] into a clean dir and pack from there — packing from the page repo sweeps up art,
zips and videos.
Stage a dir with package.json (name/version/files[]), a ROOT SKILL.md, and a skills/<name>/SKILL.md for every skill. SKILLPACK convention (SDK, replaces the dead dev-skills/*.md rule): EVERY skill — user, dev, AND publish — is a real skills/<name>/SKILL.md and ships in the tarball. Dev/publish skills are scoped by AUDIENCE, not filename: frontmatter user-invocable: false + a description that opens DEVELOPER-only, so everyday users never get them offered but maintainers still install them. List every skill path EXPLICITLY (no globs) in package.json files[] AND install.sh/uninstall.sh. Then:
cd <staging> && adom-wiki pkg pack --out /tmp/v.tgz # verify: tar lists every skills/<x>/SKILL.md, 0 binaries
adom-wiki pkg publish --org adom --skip-lint --yes # moves dist-tag latest
The runtime SKILL.md (adom-desktop-kicad, ships in the zip) and the pkg's root SKILL.md are DIFFERENT docs — update both when a change affects users.
5. Push to a running desktop + verify
adom-desktop --target <name> refresh_bridges '{"name":"kicad"}' # pulls new cache
adom-desktop --target <name> bridge_kill '{"name":"kicad"}' # force fresh spawn (old instance keeps old code)
adom-desktop --target <name> bridge_check_updates '{}' # current == latest?
adom-wiki repo show adom/adom-desktop-kicad-bridge adom-bridge-kicad-manifest.json # served version matches?
Verify the served bridge.json (repo show ... bridge.json) has the fields you expect and the zip's sha matches. A fresh verb call after a kill returns bridge_starting — retry.
6. Refreshing the README screenshots (window tour)
The README embeds screenshots hosted on the page /files (referenced as
https://wiki.adom.inc/blob/app/adom-desktop-kicad-bridge/<name>.png). Regenerate them on a real
VM (e.g. ADOMBASELINE) whenever the UI/flow changes — never hand-mock them:
- On the VM:
kicad_enable_software_opengl(if GPU-less) → open each window with sample data fromtour-pack-rp2040/(AdomRP2040symbol,QFN-56_AdomRP2040footprint, the breakout board). - For each:
kicad_dismiss_dialogs {all:true}→kicad_screenshot_all→pull_filethe matching.bmp→ PILbmp→png,thumbnail((1400,1400)). - Save into
docs/img/with the canonical names the README uses:schematic-editor.png,symbol-editor.png,footprint-editor.png,pcb-editor-2d.png,3d-viewer.png,dialog-firstrun-wizard.png,control-surfaces.svg. adom-wiki repo push adom/adom-desktop-kicad-bridge --files docs/img/*.png ...thencurl -so /dev/null -w '%{http_code}'each blob URL to confirm 200.shotlog paste <png> -c kicad-bridge -d "<caption>"to show John the live captures.
7. Showing the published page to John (pup)
pup opens windows in the BACKGROUND by default. foreground: true on browser_open_window is
the ONLY thing that puts a window on his screen — maximizing, sizing, browser_alert_window
(taskbar flash) and browser_raise_os_window do NOT. (2026-07-19: he asked "show me in pup" three
times because the window was open, correct and maximized — but behind everything.)
- He asked to be shown → open with
foreground: true, thendesktop_set_window_state maximizeONCE. (stateacceptsmaximize|minimize|restore— there is no"foreground"state.) - The standing "never foreground a window he already has" rule protects windows he is using; it does not apply to a window you just opened because he asked to see something.
- Sessions die between turns —
browser_list_windowsfirst; if the session is gone, open fresh rather thanbrowser_navigateinto a dead sessionId. - Never touch a session another AI thread owns (you'll see unfamiliar sessionIds like
wiki-lockdemo,plate-out). Open your own. - Multiple pages → ONE maximized window,
browser_open_tabper page, land on the important tab. - Then
adom-shotlog injecteach capture and hand him the phone URL (SHOTLOG_AD_TARGET=AdomLapper adom-shotlog open --channel <ch>when several desktops are connected).
8. Upstream: what the SDK still owes every bridge
Two issues are open on adom/adom-desktop-bridges (filed 2026-07-19) — if you hit these problems,
they're known, and the fix belongs in the SDK, not just here:
- SDK should require every bridge to explain pkg-vs-zip (one line, on the page + in
package.json.description). The SDK documents the artifacts ("Artifact 1 — the RUNTIME…") but never tells authors to explain them to users, so no page does. - SDK should document artifact hygiene — the KEEP/EXCLUDE policy in §2 + the no-images-in-pkg
rule in §4, ideally enforced by a
bridge lintthat fails on images/videos/archives in either artifact.
9. Standing rules
- Commit source to
mainin lockstep with each publish (drift = the bug that once droppedupdateManifestUrl). - After ANY wiki change, refresh the wiki pup window showing the page.
- The changelog must be real (≥2 words, no placeholders) — the server enforces it.
---
name: kicad-bridge-publish
user-invocable: false
description: DEVELOPER-only PUBLISH skill (user-invocable:false — for maintainers, never offered to everyday users). The exact recipe to ship a new version of the Adom Desktop KiCad bridge to wiki.adom.inc: version lockstep, the zip build, adom-wiki repo push + release create, the skills pkg, pushing to a target AD, and verify steps. Trigger words — publish kicad bridge, release kicad bridge, ship kicad bridge, bump kicad bridge, kicad bridge manifest, kicad bridge pkg.
---
# kicad-bridge-publish
How to cut and publish a KiCad-bridge release. **Use the `adom-wiki` CLI for ALL wiki interactions — never raw curl.** Two independent artifacts: the RUNTIME (zip + manifest, on the page `/files`) and the SKILLS PKG (`adom/adom-desktop-kicad-bridge`, container-side docs).
## 1. Version lockstep (bump ALL three together)
- `bridge.json` → `"version"`
- `BRIDGE_VERSION` (plain text)
- the manifest JSON → `"version"`
They must match. `bridge.json` also carries `updateManifestUrl` (durable auto-update), `docs` (your page), `homepage` (a **wiki.adom.inc** URL, NEVER github), `detect` (host-app paths incl. `%LocalAppData%\Programs\KiCad`), `verbPrefixes`, complete `verbs[]`, `statusVerb`.
## 2. Build the zip — KEEP IT TINY (it is auto-bundled into AD)
The runtime zip ships inside Adom Desktop for **every** user, so it carries ONLY what the
bridge needs to RUN. No docs, no images, no skills, no samples. (Audited 2026-07-15: the zip
had grown to 488.9 KB carrying 219 KB of hero *fonts*, five `skills/` trees, demo scripts and
READMEs — none referenced by runtime code. Slimming it to 335.7 KB was a 31% cut with zero
functional change.)
**KEEP** (runtime-required):
- all `*.py` (server + `handlers/` + `plugin_payload/`)
- `certs/cacert.pem` — AD's portable Python has no CA bundle
- `*.ps1` (`launch_editor.ps1`, `navigate_symbol.ps1`) — UIA scripts the handlers shell out to
- `templates/blank-board.kicad_pcb` — read by `handlers/place_footprint.py`
- `bridge.json`, `BRIDGE_VERSION`, `start.bat`, `start.sh`
- root `SKILL.md` ONLY (the runtime skill `adom-desktop-kicad`, `public: true` — AD installs it)
**EXCLUDE** (everything else):
`skills/**` (container-side docs — they ship in the PKG, duplicating them here is pure bloat),
`demo/**`, `docs/**`, `tour*/**`, every `*.md` except root `SKILL.md`, every image/font
(`*.png *.jpg *.svg *.gif *.ttf *.otf *.woff*`), every archive/video (`*.zip *.tar.gz *.bundle
*.mp4` — note `mesa-llvmpipe-x64.zip` is 22 MB and must NEVER land in the zip),
`__pycache__`, `*.pyc`, `.git`, `.github`, `node_modules`, `.DS_Store`, and the generated
`adom-bridge-kicad-manifest.json`.
Compute `sha256` + byte `size` for the manifest. **Verify before publishing:** every local
import resolves inside the zip, and the data files above are all present — then deploy and
call `kicad_describe` (verb count) + one data-file-dependent verb on a real target.
Manifest fields: `manifest_version:1, name:"kicad", version, url` (the `/blob/app/.../adom-bridge-kicad-v<ver>.zip`), `sha256, size, verbPrefixes:["kicad_"], healthEndpoint:"/status", released_at, hero, languages`.
## 3. Publish the runtime (CLI)
```bash
adom-wiki repo push adom/adom-desktop-kicad-bridge \
--files adom-bridge-kicad-v<ver>.zip adom-bridge-kicad-manifest.json bridge.json \
-m "v<ver>: <what changed>"
adom-wiki release create adom/adom-desktop-kicad-bridge <ver> \
--title "KiCad bridge v<ver>" --changelog "..." \
--binary-path adom-bridge-kicad-v<ver>.zip
```
`repo push` writes the files to the page `/files` (same place AD's bridge_cache fetches from). `release create` also registers a proper Release (SDK Artifact 1). For a field with no dedicated verb use `adom-wiki api -X PUT /api/v1/pages/... --body ...`, not curl.
## 4. Publish the skills pkg (container docs)
**The pkg is skills-only — it is NOT the bridge.** The pkg teaches a container agent the `kicad_*`
verbs; the **release zip** is what AD downloads and runs as the bridge runtime. Users conflate them
constantly, so say it — but say it in **ONE LINE**.
⚠️ **`description` is rendered inside the page's Install card. Keep it to one or two sentences.**
A paragraph there is worse than saying nothing — it buries the install command in a wall of text.
(Learned the hard way 2026-07-19: a 486-char description explaining the whole two-artifact model
turned the Install card into an unreadable block; John: *"you're overdoing it with that install
description."* Cut to 145 chars.) The full explanation belongs in the README body, not the card.
Canonical description — copy this shape:
> Skills for your container so your AI knows how to drive the KiCad bridge.
> The bridge runtime itself is the release zip — Adom Desktop loads that.
The longer version (the "Two artifacts on this page — which one do you want?" comparison table:
what it is / who loads it / contains / do you install it manually, closing with **"The package is
not the bridge."**) lives near the TOP of `README.md`, where there's room for it.
**No images in the pkg.** The README references page art by ABSOLUTE
`https://wiki.adom.inc/blob/app/adom-desktop-kicad-bridge/<name>.png` URLs, so the PNGs render on
the page without riding in the install tarball. (Audited 2026-07-15: `files[]` listed
`hero.png` + `arch.png` + `verbs.png` + `outcomes.png` = **496 KB** downloaded by every
`pkg install`, referenced by nothing. Removing them took the tarball to 29.5 KB.) Push page art
with `repo push`, never list it in `files[]`. Before publishing, **stage only the declared
`files[]` into a clean dir and pack from there** — packing from the page repo sweeps up art,
zips and videos.
Stage a dir with `package.json` (name/version/`files[]`), a ROOT `SKILL.md`, and a `skills/<name>/SKILL.md` for **every** skill. **SKILLPACK convention (SDK, replaces the dead `dev-skills/*.md` rule): EVERY skill — user, dev, AND publish — is a real `skills/<name>/SKILL.md` and ships in the tarball.** Dev/publish skills are scoped by AUDIENCE, not filename: frontmatter `user-invocable: false` + a description that opens DEVELOPER-only, so everyday users never get them offered but maintainers still install them. **List every skill path EXPLICITLY (no globs) in `package.json` `files[]` AND `install.sh`/`uninstall.sh`.** Then:
```bash
cd <staging> && adom-wiki pkg pack --out /tmp/v.tgz # verify: tar lists every skills/<x>/SKILL.md, 0 binaries
adom-wiki pkg publish --org adom --skip-lint --yes # moves dist-tag latest
```
The runtime SKILL.md (`adom-desktop-kicad`, ships in the zip) and the pkg's root SKILL.md are DIFFERENT docs — update both when a change affects users.
## 5. Push to a running desktop + verify
```bash
adom-desktop --target <name> refresh_bridges '{"name":"kicad"}' # pulls new cache
adom-desktop --target <name> bridge_kill '{"name":"kicad"}' # force fresh spawn (old instance keeps old code)
adom-desktop --target <name> bridge_check_updates '{}' # current == latest?
adom-wiki repo show adom/adom-desktop-kicad-bridge adom-bridge-kicad-manifest.json # served version matches?
```
Verify the served bridge.json (`repo show ... bridge.json`) has the fields you expect and the zip's sha matches. A fresh verb call after a kill returns `bridge_starting` — retry.
## 6. Refreshing the README screenshots (window tour)
The README embeds screenshots hosted on the page `/files` (referenced as
`https://wiki.adom.inc/blob/app/adom-desktop-kicad-bridge/<name>.png`). Regenerate them on a **real
VM** (e.g. ADOMBASELINE) whenever the UI/flow changes — never hand-mock them:
1. On the VM: `kicad_enable_software_opengl` (if GPU-less) → open each window with sample data from
`tour-pack-rp2040/` (`AdomRP2040` symbol, `QFN-56_AdomRP2040` footprint, the breakout board).
2. For each: `kicad_dismiss_dialogs {all:true}` → `kicad_screenshot_all` → `pull_file` the matching
`.bmp` → PIL `bmp→png`, `thumbnail((1400,1400))`.
3. Save into `docs/img/` with the canonical names the README uses: `schematic-editor.png`,
`symbol-editor.png`, `footprint-editor.png`, `pcb-editor-2d.png`, `3d-viewer.png`,
`dialog-firstrun-wizard.png`, `control-surfaces.svg`.
4. `adom-wiki repo push adom/adom-desktop-kicad-bridge --files docs/img/*.png ...` then
`curl -so /dev/null -w '%{http_code}'` each blob URL to confirm 200.
5. `shotlog paste <png> -c kicad-bridge -d "<caption>"` to show John the live captures.
## 7. Showing the published page to John (pup)
**pup opens windows in the BACKGROUND by default.** `foreground: true` on `browser_open_window` is
the ONLY thing that puts a window on his screen — maximizing, sizing, `browser_alert_window`
(taskbar flash) and `browser_raise_os_window` do NOT. (2026-07-19: he asked "show me in pup" three
times because the window was open, correct and maximized — but behind everything.)
- He asked to be shown → open with `foreground: true`, then `desktop_set_window_state maximize` ONCE.
(`state` accepts `maximize|minimize|restore` — there is **no** `"foreground"` state.)
- The standing "never foreground a window he already has" rule protects windows **he** is using; it
does not apply to a window you just opened because he asked to see something.
- Sessions die between turns — `browser_list_windows` first; if the session is gone, open fresh
rather than `browser_navigate` into a dead sessionId.
- **Never touch a session another AI thread owns** (you'll see unfamiliar sessionIds like
`wiki-lockdemo`, `plate-out`). Open your own.
- Multiple pages → ONE maximized window, `browser_open_tab` per page, land on the important tab.
- Then `adom-shotlog inject` each capture and hand him the phone URL
(`SHOTLOG_AD_TARGET=AdomLapper adom-shotlog open --channel <ch>` when several desktops are connected).
## 8. Upstream: what the SDK still owes every bridge
Two issues are open on `adom/adom-desktop-bridges` (filed 2026-07-19) — if you hit these problems,
they're known, and the fix belongs in the SDK, not just here:
1. **SDK should require every bridge to explain pkg-vs-zip** (one line, on the page + in
`package.json.description`). The SDK documents the artifacts ("Artifact 1 — the RUNTIME…") but
never tells authors to explain them to users, so no page does.
2. **SDK should document artifact hygiene** — the KEEP/EXCLUDE policy in §2 + the no-images-in-pkg
rule in §4, ideally enforced by a `bridge lint` that fails on images/videos/archives in either
artifact.
## 9. Standing rules
- Commit source to `main` in lockstep with each publish (drift = the bug that once dropped `updateManifestUrl`).
- After ANY wiki change, refresh the wiki pup window showing the page.
- The changelog must be real (≥2 words, no placeholders) — the server enforces it.