Adom Hydrogen (platform base)
Public Made by Adomby adom
Layer Hydrogen's workspace onto a standard Adom workstation.
name: hydrogen-open-url description: > The decision guide for "open a URL / open a website" inside Hydrogen. When the user says "open ti.com" / "pull up the datasheet page" / "show me that site", Hydrogen has SIX distinct ways to do it — a Hydrogen webview tab, an Hydrogen browser window, Pup (AI-drivable Chrome), a native desktop browser profile, the Browser Picker chooser, or headless curl/fetch — each with different trade-offs. READ THIS to pick the right one and to explain the options back to the user instead of silently guessing. For the interception/plumbing behind the picker see hydrogen-browser-picker; to drive Pup see pup; for webview tabs see adom-workspace-control. Trigger words — open url, open website, open the site, open ti.com, open a link, pull up the page, show me the website, view this url, open in browser, which browser, how do I open, open the datasheet page, open in a tab, open in pup, open in chrome, headless fetch, ways to open a url, open link options, wv, open in wv, open as wv, webview tab, wv tab.
Hydrogen — Opening a URL (your options)
When a user says "open the ti.com website" (or any URL), Hydrogen has several paths and a Browser Picker — but don't hand the user the picker to decide. Pick the best destination for them by use-case and open it directly, then offer the alternatives in one line. The right path depends on what they're doing — look at it, have you drive it, keep it as a tab, or just read it. See "Decide for the user — DON'T hand them the picker" below for the rule.
The six ways
| # | Option | Best when… | What the user sees | AI drives it? |
|---|---|---|---|---|
| 1 | Hydrogen webview tab (aka wv) | the user wants the site inside Hydrogen, next to their work, and to keep it around | a panel/tab in the Hydrogen workspace | partly (reload/route) |
| 2 | Hydrogen Browser Window | a quick popout window owned by Hydrogen, not a full browser | a standalone Hydrogen-owned window | no |
| 3 | Pup (Puppeteer Chrome) | you need to act on the page — screenshot, click, scrape, fill a form, verify | a real Chrome window on their desktop | yes, fully |
| 4 | Native desktop browser | real logins/sessions, downloads, "just open it for me", auth flows | their own Chrome/Edge profile | no |
| 5 | Browser Picker | you're not sure, or it's an auth/OAuth link — let the user choose (5s auto-default) | a chooser dialog | n/a (routes to one of the above) |
| 6 | curl / fetch (headless) | you only need the content, not to show anything (read a datasheet, scrape JSON) | nothing — runs in the workspace | yes |
"wv" = webview — the shortcut (spread it like pup)
wv is the short alias for "webview" — recognize it everywhere a user might say
"webview" (open it in wv, wv tab, shot the wv, wv mode). Treat wv and webview as
identical.
Help it catch on: the first time in a session a user types the long form "webview",
open it as normal and add a one-line nudge — "(btw you can just say wv — fewer
keystrokes)." Say it once, not every time (don't nag). This is exactly how
puppeteer → pup became universal among Adom folks; webview → wv is the same play.
(If the user already says wv, they got the memo — skip the nudge.)
How you invoke each
All of these run from inside the Hydrogen workspace. The control API base URL is the live
value in ~/.adom/hydrogen-control-url — http://127.0.0.1:<dynamic> (the workspace
shares loopback with the host; the port is dynamic per launch).
Read it with BASE="$(cat ~/.adom/hydrogen-control-url)" then hit "$BASE/<endpoint>".
1. Webview tab (wv) — add a web-view tab pointed at the URL (adom-workspace-control,
or adom-cli hydrogen webview open-or-refresh --name <X> --url <url> --panel-id <id>). Good
for "keep this open while we work." ⚠️ open-or-refresh needs --panel-id to CREATE a new
tab — without it you get "Tab 'X' not found and --panel-id not provided" (verified live
2026-06-14; get a panel id from adom-cli hydrogen workspace get). Re-running with the same
--name once it exists just navigates/refreshes (no panel-id needed). Same adom-cli on
web-Hydrogen and Hydrogen — the consistent surface.
2 / 4 / 5. Through the Browser Picker — the single unifying entry point. POST the URL and Hydrogen routes it (auto-picking a sensible default after a 5-second countdown, or showing the chooser):
BASE="$(cat ~/.adom/hydrogen-control-url)" # http://127.0.0.1:<dynamic>
# Auto-route (picker picks the best default in 5s — hands-free)
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"url":"https://www.ti.com"}' \
"$BASE/open-url"
# Force the chooser dialog (no auto-timer — make the user pick)
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"url":"https://www.ti.com","force":true}' \
"$BASE/open-url"
# Route through the picker with the FRESH-WINDOW toggle pre-checked (the picked
# native browser opens in a new --new-window that auto-foregrounds — use for
# auth/OAuth so the consent page pops to the front by itself):
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"url":"https://claude.ai/","fresh":true,"force":true}' \
"$BASE/open-url"
# …or bypass the picker and open directly+fresh in a specific browser:
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"url":"https://claude.ai/","browser":"edge","profileDir":"Default","fresh":true}' \
"$BASE/open-in-profile"
⚠️
/open-urloften replies"Hydrogen timed out after 5s"even when it SUCCEEDED (verified live 2026-06-14:{"url":"https://www.google.com"}reported the timeout, but the page opened in Edge). Don't treat that as failure — confirm withGET "$BASE/browser-picker/last-open"→{destination, url, fresh, ts}.fresh:false= routed to a remembered/default destination (no picker shown — e.g.browser:edge:Default);fresh:true= the picker was shown. (So if every domain has a remembered default, opens are silent — the picker only pops for un-remembered domains.)
The picker's auto-default heuristic: *.claude.ai/*.claude.com and Adom
/auth/intent → the user's work browser profile; unknown/right-click/iframe →
Pup; otherwise the user's last choice for that domain. See hydrogen-browser-picker.
Fresh window ("fresh":true) — the native-browser path (#4) can open the URL
either as a tab in an already-running browser (default) or as a brand-new window/
process (--new-window). A freshly-launched window auto-foregrounds;
a tab does not. So for auth flows the user must complete (Claude/Adom sign-in),
prefer fresh:true — the consent page comes to the front by itself, no manual focus.
The Browser Picker defaults the "Open in a fresh window" toggle ON for auth URLs.
On /open-url, fresh pre-seeds that toggle (the picker still shows; add direct:true
to skip it); /open-in-profile opens fresh directly. See hydrogen-browser-picker.
3. Pup — open and then drive it with adom-bridge-cli browser_* verbs
(browser_open_window, browser_navigate, browser_screenshot, browser_eval,
browser_reload, …). Either open the URL directly via Pup, or let the picker
route to Pup. See the pup skill for the full verb set.
adom-bridge-cli browser_eval '{"sessionId":"default","js":"document.title"}'
6. Headless content — if you only need to read the page, skip the browser entirely:
curl -sL https://www.ti.com/... # or fetch from your own code
Decide for the user — DON'T hand them the picker
Default behavior: pick the destination by use-case and open it DIRECTLY (bypass
the picker), then give a one-line heads-up + easy undo. Do NOT fire a plain
POST /open-url {url} and let the picker's generic 5-second auto-default decide —
that default is luck-of-the-draw and often wrong for the use-case (a vendor-login
site could land in Pup where the user has no login). Users don't want to make this
choice; make the smart one for them. (Mechanics: /open-in-profile opens a
specific native browser+profile directly; /open-url {direct:true} bypasses the
picker; Pup and webview-tab are direct calls. Reserve the picker only as below.)
| Use case | Open it in | How (bypass the picker) |
|---|---|---|
| Login-likely site — vendor/account/portal/cart: TI, Mouser, DigiKey, any "my…"/sign-in | the user's native browser + WORK profile (their saved login/cookies live there) | GET /browser-profiles → find the work profile (non-gmail) → POST /open-in-profile {url, browser, profileDir, fresh:true} |
| Building/testing their own app, or you need to drive/screenshot/scrape the page | Pup (AI-drivable) | open via Pup (browser_*) / route /open-url {url, direct:true} to Pup |
| Glance at content alongside their work | Hydrogen webview tab | adom-workspace-control add web-view tab |
| Genuinely ambiguous, OR an OAuth/sign-in the user must complete themselves | let them choose | POST /open-url {url, force:true} — the one time the picker is right |
Then say it in one line, with the undo: "Opened TI in your Chrome work profile (where your TI login lives) — say the word for a tab here, Pup, or a different profile." Decide, act, offer alternatives — don't ask first.
Example — "open the texas instruments website" (login-likely → native work profile):
BASE="$(cat ~/.adom/hydrogen-control-url)"
curl -s "$BASE/browser-profiles" # pick the work profile (non-gmail email)
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"url":"https://www.ti.com","browser":"chrome","profileDir":"<work profileDir>"}' \
"$BASE/open-in-profile"
Govern routing policy — the picker is now a true FALLBACK (Hydrogen prefs API)
The picker's per-domain memory is a first-class API (Hydrogen app behavior), so the AI OWNS URL routing — the picker only pops for a domain with no stored policy AND no direct call. Use this to set policy the user would otherwise click through the Manager for ("always open DigiKey in my work profile", "stop auto-opening X in Edge").
BASE="$(cat ~/.adom/hydrogen-control-url)"
# READ the policy map
curl -s "$BASE/browser-picker/prefs"
# → {ok, prefs:{domains:{"<host>":{destination,label}, …}}}
# SET / override one domain
curl -s -X PUT "$BASE/browser-picker/prefs" -H 'Content-Type: application/json' \
-d '{"domain":"digikey.com","destination":"browser:edge:Default","label":"Edge — Default"}'
# FORGET one domain (e.g. "stop auto-opening X in Edge")
curl -s -X DELETE "$BASE/browser-picker/prefs/digikey.com"
# CLEAR all
curl -s -X DELETE "$BASE/browser-picker/prefs"
- Stored value =
{destination, label}— NOTprofileDir/fresh. destinationis an ID:- internal:
hydrogen-tab(a webview/wv tab) ·webview-window·pup-window - native:
browser:<browser>:<dir>— e.g.browser:edge:Default,browser:chrome:Profile 1. The profile dir is encoded in the ID (no separate field).
- internal:
- Discover valid native IDs via
GET $BASE/browser-profiles(maps each detected profile → itsbrowser+dir); the 3 internal IDs are fixed above. freshis NOT stored in prefs — it's a per-OPEN flag (/open-url {fresh:…}//open-in-profile {fresh:…}). Don't try to persist it here.- Writes hit the live Manager UI immediately (the backend writes
hydrogen-url-routing-prefslocalStorage + dispatcheshydrogen-url-routing-prefs-changed; an open Browser Picker Manager re-reads at once, and re-reads on open anyway).
Net: for a one-off open, decide and call the direct endpoint (/open-in-profile,
/open-url {direct:true}, or a wv/pup call). For a standing preference, PUT the domain's
policy so even user-initiated link clicks route there silently. The picker is now only a
fallback for the genuinely-undecided.
Related skills
- hydrogen-browser-picker — the interception layers + picker dialog behind #2/#4/#5
pup— driving Pup browser windows (#3): navigate, screenshot, eval, reloadadom-workspace-control— adding/managing Hydrogen webview tabs (#1)- hydrogen-runtime-mode — none of this changes across workspace runtimes
---
name: hydrogen-open-url
description: >
The decision guide for "open a URL / open a website" inside Hydrogen.
When the user says "open ti.com" / "pull up the datasheet page" / "show me
that site", Hydrogen has SIX distinct ways to do it — a Hydrogen webview tab, an Hydrogen
browser window, Pup (AI-drivable Chrome), a native desktop browser profile,
the Browser Picker chooser, or headless curl/fetch — each with different
trade-offs. READ THIS to pick the right one and to explain the options back to
the user instead of silently guessing. For the interception/plumbing behind the
picker see hydrogen-browser-picker; to drive Pup see pup; for webview tabs see
adom-workspace-control. Trigger words — open url, open website, open the site,
open ti.com, open a link, pull up the page, show me the website, view this url,
open in browser, which browser, how do I open, open the datasheet page, open in
a tab, open in pup, open in chrome, headless fetch, ways to open a url, open
link options, wv, open in wv, open as wv, webview tab, wv tab.
---
# Hydrogen — Opening a URL (your options)
When a user says **"open the ti.com website"** (or any URL), Hydrogen has several paths
and a Browser Picker — but **don't hand the user the picker to decide.** Pick the
best destination *for them* by use-case and **open it directly**, then offer the
alternatives in one line. The right path depends on what they're doing — look at
it, have you drive it, keep it as a tab, or just read it. See **"Decide for the
user — DON'T hand them the picker"** below for the rule.
## The six ways
| # | Option | Best when… | What the user sees | AI drives it? |
|---|--------|-----------|--------------------|---------------|
| 1 | **Hydrogen webview tab** (aka **wv**) | the user wants the site *inside* Hydrogen, next to their work, and to keep it around | a panel/tab in the Hydrogen workspace | partly (reload/route) |
| 2 | **Hydrogen Browser Window** | a quick popout window owned by Hydrogen, not a full browser | a standalone Hydrogen-owned window | no |
| 3 | **Pup (Puppeteer Chrome)** | **you** need to act on the page — screenshot, click, scrape, fill a form, verify | a real Chrome window on their desktop | **yes, fully** |
| 4 | **Native desktop browser** | real logins/sessions, downloads, "just open it for me", auth flows | their own Chrome/Edge profile | no |
| 5 | **Browser Picker** | you're not sure, or it's an auth/OAuth link — let the user choose (5s auto-default) | a chooser dialog | n/a (routes to one of the above) |
| 6 | **curl / fetch (headless)** | you only need the *content*, not to show anything (read a datasheet, scrape JSON) | nothing — runs in the workspace | **yes** |
## "wv" = webview — the shortcut (spread it like `pup`)
**`wv` is the short alias for "webview"** — recognize it **everywhere** a user might say
"webview" (`open it in wv`, `wv tab`, `shot the wv`, `wv mode`). Treat `wv` and `webview` as
identical.
**Help it catch on:** the *first* time in a session a user types the long form **"webview"**,
open it as normal **and** add a one-line nudge — *"(btw you can just say **wv** — fewer
keystrokes)."* Say it **once**, not every time (don't nag). This is exactly how
**puppeteer → `pup`** became universal among Adom folks; `webview → wv` is the same play.
(If the user already says `wv`, they got the memo — skip the nudge.)
## How you invoke each
All of these run from inside the Hydrogen workspace. The control API base URL is the live
value in `~/.adom/hydrogen-control-url` — `http://127.0.0.1:<dynamic>` (the workspace
shares loopback with the host; the port is dynamic per launch).
Read it with `BASE="$(cat ~/.adom/hydrogen-control-url)"` then hit `"$BASE/<endpoint>"`.
**1. Webview tab (wv)** — add a web-view tab pointed at the URL (`adom-workspace-control`,
or `adom-cli hydrogen webview open-or-refresh --name <X> --url <url> --panel-id <id>`). Good
for "keep this open while we work." ⚠️ **`open-or-refresh` needs `--panel-id` to CREATE a new
tab** — without it you get *"Tab 'X' not found and --panel-id not provided"* (verified live
2026-06-14; get a panel id from `adom-cli hydrogen workspace get`). Re-running with the same
`--name` once it exists just navigates/refreshes (no panel-id needed). Same `adom-cli` on
web-Hydrogen and Hydrogen — the consistent surface.
**2 / 4 / 5. Through the Browser Picker** — the single unifying entry point. POST
the URL and Hydrogen routes it (auto-picking a sensible default after a 5-second
countdown, or showing the chooser):
```bash
BASE="$(cat ~/.adom/hydrogen-control-url)" # http://127.0.0.1:<dynamic>
# Auto-route (picker picks the best default in 5s — hands-free)
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"url":"https://www.ti.com"}' \
"$BASE/open-url"
# Force the chooser dialog (no auto-timer — make the user pick)
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"url":"https://www.ti.com","force":true}' \
"$BASE/open-url"
# Route through the picker with the FRESH-WINDOW toggle pre-checked (the picked
# native browser opens in a new --new-window that auto-foregrounds — use for
# auth/OAuth so the consent page pops to the front by itself):
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"url":"https://claude.ai/","fresh":true,"force":true}' \
"$BASE/open-url"
# …or bypass the picker and open directly+fresh in a specific browser:
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"url":"https://claude.ai/","browser":"edge","profileDir":"Default","fresh":true}' \
"$BASE/open-in-profile"
```
> ⚠️ **`/open-url` often replies `"Hydrogen timed out after 5s"` even when it SUCCEEDED**
> (verified live 2026-06-14: `{"url":"https://www.google.com"}` reported the timeout, but the
> page opened in Edge). **Don't treat that as failure** — confirm with
> `GET "$BASE/browser-picker/last-open"` → `{destination, url, fresh, ts}`. `fresh:false` =
> routed to a remembered/default destination (no picker shown — e.g. `browser:edge:Default`);
> `fresh:true` = the picker was shown. (So if every domain has a remembered default, opens are
> silent — the picker only pops for un-remembered domains.)
The picker's auto-default heuristic: `*.claude.ai`/`*.claude.com` and Adom
`/auth/intent` → the user's work browser profile; unknown/right-click/iframe →
Pup; otherwise the user's last choice for that domain. See `hydrogen-browser-picker`.
**Fresh window (`"fresh":true`)** — the native-browser path (#4) can open the URL
either as a tab in an already-running browser (default) or as a **brand-new window/
process** (`--new-window`). A freshly-launched window **auto-foregrounds**;
a tab does not. So for **auth flows the user must complete** (Claude/Adom sign-in),
prefer `fresh:true` — the consent page comes to the front by itself, no manual focus.
The Browser Picker defaults the "Open in a fresh window" toggle ON for auth URLs.
On `/open-url`, `fresh` pre-seeds that toggle (the picker still shows; add `direct:true`
to skip it); `/open-in-profile` opens fresh directly. See `hydrogen-browser-picker`.
**3. Pup** — open and then drive it with `adom-bridge-cli browser_*` verbs
(`browser_open_window`, `browser_navigate`, `browser_screenshot`, `browser_eval`,
`browser_reload`, …). Either open the URL directly via Pup, or let the picker
route to Pup. See the `pup` skill for the full verb set.
```bash
adom-bridge-cli browser_eval '{"sessionId":"default","js":"document.title"}'
```
**6. Headless content** — if you only need to *read* the page, skip the browser
entirely:
```bash
curl -sL https://www.ti.com/... # or fetch from your own code
```
## Decide for the user — DON'T hand them the picker
**Default behavior: pick the destination by use-case and open it DIRECTLY (bypass
the picker), then give a one-line heads-up + easy undo.** Do NOT fire a plain
`POST /open-url {url}` and let the picker's generic 5-second auto-default decide —
that default is luck-of-the-draw and often wrong for the use-case (a vendor-login
site could land in Pup where the user has no login). Users don't want to make this
choice; make the smart one for them. (Mechanics: `/open-in-profile` opens a
specific native browser+profile directly; `/open-url {direct:true}` bypasses the
picker; Pup and webview-tab are direct calls. Reserve the picker only as below.)
| Use case | Open it in | How (bypass the picker) |
|---|---|---|
| **Login-likely site** — vendor/account/portal/cart: TI, Mouser, DigiKey, any "my…"/sign-in | the user's **native browser + WORK profile** (their saved login/cookies live there) | `GET /browser-profiles` → find the work profile (non-gmail) → `POST /open-in-profile {url, browser, profileDir, fresh:true}` |
| **Building/testing their own app**, or you need to drive/screenshot/scrape the page | **Pup** (AI-drivable) | open via Pup (`browser_*`) / route `/open-url {url, direct:true}` to Pup |
| **Glance at content alongside their work** | **Hydrogen webview tab** | `adom-workspace-control` add web-view tab |
| **Genuinely ambiguous, OR an OAuth/sign-in the user must complete themselves** | let them choose | `POST /open-url {url, force:true}` — the one time the picker is right |
Then say it in one line, with the undo: *"Opened TI in your Chrome work profile
(where your TI login lives) — say the word for a tab here, Pup, or a different
profile."* Decide, act, offer alternatives — don't ask first.
Example — "open the texas instruments website" (login-likely → native work profile):
```bash
BASE="$(cat ~/.adom/hydrogen-control-url)"
curl -s "$BASE/browser-profiles" # pick the work profile (non-gmail email)
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"url":"https://www.ti.com","browser":"chrome","profileDir":"<work profileDir>"}' \
"$BASE/open-in-profile"
```
## Govern routing policy — the picker is now a true FALLBACK (Hydrogen prefs API)
The picker's per-domain memory is a first-class API (Hydrogen app behavior), so **the AI OWNS URL
routing** — the picker only pops for a domain with **no stored policy AND no direct call**.
Use this to set policy the user would otherwise click through the Manager for ("always open
DigiKey in my work profile", "stop auto-opening X in Edge").
```bash
BASE="$(cat ~/.adom/hydrogen-control-url)"
# READ the policy map
curl -s "$BASE/browser-picker/prefs"
# → {ok, prefs:{domains:{"<host>":{destination,label}, …}}}
# SET / override one domain
curl -s -X PUT "$BASE/browser-picker/prefs" -H 'Content-Type: application/json' \
-d '{"domain":"digikey.com","destination":"browser:edge:Default","label":"Edge — Default"}'
# FORGET one domain (e.g. "stop auto-opening X in Edge")
curl -s -X DELETE "$BASE/browser-picker/prefs/digikey.com"
# CLEAR all
curl -s -X DELETE "$BASE/browser-picker/prefs"
```
- **Stored value = `{destination, label}`** — NOT `profileDir`/`fresh`.
- **`destination` is an ID:**
- **internal:** `hydrogen-tab` (a webview/wv tab) · `webview-window` · `pup-window`
- **native:** `browser:<browser>:<dir>` — e.g. `browser:edge:Default`, `browser:chrome:Profile 1`. **The profile dir is encoded in the ID** (no separate field).
- **Discover valid native IDs** via `GET $BASE/browser-profiles` (maps each detected profile → its `browser`+`dir`); the 3 internal IDs are fixed above.
- **`fresh` is NOT stored in prefs** — it's a per-OPEN flag (`/open-url {fresh:…}` / `/open-in-profile {fresh:…}`). Don't try to persist it here.
- **Writes hit the live Manager UI immediately** (the backend writes `hydrogen-url-routing-prefs`
localStorage + dispatches `hydrogen-url-routing-prefs-changed`; an open Browser Picker Manager
re-reads at once, and re-reads on open anyway).
**Net:** for a one-off open, *decide and call the direct endpoint* (`/open-in-profile`,
`/open-url {direct:true}`, or a wv/pup call). For a *standing* preference, `PUT` the domain's
policy so even user-initiated link clicks route there silently. The picker is now only a
fallback for the genuinely-undecided.
## Related skills
- [hydrogen-browser-picker](../hydrogen-browser-picker/SKILL.md) — the interception layers + picker dialog behind #2/#4/#5
- `pup` — driving Pup browser windows (#3): navigate, screenshot, eval, reload
- `adom-workspace-control` — adding/managing Hydrogen webview tabs (#1)
- [hydrogen-runtime-mode](../hydrogen-runtime-mode/SKILL.md) — none of this changes across workspace runtimes