💬 Sample prompts Paste any of these into Claude Code to use this skill
Open URL Open https://example.com in a pup window
Reload Reload the pup window for my dev server
Screenshot Screenshot the active pup window
Eval JS Eval document.title in the pup window
Close Close the pup window for session 'demo'
Install this skill

Paste this into Claude Code (VS Code panel, Adom editor, or terminal) to install:

Search the Adom Wiki for the skill "pup" (slug: pup) at https://wiki-ufypy5dpx93o.adom.cloud/wiki/skills/pup and install it into my local ~/.claude/skills/pup/ directory. Fetch the skill_source content from the wiki page and save it as SKILL.md. Then confirm it's installed by showing the first 5 lines.
?
What is a skill? Skills are instructions that teach AI assistants like Claude Code how to perform specific tasks. The description below is loaded into the AI as context when you invoke this skill. Well-written skills make the AI significantly more effective. Like Wikipedia, anyone can improve a skill by clicking Edit AI Skill — or have your AI submit an edit on your behalf.

Description

Edit AI Skill

name: pup user-invocable: true description: "Control Puppeteer browser windows on the user's desktop via the adom-desktop CLI. Use for: opening/closing browser windows, reloading pages, taking screenshots, evaluating JS, flashing taskbar alerts, navigating URLs, checking errors, managing multi-session Chrome. Trigger words: pup, puppeteer, browser window, browser reload, browser screenshot, pup reload, pup screenshot, pup alert, browser debug, visual debug, open in browser, reload browser, flash taskbar, browser_reload, browser_alert_window, browser_open_window, browser_screenshot, browser_eval."

Pup — Puppeteer Browser Control

Control Chrome browser windows on the user's desktop via the adom-desktop CLI.

How to Run Commands

All browser_* commands are run via the adom-desktop CLI using Bash:

adom-desktop <command> '<json_args>'

Examples:

adom-desktop browser_reload '{"sessionId":"dart2"}'
adom-desktop browser_alert_window '{"sessionId":"dart2"}'
adom-desktop browser_screenshot '{"sessionId":"dart2"}'
adom-desktop browser_open_window '{"sessionId":"myapp","profile":"myapp","url":"http://localhost:3000"}'
adom-desktop browser_eval '{"sessionId":"dart2","expr":"document.title"}'

IMPORTANT: These are NOT MCP tools. They are Bash commands. Use the Bash tool to run them.

Available Commands

Session Management

CommandDescriptionRequired Args
browser_open_windowOpen/navigate a browser tabsessionId, profile, url
browser_close_windowClose a specific sessionsessionId
browser_focus_windowBring window to foregroundsessionId (optional)
browser_alert_windowFlash taskbar icon (non-intrusive)sessionId (optional)
browser_switch_windowSwitch global active sessionsessionId
browser_list_windowsList all open sessionsnone

Page Commands (all accept optional sessionId)

CommandDescriptionKey Args
browser_reloadReload page + clear error logsessionId
browser_navigateNavigate to new URLurl, sessionId
browser_screenshotCapture page screenshot (lossless PNG)sessionId, maxWidth, fullPage
browser_evalEvaluate JS expression in pageexpr, sessionId
browser_errorsGet console/page errorssessionId
browser_waitWait for content to settlems (default 3000)
browser_statusCheck all sessionsnone
browser_closeClose ALL sessionsnone

Common Patterns

Reload + Alert (after code changes)

adom-desktop browser_reload '{"sessionId":"dart2"}' && \
adom-desktop browser_alert_window '{"sessionId":"dart2"}'

Debug Loop

  1. Edit code
  2. browser_reload
  3. browser_wait (3-5s for 3D tiles)
  4. browser_screenshot
  5. browser_errors
  6. Analyze, repeat if needed

Check Connectivity

adom-desktop ping

Pick ONE surface — pup OR Hydrogen, never both

