app
Pup - the AI's own browser
Public Made by Adomby adom
pup gives your AI a real browser on your desktop that it drives completely, in the background, signed in as you: windows that never jump in front of your work, one shared profile that learns your logins, and every window labeled on the taskbar with its AI thread's name.
← Commit history
Update 5 file(s)
4 files changed
+242
dev-skills/pup-auto-mode/SKILL.mdadded+103@@ -0,0 +1,103 @@+---+name: pup-auto-mode+description: "THE operating reality: Adom users run their AI in Claude Code AUTO mode (Hydrogen places them there; Anthropic removed the bypassPermissions menu option). pup must be a great doppelganger INSIDE Auto mode, never assume bypass. The design rule: expose rich structured verbs so the safety check passes, make the genuinely-risky moments clean human-approval pauses. Read before adding any verb or any flow that touches credentials, the OS, or destructive actions."+---++# pup under Auto mode — design for the safety check, don't fight it++## The reality (John, 2026-08-13)++Adom's own product (Hydrogen / ah) places every user's local AI in Claude Code **Auto mode**,+and a recent Claude Code version **removed `bypassPermissions` from the mode menu** entirely.+Auto mode: *"Claude approves actions that pass a safety check and pauses for anything risky."*++**So the design target is Auto mode, always.** Never build a pup flow that only works if the+user is in bypassPermissions — most users can't be, and the ones who could are the exception.+A flow that needs the AI to run something the safety check rejects is a broken flow for the+fleet, no matter how well it works in a dev bypass session.++## The one empirical law that makes this work++**Structured, purpose-built verbs PASS the safety check. Raw `pup_eval` carrying sensitive+content gets PAUSED.** Proven live on a real payroll login:++- `pup_login {sessionId, username, password, submit, submitReason}` → **allowed.** The+ credential is a parameter to a named login verb; the classifier sees a legitimate,+ purpose-scoped operation.+- `pup_eval` injecting the *same* credential as hand-rolled JavaScript → **blocked.** Raw code+ execution carrying a secret reads as opaque and risky.++Everything follows from this:++1. **Expose a rich, high-level verb for every sensitive operation** so the AI never has to+ hand-roll `pup_eval` for it. The verbs are the safe interface Auto mode trusts. If a common+ task can only be done today via `pup_eval` (filling a weird field, clicking a specific+ control, reading a code), that is a MISSING VERB — add it, named and scoped, so it passes.+2. **Name and scope verbs so intent is legible.** `pup_login`, `pup_fill_field`,+ `pup_click`, `pup_read_2fa` beat a generic eval. The classifier reasons about what a call+ is *for*.+3. **Keep secrets out of raw commands.** Prefer the vault (pup fills from the keychain, no+ secret in any command) over passing a password inline. First-time capture that must carry a+ secret goes through `pup_login`/`credential_set`, never `pup_eval`.++## The fleet-level unblock: ship an autoMode.allow allowlist++Auto mode's classifier honors a per-user allowlist (`permissions.autoMode.allow` in+settings.json). **Adom setups that place users in Auto (Hydrogen) should ALSO ship allow rules+that whitelist the Adom tooling**, so all the *benign* pup driving flows with zero friction+while the safety net stays on genuinely-dangerous unrelated commands. Recommended entries+(Hydrogen provisioning / the Adom Bridge installer should write these into user settings):++```json+"permissions": {+ "autoMode": {+ "allow": [+ "$defaults",+ "adom-bridge-cli and pup_* verbs are the user's own sandboxed browser automation (open/navigate/screenshot/click/list windows) — allow",+ "adom-wiki publishing to the user's own wiki — allow"+ ]+ }+}+```++This is the scalable answer, NOT teaching each user to disable Auto mode (they structurally+can't from the menu, and an AI cannot disable its own oversight — correctly). The AI cannot+write this itself (editing the classifier's own config is blocked, by design); it is a+provisioning-time config Hydrogen/the installer ships, or the user pastes once.++## The genuinely-risky moments: clean human pauses, not fights++Some actions SHOULD pause even under a perfect allowlist: typing a credential into a new site,+a destructive kill, a registry write. Auto mode pausing on these is correct and it **aligns+with the doppelganger model** — the human oversees the consequential moment. So design for the+pause instead of trying to route around it:++- Make the pause point ATOMIC and LEGIBLE: one verb, a clear `submitReason`, the exact domain+ named (so the human confirms it is the right site — anti-phishing).+- Return a `_hint` to the calling AI thread telling it *how to present the approval* to the+ human and what the safe next step is (see the `_hint` doctrine in [[pup-doppelganger]]).+- Lean on the vault so the pause happens ONCE per site (first login), then autofill is silent+ forever after — the human approves the introduction, not every visit.++## AI hints: teach the calling thread the Auto-safe path++pup responses should actively coach the driving AI toward the Auto-mode-safe path, because a+generic AI will reach for `pup_eval` and get paused. On a login/credential context, hint:+"use `pup_login` (a structured verb the safety check allows), not `pup_eval` with the password."+On a missing capability, hint the verb to use. This is how pup stays drivable for ANY AI thread+under Auto mode, not just one that already knows the tricks.++## Per-website login recipes (the growing corpus)++Real logins differ wildly (email-first, account pickers, React-masked fields, 2FA, anti-bot).+The repo's `login-recipes/` holds one recipe per site documenting the Auto-mode-aware sequence:+which steps auto-approve, which pause for the human, which fields need real keystrokes. These+publish to the wiki page's Files tab so any Adom user can read and CONTRIBUTE the recipe for a+site they hit. The goal: thousands of site recipes so pup can truly drive logins for everyone.+See `login-recipes/README.md`.++## The bottom line++Do not ask the user to weaken their safety mode. Make pup so well-versed in structured verbs,+vault-backed fills, clean pause points, and AI hints that a doppelganger works *beautifully*+inside Auto mode's floor — that is the product.
dev-skills/pup-doppelganger/SKILL.mdadded+58@@ -0,0 +1,58 @@+---+name: pup-doppelganger+description: "THE mission of pup, and the design rule that flows from it. Normal browsers are built for humans; pup is a browser built for the AI — the human's doppelganger on the web. Every design call defers to this: anything a human browser shows a HUMAN to click, pup handles SILENTLY for the AI. Read before adding any user-facing prompt, dialog, foreground, or gesture-dependent behavior."+---++# pup is the AI's browser — the human's doppelganger on the web++## The mission (John, 2026-08-13)++> "Normal browsers are for humans. pup is for the AI to drive a browser. We're making a+> new browser for the AI as a **doppelganger for the human**."++A normal browser (Chrome, Edge, Safari) is a product for a *person*: it asks the person+questions, pops dialogs for the person to click, shows the person banners, pulls its window+in front of the person. pup is not that. **pup is a browser built for the AI to drive on the+human's behalf** — a full, real browser the AI operates as the human's stand-in. The AI acts+*as* the human (it carries the human's shared `adom-you` identity, accumulates the human's+logins), but it is *not* the human sitting at the screen, so it never needs the human-facing+machinery a normal browser is made of.++## The design rule this dictates++**Anything a normal browser would show a HUMAN to read, click, confirm, or drag, pup handles+SILENTLY for the AI instead.** If a design choice puts a human-facing prompt, dialog,+foreground steal, gesture requirement, or desktop-clutter footprint in the path, it is wrong+for pup by definition — find the silent, background, AI-driven equivalent.++Concretely, every one of these decisions is the same principle applied:++| A normal (human) browser… | pup (the AI's doppelganger)… |+|---|---|+| shows a "Save password?" dialog to click | captures the login silently into the keychain vault (v2.0.121–122) |+| makes you pick a saved login from a dropdown (needs a real gesture) | fills it directly over CDP — background, no gesture, no foreground |+| pulls its window forward when it wants attention | stays in the background; signals with a taskbar flash, never a focus steal |+| pops a Windows Firewall / UAC prompt for mDNS/Cast | disables Cast so it never binds the network, no prompt (v2.0.120) |+| requires clicking "Developer mode" to load an extension | flips it on itself via the developerPrivate API (v2.0.114) |+| leaves a Start Menu shortcut / "managed by your org" banner | registry-only identity, no Start Menu footprint (v2.0.118) |+| rewrites tab titles / shows its own chrome over the page | leaves the page untouched (see [[pup-page-integrity]]) |++When a new question comes up ("should pup show X?"), the answer is almost always: **a human+browser shows a human X; the AI's doppelganger browser doesn't need to be shown — it already+knows, so do X silently.**++## The one boundary: doppelganger, not impostor++Acting *as* the human is the point (shared identity, real logins), but pup is still a+*sandbox the AI owns*, never the human's real signed-in browser — that is `nb`/`nbe`'s job.+And "handle it silently for the AI" never means "hide it from the human": the human can always+see what pup did (the dashboard, the taskbar identity, the caption, the vault listing). Silent+toward the *browser UI*, transparent toward the *person*.++## Why this is written down++pup accretes features fast, and each one faces the same fork: do the human-browser thing+(prompt/dialog/foreground) or the doppelganger thing (silent/background/AI-driven). Left+un-stated, the easy path is to inherit whatever Chrome does for humans. This mission is the+tie-breaker: **build for the AI driver, not the human reader.** The user-facing version of+this lives at the top of the wiki README so users understand what pup is *for*.
login-recipes/README.mdadded+56@@ -0,0 +1,56 @@+# pup login recipes — how the AI signs you into any site++**pup is your AI's doppelganger on the web.** For most sites, pup logs you in automatically:+it fills your saved credential from the OS-keychain vault and submits, no dialog, no fuss. But+real login flows differ wildly, email-first steps, account pickers, custom-masked password+fields, 2FA, anti-bot defenses, and a generic approach fails on the tricky ones.++This folder is a **growing corpus of per-site login recipes**: one file per domain documenting+the exact sequence pup should drive to sign you in, and which steps need *you* (the human) for a+moment. Every Adom user's AI reads these, and **you can contribute the recipe for any site you+hit** so the next person's AI just works.++The goal is thousands of recipes so pup can truly log into anything, for all of us.++## The operating context: Auto mode++Adom users run their AI in Claude Code **Auto mode** (Hydrogen puts you there). Auto approves+safe actions and pauses on risky ones. So every recipe is written Auto-mode-aware:++- **Prefer structured pup verbs** (`pup_login`, `pup_type`, `pup_click`) over raw `pup_eval`,+ the safety check allows the former and pauses the latter. See the `pup-auto-mode` dev skill.+- **Mark which steps auto-approve vs. pause for the human.** Typing a *new* credential pauses+ (correct, you confirm the site); everything after the vault knows it flows silently.+- **Always on the durable `adom-you` profile**, so the session + 2FA-remember persist and you+ rarely re-authenticate. Never log in on an isolated throwaway.++## Recipe file format++Name the file by registrable domain: `login-recipes/<domain>.md` (e.g. `gusto.com.md`). Use:++```markdown+# <site name> (<domain>)++- **Login entry URL:** the URL that lands on the sign-in flow+- **Flow type:** single-page | email-first | account-picker | SSO-redirect | other+- **2FA:** none | TOTP authenticator | SMS | push (and whether "remember device" is offered)+- **Anti-automation notes:** custom-masked fields, isTrusted requirements, etc.++## Steps+1. …each step: the action, the exact selector if non-obvious, the pup verb to use, and+ whether it AUTO-APPROVES or PAUSES for the human.++## Field selectors+- username: `<selector>` (type: text/email)+- password: `<selector>` (note if NOT type=password)+- submit: `<selector or button text>`++## Gotchas+- anything that bit someone: React-controlled fields, reloads that clear values, redirects, etc.+```++## Contributing (any Adom user)++Hit a site whose login your AI fumbled? Tell your AI "add a pup login recipe for <site>" or open+a PR on the pup wiki page (Files tab → `login-recipes/`). Include the flow type, the field+selectors, and any gotcha. Keep secrets OUT, recipes describe the *flow*, never credentials.
login-recipes/gusto.com.mdadded+25@@ -0,0 +1,25 @@+# Gusto (gusto.com) — payroll++- **Login entry URL:** `https://app.gusto.com/login` (redirects to `login.gusto.com`, a Keycloak IdP)+- **Flow type:** email-first → account-picker → password → 2FA+- **2FA:** TOTP authenticator (6-digit code); "Remember device for 30 days" checkbox offered — check it on adom-you so future logins skip 2FA+- **Anti-automation notes:** the password field is a **React-controlled masked input** and is `type="text"` (not `type=password`), with `autocomplete="current-password"`. Setting `.value` does NOT register with React's state — you MUST use real keystrokes (`pup_type`) and then read the value back to confirm it landed before submitting.++## Steps+1. Open on **adom-you** (never isolated) — `pup_open_window {url:"https://app.gusto.com/login"}`. AUTO-APPROVES. If adom-you already has a Gusto session you land signed in; done.+2. **Email step** — fill the email field (benign, AI may enter it) and click **Continue**. `pup_type` or a fill; AUTO-APPROVES (username is not a secret).+3. **Account picker** — Gusto often shows "Select your email address" with your account as a row. Click the row for your email (a `<button>`). AUTO-APPROVES.+4. **Password step** ("Enter your password") — the field is `#password`, `type=text`, masked by React. Use `pup_login {username, password, submit:true, submitReason:"…confirm login.gusto.com is the intended site…"}` (structured verb → passes the safety check) OR `pup_type {selector:"#password", text, clear:true}` then verify `#password` value length, then click Continue. This is the step that **PAUSES for the human under Auto mode** (typing a credential) — surface it for one-tap approval, or the human types it. Real keystrokes are mandatory; `.value`-set silently fails.+5. **2FA** — "Enter the 6-digit code in your authenticator app." pup CANNOT generate this; the **human enters the 6-digit code** from their authenticator (PAUSES). Check "Remember device" so it is a one-time step on adom-you.+6. Redirects to `app.gusto.com/…` dashboard = signed in.++## Field selectors+- username/email: `input[type=email], input[name=username]` (type: email)+- password: `#password` — **NOTE: `type="text"`, `autocomplete="current-password"`, not `type=password`**+- submit: button with text "Continue"++## Gotchas+- `type=password` selectors miss the password field entirely (it is `type=text`). pup ≥2.0.123 also matches `autocomplete=current-password` / `name=password`.+- Setting `.value` on the password field passes React's display but submits EMPTY ("Password is required"). Use real keystrokes and verify the value landed.+- On the email step, the value can reset on reload — re-enter and submit via the form, then poll for the password field.+- It is a cross-origin SSO redirect (`login.gusto.com` → `app.gusto.com`); capture on password blur (pup ≥2.0.121) so the credential is vaulted before the redirect.