← Commit history

Publish v1.0.1 package: install/uninstall scripts, skills, manifest

John Lauer ·ccb7b1fb1e ·4mo ago ·parent 50fe260
6 files changed +339−21
install.sh+14−13
@@ -1,15 +1,16 @@ #!/bin/bash-set -e-PKG_DIR="$(cd "$(dirname "$0")" && pwd)"-SKILLS_DIR="$HOME/.claude/skills"-mkdir -p "$SKILLS_DIR/adom-jlcpcb"-if [ -f "$PKG_DIR/SKILL.md" ]; then-  cp "$PKG_DIR/SKILL.md" "$SKILLS_DIR/adom-jlcpcb/SKILL.md"-fi-for skill_dir in "$PKG_DIR/skills"/*/; do-  [ -d "$skill_dir" ] || continue-  skill_name=$(basename "$skill_dir")-  mkdir -p "$SKILLS_DIR/$skill_name"-  cp -r "$skill_dir"* "$SKILLS_DIR/$skill_name/"+# install.sh for adom-jlcpcb (app) — runs from the extracted module dir.+set -euo pipefail+DIR="$(cd "$(dirname "$0")" && pwd)"; cd "$DIR"+BIN_DIR="${HOME}/.local/bin"; mkdir -p "$BIN_DIR"+install -m 0755 "$DIR/bin/adom-jlcpcb" "$BIN_DIR/adom-jlcpcb"+echo "Installed adom-jlcpcb -> $BIN_DIR/adom-jlcpcb"+SKILL_DIR="${HOME}/.claude/skills"+for s in adom-jlcpcb adom-jlcpcb-build; do+  if [ -f "$DIR/skills/$s/SKILL.md" ]; then+    mkdir -p "$SKILL_DIR/$s"+    install -m 0644 "$DIR/skills/$s/SKILL.md" "$SKILL_DIR/$s/SKILL.md"+    echo "Installed skill -> $SKILL_DIR/$s/SKILL.md"+  fi done-echo "Installed adom-jlcpcb"+echo "adom-jlcpcb installed. Try: adom-jlcpcb --help"
package.json+33−4
@@ -1,7 +1,36 @@ {   "slug": "adom-jlcpcb",-  "version": "1.0.0",+  "version": "1.0.1",   "type": "app",-  "description": "Check the JLCPCB / LCSC parts library before you fab — Basic vs Extended tier, LCSC stock and assembly pricing, so you avoid surprise feeder-setup fees. CLI, a Hydrogen app, and a shared backend.",-  "dependencies": {}-}+  "description": "Check the JLCPCB / LCSC parts library before you fab \u2014 Basic vs Extended tier, LCSC stock and assembly pricing, so you avoid surprise feeder-setup fees. CLI, a Hydrogen app, and a shared backend.",+  "dependencies": {},+  "tags": [+    "jlcpcb",+    "lcsc",+    "basic-part",+    "extended-part",+    "assembly",+    "pcba",+    "electronics",+    "open-source",+    "mit"+  ],+  "license": "MIT",+  "needs_sudo": false,+  "scripts": {+    "install": "./install.sh",+    "uninstall": "./uninstall.sh"+  },+  "files": [+    "bin/**",+    "skills/**",+    "install.sh",+    "uninstall.sh",+    "package.json",+    "page.json",+    "README.md",+    "SKILL.md",+    "BUILD-SKILL.md",+    "screenshots/**"+  ]+}\ No newline at end of file
page.json+1−1
@@ -4,7 +4,7 @@   "slug": "adom-jlcpcb",   "title": "JLCPCB Parts Library",   "brief": "Check the JLCPCB / LCSC parts library before you fab \u2014 Basic vs Extended tier, LCSC stock and assembly pricing, so you avoid surprise feeder-setup fees. CLI, a Hydrogen app, and a shared backend.",-  "version": "1.0.0",+  "version": "1.0.1",   "install": {     "binary_name": "adom-jlcpcb",     "install_dir": "",
skills/adom-jlcpcb-build/SKILL.mdadded+75
@@ -0,0 +1,75 @@+---+name: adom-jlcpcb-build+description: Build and release a new version of adom-jlcpcb. Use when the user says "release adom-jlcpcb", "publish adom-jlcpcb", "cut a new adom-jlcpcb version", "bump adom-jlcpcb", "ship adom-jlcpcb", or "push adom-jlcpcb to the wiki".+---++# Release adom-jlcpcb++A release syncs five places to the same version X.Y.Z:+`VERSION`, `Cargo.toml`, `adom-jlcpcb --version`, wiki page `metadata.version`, running `/health` on the service container.++## Steps++1. **Bump** — decide X.Y.Z (semver). Then:+   ```bash+   echo "X.Y.Z" > VERSION+   sed -i 's/^version = .*/version = "X.Y.Z"/' Cargo.toml+   ```++2. **Local build + smoke test**:+   ```bash+   ./build.sh+   adom-jlcpcb --version                    # must print "adom-jlcpcb X.Y.Z"+   adom-jlcpcb health                       # backend reachable+   adom-jlcpcb search "STM32F103RBT6" --limit 1 | jq '.components[0].mouser_pn'+   ```++3. **Ralph loop the UI** (per app-creator): open in pup, drive a real search, screenshot, check `/console` for errors.+   ```bash+   JLCPCB_API=<backend> adom-jlcpcb app --no-tab &+   adom-desktop browser_open_window '{"sessionId":"jlcpcb","profile":"jlcpcb","url":"http://127.0.0.1:8892"}'+   # drive a search, screenshot, verify 0 console errors+   ```++4. **Show the user a screenshot and wait for explicit approval** before publishing. The app-creator skill is hard about this.++5. **Publish**:+   ```bash+   ./publish.sh+   ```+   Runs: git commit + tag `vX.Y.Z`, `git push origin main --tags`, `gh release create`, `adom-wiki asset upload` (replaces the prior `docker_binary`), `adom-wiki page update`, and a final curl of the wiki binary to check `--version` returns X.Y.Z.++6. **Service container picks it up automatically** — `service/watchdog.sh` runs every 2 min, `git fetch`es origin/main, and rebuilds + restarts when HEAD moves. Verify within ~5 min:+   ```bash+   curl -s https://jlcpcb-<slug>.adom.cloud/health | jq '.version'   # → "X.Y.Z"+   ```++7. **Verify on a fresh user container** (optional, but catches gallia regressions):+   ```bash+   # on a fresh container:+   node ~/gallia/install.mjs                 # Tier A block fetches from wiki+   adom-jlcpcb --version                     # → "adom-jlcpcb X.Y.Z"+   ```++## Pre-release checklist++- [ ] `VERSION`, `Cargo.toml`, `adom-jlcpcb --version`, wiki `metadata.version`, `/health` all return X.Y.Z+- [ ] Wiki page at `apps/adom-jlcpcb` renders the new `install_hint` one-liner+- [ ] User has seen a working screenshot of the webview+- [ ] No console errors via `GET /console`+- [ ] `gallia/install.mjs` Tier A block still works (pulls + installs the new version)+- [ ] **Brand audit — in-app icons are monochrome white.** Run:+      ```+      grep -nE 'fill="#00b8b0"|stroke="#00b8b0"|color: var\(--accent\)' src/app/*.html src/app/*.svg 2>/dev/null+      ```+      Expected result: empty, OR only the text-color rules (`.jlcpcb-pn`,+      `<a>`, focus-rings) on non-SVG elements. Any match on an `<svg>` or+      a `.logo` / `.icon` class CSS rule is a bug — the brand skill+      requires monochrome white for in-app icons. See+      `app-creator` §1b and §Checklist.++## Notes++- **Never skip the ralph loop** — a green `cargo build` is not proof the UI works. Fonts, search, card rendering must be seen working.+- **Wiki upload is idempotent** — `adom-wiki asset upload --asset-type docker_binary` replaces the prior binary for this app automatically.+- **Version discipline is load-bearing** — `refresh-wiki-catalog.mjs` uses semver comparison to surface stale installs; inconsistent versions silently break that.
skills/adom-jlcpcb/SKILL.mdadded+212
@@ -0,0 +1,212 @@+---+name: adom-jlcpcb+description: Search JLCPCB Electronics for components, pricing, stock, and part numbers. Use when the user asks to find components on JLCPCB, check JLCPCB pricing, look up a JLCPCB part number, search for in-stock parts, get price breaks, compare alternatives, or find a datasheet or product page for a specific part. Also use for "open jlcpcb", "jlcpcb app", "jlcpcb search UI".+---++# JLCPCB Electronics Search++Search JLCPCB's catalog of millions of electronic components from thousands of manufacturers. Real-time pricing, stock, lead times, and product links.++## What you have++A single CLI — `adom-jlcpcb` — with three faces:++1. **One-shot search from the shell**, for when the AI just needs the data:+   ```bash+   adom-jlcpcb search "STM32F103RBT6"+   adom-jlcpcb part C8734+   adom-jlcpcb health+   ```+   Each prints JSON on stdout and an `OK:` / `ERROR:` line on stderr, so `| jq` works cleanly.++2. **A Hydrogen webview app**, for when the user wants to browse interactively:+   ```bash+   adom-jlcpcb app        # opens a "JLCPCB Search" tab in Hydrogen+   ```+   The app has a search bar, in-stock filter, per-result cards with price breaks, MPN/JLCPCB-PN copy buttons, datasheet + product-page links, and hover tooltips on every control.++3. **A backend HTTP service** (port 8774), which is what the shared `service-jlcpcb` container runs:+   ```bash+   adom-jlcpcb serve      # JLCPCB_API_KEY_UNUSED_placeholder must be set+   ```+   The CLI and the app both talk to this backend over HTTP (`POST /` with an `{"action":"search"|"part"|"health", ...}` body, or `GET /search?keyword=...`). It caches responses for 10 min and keeps the API key server-side.++There is no MCP server. All access is through the CLI + HTTP service.++## Commands++### `adom-jlcpcb search <keyword>`++Search by keyword, MPN, or JLCPCB PN.++| Flag | Default | Description |+|---|---|---|+| `--limit N` | 10 | Max results (1–50) |+| `--in-stock-only` | false | Only parts currently in stock |+| `--api URL` / `$JLCPCB_API` | auto | Backend URL. If unset, the CLI tries `http://127.0.0.1:8774`, and if that's also down it falls back to calling JLCPCB directly (requires `JLCPCB_API_KEY_UNUSED_placeholder`) |++Examples:+```bash+adom-jlcpcb search "STM32F103RBT6" --limit 5+adom-jlcpcb search "USB-C connector" --in-stock-only+adom-jlcpcb search "LDO 3.3V 500mA SOT-23"+adom-jlcpcb search "ESP32 WiFi Bluetooth" | jq '.components[].mpn'+```++### `adom-jlcpcb part <part-number>`++Full detail lookup for a specific part. Accepts JLCPCB PN (`C8734`) or MPN (`STM32F103RBT6`). Returns a single-component result with full price-break table and attributes.++```bash+adom-jlcpcb part C8734+adom-jlcpcb part STM32F103RBT6 | jq '.components[0].price_tiers'+```++### `adom-jlcpcb app`++Open the search UI in a Hydrogen webview tab.++| Flag | Default | Description |+|---|---|---|+| `--port N` | 8892 | Local app HTTP server port |+| `--api URL` | auto | Backend to use (same resolution as `search`) |+| `--tab-name S` | "JLCPCB Search" | Hydrogen tab label |+| `--no-tab` | false | Skip opening the tab (test via curl or browser) |+| `--dev` | false | Enable the `/eval` hot-patch channel |++```bash+adom-jlcpcb app                         # normal use+adom-jlcpcb app --dev                   # enable /eval for UI debugging+adom-jlcpcb app --no-tab --port 8892 &  # local-browser mode+```++When `adom-jlcpcb app` is running, these HTTP endpoints are AI-drivable (no UI clicks needed):++```bash+# run a search via HTTP, watch the UI update live+curl -X POST http://127.0.0.1:8892/search \+  -H 'Content-Type: application/json' \+  -d '{"keyword":"ESP32","limit":5,"inStockOnly":false}'++# state + cached last-search+curl http://127.0.0.1:8892/state | jq++# UI-side console logs (what the frontend JS printed)+curl http://127.0.0.1:8892/console | jq '.messages[-10:]'++# backend-health proxy (so the UI doesn't need CORS to 8774)+curl http://127.0.0.1:8892/backend-health | jq++# shutdown cleanly (removes the Hydrogen tab and exits)+curl -X POST http://127.0.0.1:8892/shutdown+```++### `adom-jlcpcb serve`++Run the backend HTTP proxy. This is what the `service-jlcpcb` container runs.++| Flag | Default | Description |+|---|---|---|+| `--port N` / `$JLCPCB_PORT` | 8774 | Port |++Requires `JLCPCB_API_KEY_UNUSED_placeholder`. Endpoints:++```+GET  /health                                  — health + live API ping+GET  /search?keyword=...&limit=10&inStockOnly=false+GET  /part?partNumber=...+POST /              {"action":"search"|"part"|"health", ...}+GET  /              (text/html landing page)+```++### `adom-jlcpcb health`++Check reachability.++```bash+adom-jlcpcb health                 # checks backend (or falls back to JLCPCB direct)+adom-jlcpcb health --api http://127.0.0.1:8774+```++## What's in a result++Each component in `.components[]` has:++- `mouser_pn`    — JLCPCB part number, use this for BOM+- `mpn`          — manufacturer part number, use this for schematic/footprint+- `manufacturer` — manufacturer name+- `description`, `category`+- `stock`        — integer count in JLCPCB's warehouse (live, 10-min cache on backend)+- `stock_text`   — raw JLCPCB text ("In Stock", "Non-Stocked", etc.)+- `popularity`   — `low` / `medium` / `high` heuristic from stock+- `lead_time`    — factory lead time if ordering more+- `unit_price`   — price at qty 1+- `price_tiers`  — array of `{qty, price}` for quantity price breaks+- `min_order`, `mult` — minimum order + order multiple+- `rohs`         — compliance flag+- `lifecycle`    — New Product / Active / NRND / Obsolete+- `datasheet_url`, `product_url`, `image_url`+- `attributes`   — array of `{name, value}` from the product-attribute table++## Typical workflows++### Finding a part from scratch+```bash+adom-jlcpcb search "32-bit ARM Cortex-M3 microcontroller LQFP-48"+# pick one, then:+adom-jlcpcb part <jlcpcb-pn>+```++### Confirming price for a BOM entry+```bash+adom-jlcpcb part STM32F103RBT6 | jq '.components[0] | {mouser_pn, unit_price, price_tiers, stock}'+```++### Browsing interactively+```bash+adom-jlcpcb app+# then type in the search box, click Product page / Datasheet, etc.+```++## Running the backend++There are two common setups.++### Dedicated `service-jlcpcb` container (shared, has the API key)++The backend proxy runs on a dedicated `default-light` container with `JLCPCB_API_KEY_UNUSED_placeholder` set in `/etc/environment` and a cron watchdog (`service/watchdog.sh`, every 2 min) that (a) keeps the service healthy and (b) auto-pulls `origin/main` + rebuilds when new versions land. Consumer containers point `JLCPCB_API` at its public URL:++```+https://jlcpcb-wela51osctvp.adom.cloud+```++`curl /health` should return `{"ok":true, "api_reachable":true, "version":"X.Y.Z", ...}`. Recover the current URL from `~/service-watcher/services.json` (`jlcpcb` entry, `"primary": true`) if the slug has rotated. To point the CLI at it:++```bash+export JLCPCB_API=https://jlcpcb-wela51osctvp.adom.cloud+adom-jlcpcb search "LM317"+adom-jlcpcb app        # UI reads $JLCPCB_API automatically+```++Gallia users don't need to set `JLCPCB_API` explicitly — `adom-jlcpcb` is a Tier A app (see `adom-app-model`), so it's installed by every `gallia/install.mjs` run from the wiki binary. The CLI autodetects a local `adom-jlcpcb serve` on 127.0.0.1:8774 and falls back to calling JLCPCB directly if `JLCPCB_API_KEY_UNUSED_placeholder` is set locally.++### Local-only (quick testing)++On any container, if `JLCPCB_API_KEY_UNUSED_placeholder` is set and you run `adom-jlcpcb serve &`, the CLI and the app will autodetect `http://127.0.0.1:8774` and use it. This is the dev-loop path.++## Installation++The binary is distributed as a GitHub release from `adom-inc/adom-jlcpcb`. After downloading to `/usr/local/bin/adom-jlcpcb` and making it executable, run:++```bash+adom-jlcpcb install+```++This deploys the skill to `~/.claude/skills/jlcpcb/SKILL.md` and installs bash completions.++## Notes++- Price data does not include shipping or tariffs.+- Stock is live at query time (10-min cache on the backend).+- Results are sorted by JLCPCB's internal relevance algorithm, not strictly by stock.+- `JLCPCB_API_KEY_UNUSED_placeholder` is only ever needed on the backend (`serve`) side. Consumer containers just need `JLCPCB_API` pointing at a running backend.
uninstall.sh+4−3
@@ -1,4 +1,5 @@ #!/bin/bash-set -e-rm -rf "$HOME/.claude/skills/adom-jlcpcb"-echo "Uninstalled adom-jlcpcb"+set -euo pipefail+rm -f "${HOME}/.local/bin/adom-jlcpcb"+rm -rf "${HOME}/.claude/skills/adom-jlcpcb" "${HOME}/.claude/skills/adom-jlcpcb-build"+echo "Removed adom-jlcpcb"