When you need a browser surface for a task, pick ONE: pup (your automation puppet) OR a Hydrogen webview tab (the user's interactive view). Never open the same content in both at once. User feedback 2026-04-26: "why the fuck did you open something in pup and some stuff in webview. pick one or the other."

Two costs of dual-opening:

  1. Two copies of the page → user sees changes in one but not the other → "why doesn't my upload show up?" or "which one is real?".
  2. Background WS / polling traffic doubles, which makes the Cloudflare-blipping problem worse.

The decision rule:

Use caseSurfaceWhy
Automated test, screenshot, eval, ralph loop, scripted multi-step demopupscriptable; doesn't compete with the user's tabs; pup's browser_eval works on every tab
Showing the user a finished result they should look atHydrogen webview tab (adom-cli hydrogen webview open-or-refresh)the tab persists in their workspace; they can interact normally
Both at once for the SAME contentdon'tpick whichever role the situation calls for and stick with it

If you've opened the user's Hydrogen tab for a dashboard / viewer, use that tab for screenshots too via adom-cli hydrogen screenshot panel --name "<tab-name>". Don't ALSO open a pup window of the same URL. If you started in pup for testing and the user wants to see the final state, route them to a Hydrogen tab once and close the pup window.

Memory rule still applies for testing: pup is the testing surface, NOT Hydrogen. The point of THIS rule is: don't open both for the SAME content at the SAME time.

Multi-URL workflows — ONE window, MANY tabs

When you'd open more than one URL for the same user task (vendor fetch, multi-doc review, compare-pages workflows), put them in tabs of one window, not separate windows. User feedback 2026-04-26: "when you make all those pup windows, they clutter up the user's desktop, so you should open all of those as tabs in one pup window."

# 1) Create the window with the first URL.
adom-desktop browser_open_window '{
  "sessionId":"my-task","profile":"my-task",
  "url":"https://first.example.com"
}'

# 2) Add the rest as tabs in the SAME session.
adom-desktop browser_open_tab '{"sessionId":"my-task","url":"https://second.example.com"}'
adom-desktop browser_open_tab '{"sessionId":"my-task","url":"https://third.example.com"}'

# 3) Activate a specific tab when you want to screenshot or eval it.
adom-desktop browser_switch_tab '{"sessionId":"my-task","tabId":"tab-2"}'
adom-desktop browser_screenshot   '{"sessionId":"my-task","maxWidth":1500}'
adom-desktop browser_eval         '{"sessionId":"my-task","expr":"document.title"}'

browser_open_tab lives alongside the documented browser_* verbs. Same JSON-args convention; same sessionId semantics.

Pick a stable profile name across runs of the same task so the cookie jar persists — the user logs in once and reuses for 12+ months. Cross-vendor cookie blending is fine because cookies are per-domain.

Verify what you opened — "ok": true is not enough

browser_open_window / browser_open_tab returns "ok": true as soon as the navigation starts, NOT when the page actually rendered useful content. Always sanity-check the result:

# Title check — fastest. 404s, anti-bot blocks, and login walls
# all change the title.
adom-desktop browser_eval '{"sessionId":"my-task","expr":"document.title"}'

# Screenshot — slowest, most thorough. Use when title isn't
# discriminating (e.g. SPA that updates title async).
adom-desktop browser_screenshot '{"sessionId":"my-task"}'

Never blindly template a part number into a vendor URL pattern without verifying the page exists. The cost of a 404 you didn't catch is the user spotting it instead. (Real example: shipped a manufacturer-search-URL pattern that 404'd on ti.com/product/ and nxp.com/ for parts those vendors don't make. Using a google.com/search?q=… link routes through Google's resolver and gets a real product hit on the first result.)

Key Rules

  • Always pass sessionId — never use '{}' as args. The default targets the active session which may not be what you want.
  • adom-desktop browser_<cmd> <json> — never adom-desktop pup <cmd> --flags. There is no pup subcommand at the top level; that pattern fails with "Invalid JSON args".
  • No semicolons in browser_eval — use comma operator or IIFE instead.
  • Sessions persist — IndexedDB, cookies, localStorage survive restarts. Profile name is the persistence key.
  • Each session = independent Chrome window — crash-isolated. Multiple tabs share one session and one cookie jar.
  • Never kill Chrome broadly — use browser_close_window for specific sessions.
  • Always reload + alert after browser-facing code changes — the user expects to see updates immediately.

Full Reference

For detailed docs (profiles, sleep/wake recovery, troubleshooting, first-time setup), see ~/.claude/skills/adom/guides/pup.md.

Skill Source

