Skills move to skills/<name>/SKILL.md and the repo gains both manifests, so it is now a marketplace hosting exactly one plugin whose root is the repo root (source: "."). Claude Code installs it from git; no symlinks involved. Why: install.sh wired the library into every consuming repo as an ABSOLUTE symlink to $CHECKOUT_DIR. The checkout moved three times, most recently when local-dev@1966d5a dropped the embedded .skills/ copy, and nothing migrated the links — 243 dangling links across 12 repos, hidden from git by the **/.claude/skills/ ignore rule. Worse, ~/dev spans two path roots (/Users/mathias on the iCloud-shared Macs, /home/mathias on koala), so an absolute link stored there is broken on one side by construction. Re-running the installer cannot fix that; only removing the mechanism can. install.sh keeps the harnesses with no plugin system and drops from 42 links per harness to one directory link, via the convergent ~/.agents/skills convention that Pi and OpenCode both read: ~/.agents/skills -> $CHECKOUT_DIR/skills ~/.config/crush/skills -> ~/.agents/skills ~/.config/opencode/skills -> ~/.agents/skills wire_claude_repo is deleted outright rather than gated behind a flag — on a mixed-root fleet it cannot be made correct. Antigravity and Vibe targets go too; both unused. CHECKOUT_DIR keeps its host-local default deliberately: pointing it into ~/dev would put a git working tree inside iCloud with two concurrent writers. Taskfile drops five near-identical wiring loops (they had already drifted) and delegates to install.sh. `task check` gains frontmatter validation, a stray-root-entry gate, and manifest/tag version parity — the loose secret-hygiene.md sat unloadable for months because nothing checked layout. Verified: claude plugin validate . passes clean; a probe skill loaded as skills:zzprobe through --plugin-dir; task check green at 42 skills. Refs: #23 Bump-Type: minor Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BeAp5LTscnz2W7Ubt4eJ6m
3.7 KiB
3.7 KiB
name, description
| name | description |
|---|---|
| web-shot | Screenshot any running web UI by spawning a one-shot Playwright Job on the koala k3s cluster. Auto-detects the calling host's Tailscale name so a dev server on flamingo:8099, iguana:3000 or koala:8181 just works. Use when the user asks for a screenshot, visual verification, "what does the UI look like", or any time chromium / firefox / a browser is requested but none is installed on the host. |
web-shot
Screenshot a locally-running web UI without installing a browser on the agent's host.
Mechanism
shot.shbuilds a k8s Job that runsmcr.microsoft.com/playwright:v1.49.0-jammyon koala's k3s cluster.hostNetwork: trueis not used — the pod uses cluster DNS so Tailscale Magic DNS resolvesflamingo,iguana,koaladirectly when the koala node has Tailscale up (it does).- The pod renders the URL with chromium, drops PNGs into an
emptyDir, thensleeps briefly sokubectl cpcan pull the files out. - PNGs land in
./screenshots/(or--out DIR) on the agent's host.
Prerequisites
kubectlon the calling host with a kubeconfig pointing at koala's k3s.- The dev server binds 0.0.0.0 (not 127.0.0.1) so pods on koala can reach it across Tailscale. For Go:
http.ListenAndServe(":8099", ...). For Node:--host 0.0.0.0. For Vite:--host. - The dev server's host (flamingo, iguana, koala, …) is reachable on Tailscale and Magic DNS resolves the short hostname.
Usage
# auto-detect Tailscale hostname, screenshot port 8099 root
~/dev/.skills/web-shot/shot.sh --port 8099
# explicit URL
~/dev/.skills/web-shot/shot.sh --url http://flamingo:5173
# capture a search state too (types into input[name=q])
~/dev/.skills/web-shot/shot.sh --port 8181 --search agentsquad
# different output dir
~/dev/.skills/web-shot/shot.sh --port 3000 --out /tmp/shots
Flags
| Flag | Default | Notes |
|---|---|---|
--port N |
— | Host port. Combined with --host and --path. |
--path P |
/ |
URL path after the host:port. |
--host H |
auto via tailscale status |
Override the hostname pods will dial. |
--url U |
— | Full URL. Overrides --host, --port, --path. |
--search Q |
— | Also capture a search state — types Q into input[name=q]. |
--out D |
./screenshots |
Output dir (created if missing). |
--name N |
web-shot |
Job name prefix. |
-h |
— | Show usage. |
Output
<out>/home.png— initial page.<out>/search.png— only when--searchwas passed.
Failure modes
kubectl: command not found→ install kubectl + tailscale-mode kubeconfig.connection refusedfrom the pod → dev server bound to 127.0.0.1, fix the bind.No matches for selectorwhen--searchwas given → page lacksinput[name=q]. Use a project-specific script or rerun without--search.- Image pull slow on first run → ~1GB playwright image cached on koala after first use.
When NOT to use
- The site needs auth / cookies / login state — extend the script or use a project-local Playwright suite.
- You need PDF, video, or interaction more elaborate than "type a query and screenshot". Promote to a real Playwright test under the project repo.