Edit AI Skill
---
name: pup
user-invocable: true
description: "Control Puppeteer browser windows on the user's desktop via the adom-desktop CLI. Use for: opening/closing browser windows, reloading pages, taking screenshots, evaluating JS, flashing taskbar alerts, navigating URLs, checking errors, managing multi-session Chrome. Trigger words: pup, puppeteer, browser window, browser reload, browser screenshot, pup reload, pup screenshot, pup alert, browser debug, visual debug, open in browser, reload browser, flash taskbar, browser_reload, browser_alert_window, browser_open_window, browser_screenshot, browser_eval."
---

# Pup — Puppeteer Browser Control

Control Chrome browser windows on the user's desktop via the `adom-desktop` CLI.

## How to Run Commands

All `browser_*` commands are run via the `adom-desktop` CLI using Bash:

```bash
adom-desktop <command> '<json_args>'
```

**Examples:**
```bash
adom-desktop browser_reload '{"sessionId":"dart2"}'
adom-desktop browser_alert_window '{"sessionId":"dart2"}'
adom-desktop browser_screenshot '{"sessionId":"dart2"}'
adom-desktop browser_open_window '{"sessionId":"myapp","profile":"myapp","url":"http://localhost:3000"}'
adom-desktop browser_eval '{"sessionId":"dart2","expr":"document.title"}'
```

**IMPORTANT:** These are NOT MCP tools. They are Bash commands. Use the Bash tool to run them.

## Available Commands

### Session Management
| Command | Description | Required Args |
|---|---|---|
| `browser_open_window` | Open/navigate a browser tab | `sessionId`, `profile`, `url` |
| `browser_close_window` | Close a specific session | `sessionId` |
| `browser_focus_window` | Bring window to foreground | `sessionId` (optional) |
| `browser_alert_window` | Flash taskbar icon (non-intrusive) | `sessionId` (optional) |
| `browser_switch_window` | Switch global active session | `sessionId` |
| `browser_list_windows` | List all open sessions | none |

### Page Commands (all accept optional `sessionId`)
| Command | Description | Key Args |
|---|---|---|
| `browser_reload` | Reload page + clear error log | `sessionId` |
| `browser_navigate` | Navigate to new URL | `url`, `sessionId` |
| `browser_screenshot` | Capture page screenshot (lossless PNG) | `sessionId`, `maxWidth`, `fullPage` |
| `browser_eval` | Evaluate JS expression in page | `expr`, `sessionId` |
| `browser_errors` | Get console/page errors | `sessionId` |
| `browser_wait` | Wait for content to settle | `ms` (default 3000) |
| `browser_status` | Check all sessions | none |
| `browser_close` | Close ALL sessions | none |

## Common Patterns

### Reload + Alert (after code changes)
```bash
adom-desktop browser_reload '{"sessionId":"dart2"}' && \
adom-desktop browser_alert_window '{"sessionId":"dart2"}'
```

### Debug Loop
1. Edit code
2. `browser_reload`
3. `browser_wait` (3-5s for 3D tiles)
4. `browser_screenshot`
5. `browser_errors`
6. Analyze, repeat if needed

### Check Connectivity
```bash
adom-desktop ping
```

## Pick ONE surface — pup OR Hydrogen, never both

When you need a browser surface for a task, pick ONE: pup (your
automation puppet) OR a Hydrogen webview tab (the user's interactive
view). **Never open the same content in both at once.** User
feedback 2026-04-26: *"why the fuck did you open something in pup
and some stuff in webview. pick one or the other."*

Two costs of dual-opening:
1. Two copies of the page → user sees changes in one but not the
   other → "why doesn't my upload show up?" or "which one is
   real?".
2. Background WS / polling traffic doubles, which makes the
   Cloudflare-blipping problem worse.

The decision rule:

| Use case | Surface | Why |
|---|---|---|
| Automated test, screenshot, eval, ralph loop, scripted multi-step demo | **pup** | scriptable; doesn't compete with the user's tabs; pup's `browser_eval` works on every tab |
| Showing the user a finished result they should look at | **Hydrogen webview tab** (`adom-cli hydrogen webview open-or-refresh`) | the tab persists in their workspace; they can interact normally |
| Both at once for the SAME content | **don't** | pick whichever role the situation calls for and stick with it |

If you've opened the user's Hydrogen tab for a dashboard / viewer,
use **that** tab for screenshots too via `adom-cli hydrogen
screenshot panel --name "<tab-name>"`. Don't ALSO open a pup
window of the same URL. If you started in pup for testing and the
user wants to see the final state, route them to a Hydrogen tab
once and close the pup window.

Memory rule still applies for testing: pup is the testing surface,
NOT Hydrogen. The point of THIS rule is: don't open both for the
SAME content at the SAME time.

## Multi-URL workflows — ONE window, MANY tabs

When you'd open more than one URL for the same user task (vendor
fetch, multi-doc review, compare-pages workflows), put them in
**tabs of one window**, not separate windows. User feedback
2026-04-26: *"when you make all those pup windows, they clutter
up the user's desktop, so you should open all of those as tabs
in one pup window."*

```bash
# 1) Create the window with the first URL.
adom-desktop browser_open_window '{
  "sessionId":"my-task","profile":"my-task",
  "url":"https://first.example.com"
}'

# 2) Add the rest as tabs in the SAME session.
adom-desktop browser_open_tab '{"sessionId":"my-task","url":"https://second.example.com"}'
adom-desktop browser_open_tab '{"sessionId":"my-task","url":"https://third.example.com"}'

# 3) Activate a specific tab when you want to screenshot or eval it.
adom-desktop browser_switch_tab '{"sessionId":"my-task","tabId":"tab-2"}'
adom-desktop browser_screenshot   '{"sessionId":"my-task","maxWidth":1500}'
adom-desktop browser_eval         '{"sessionId":"my-task","expr":"document.title"}'
```

`browser_open_tab` lives alongside the documented `browser_*`
verbs. Same JSON-args convention; same `sessionId` semantics.

Pick a stable `profile` name across runs of the same task so the
cookie jar persists — the user logs in once and reuses for 12+
months. Cross-vendor cookie blending is fine because cookies are
per-domain.

## Verify what you opened — `"ok": true` is not enough

`browser_open_window` / `browser_open_tab` returns `"ok": true` as
soon as the navigation starts, NOT when the page actually
rendered useful content. Always sanity-check the result:

```bash
# Title check — fastest. 404s, anti-bot blocks, and login walls
# all change the title.
adom-desktop browser_eval '{"sessionId":"my-task","expr":"document.title"}'

# Screenshot — slowest, most thorough. Use when title isn't
# discriminating (e.g. SPA that updates title async).
adom-desktop browser_screenshot '{"sessionId":"my-task"}'
```

**Never blindly template a part number into a vendor URL pattern
without verifying the page exists.** The cost of a 404 you didn't
catch is the user spotting it instead. (Real example: shipped a
manufacturer-search-URL pattern that 404'd on `ti.com/product/`
and `nxp.com/` for parts those vendors don't make. Using a
`google.com/search?q=…` link routes through Google's resolver
and gets a real product hit on the first result.)

## Key Rules

- **Always pass `sessionId`** — never use `'{}'` as args. The default targets the *active* session which may not be what you want.
- **`adom-desktop browser_<cmd> <json>` — never `adom-desktop pup <cmd> --flags`.** There is no `pup` subcommand at the top level; that pattern fails with "Invalid JSON args".
- **No semicolons in `browser_eval`** — use comma operator or IIFE instead.
- **Sessions persist** — IndexedDB, cookies, localStorage survive restarts. Profile name is the persistence key.
- **Each session = independent Chrome window** — crash-isolated. Multiple tabs share one session and one cookie jar.
- **Never kill Chrome broadly** — use `browser_close_window` for specific sessions.
- **Always reload + alert after browser-facing code changes** — the user expects to see updates immediately.

## Full Reference

For detailed docs (profiles, sleep/wake recovery, troubleshooting, first-time setup), see `~/.claude/skills/adom/guides/pup.md`.

Sub-Skills
?
What are Sub-Skills?

Sub-skills are community-contributed AI skill extensions for this component. They teach AI assistants about specific tools, configurators, or workflows.

Examples:

  • A manufacturer’s configuration tool for a motor controller
  • A community-written design guide for an amplifier circuit
  • An automated test/validation script for a sensor module

How to add one: Click Add Sub-Skill, provide the URL to your skill and a brief description. Submissions are reviewed by the Adom team before going live.

No sub-skills yet. Be the first to contribute one!

Recent activity

1 commit
  • Edit v1.0.1 John Lauer 26 days ago
    Sync with gallia — fixed user-invocable spelling and dropped unsupported frontmatter fields
0 revisions · Updated 2026-05-01 14:14:19