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.
e1a9528
18d ago
Open source: code and contributing
pup is open source under the MIT license. Its complete source is in this page's Files tab, and changes come back as pull requests on this page. This guide shows how the code is organized, how to build and test it, how to add a feature, and how to send it back.
How the code is organized
pup is one Rust workspace in rust/, built into a single Windows program. Twelve crates, each with one job:
| crate | lines | job |
|---|---|---|
bridge |
210 | The program's entry point: start the HTTP server on 127.0.0.1, route commands, run the start-up tasks. |
verbs |
8,100 | Every command (pup_*). Each is a function of (context, caller, arguments) that returns a reply. |
browser |
970 | Which browser to drive, fetching pup's browser build, launch arguments, and staging the extensions. |
session |
160 | The window and tab model and the small file kept per window for recovery. |
identity |
660 | Taskbar identity: names, the thread tile drawing, favicon badges, jump list contents. No OS calls. |
vault |
370 | Logins and payment cards: matching, validation, the encrypted store's format. |
dashboard |
450 | Every page pup serves that is not a command: /status, /health, the dashboard and its assets. |
cdp |
360 | The client for the older debugging lane. |
core |
390 | Shared types: settings, the reply envelope, caller identity, logging. |
host |
150 | The operating-system interface, as traits and nothing else. |
host-win |
570 | The Windows implementation of host, and the only crate allowed to call Windows directly. |
host-mac |
50 | The macOS implementation, in progress. |
The rule that keeps the port possible: every Windows call lives in host-win behind a trait in host. tools/check-borders.sh fails the build if a Windows or macOS API name appears anywhere else. The Mac port is one crate: implement host-mac.
The browser extensions that pup loads into its windows live in src/extension*/ as plain JavaScript and are built into the program, along with the dashboard (rust/dashboard/assets/) and the command catalog.
Build and test
You need Rust with the Windows target. From Linux or WSL, install mingw-w64 for the linker; on Windows, use the stable toolchain.
rustup target add x86_64-pc-windows-gnu
python3 tools/gen-assets.py # embed extensions, dashboard and the command catalog
tools/check-borders.sh # Windows calls only in host-win
cd rust && cargo test --workspace # unit tests, on any OS
cargo build --release --target x86_64-pc-windows-gnu
# -> rust/target/x86_64-pc-windows-gnu/release/adom-pup-bridge.exe
Add a feature
Most features are a new command or a change to one. To add pup_something:
- Write the handler in the fitting file under
rust/verbs/src/(tabs.rs,input.rs,extras.rs, ...): a function of(ctx, caller, args)that returnsok(json!({...}))orerr(code, message, hint). - Route it in
dispatchinrust/verbs/src/lib.rsand add its name toPHASE1_VERBS. - Describe it for AIs: add an entry to
_STUBSintools/gen-assets.pywith a summary, inputs, an example and a hint. The build stops if a routed command has no description, and the same list becomes bothpup_describeand the manifest Adom Bridge reads, so they cannot drift apart. - If it needs the operating system, add a method to a trait in
host, implement it inhost-win, and givehost-maca stub. - Add a test, and run the build and tests above.
Good first changes: a clearer hint on a command that confused your AI, a new jump list task, a Settings row with a better explanation, a faster screenshot path. Open the folder in Claude Code and describe the change you want; the code's comments record why things are the way they are, often with the date and the problem that caused them.
Send it back
Open a pull request on this page with the files you changed:
adom-wiki pr create adom/pup-bridge --title "Add pup_something" --body-file why.md \
--files rust/verbs/src/extras.rs rust/verbs/src/lib.rs tools/gen-assets.py
Or start a thread in the Issues tab first if you want to talk the idea through.
What happens to your change
Adom maintainers review it, then build, sign and test every release before anyone gets it:
- Foreground proof. A cold start, navigations and new windows while the screen is sampled twice a second; it fails if a pup window is ever on top.
- Smoke test. Every everyday command, end to end, through Adom Bridge on a real desktop.
- Parity. 56 recorded reply shapes replayed and compared.
- Jump list test. Every jump list task fired exactly as Windows fires it, with its effect checked in the window.
A release goes first to the insiders tier on Adom's own desktops, and only reaches everyone when a person approves it in their own words.
# Open source: code and contributing
pup is open source under the MIT license. Its complete source is in this page's **Files** tab, and changes come back as pull requests on this page. This guide shows how the code is organized, how to build and test it, how to add a feature, and how to send it back.
## How the code is organized
pup is one Rust workspace in `rust/`, built into a single Windows program. Twelve crates, each with one job:
| crate | lines | job |
|---|---|---|
| `bridge` | 210 | The program's entry point: start the HTTP server on 127.0.0.1, route commands, run the start-up tasks. |
| `verbs` | 8,100 | Every command (`pup_*`). Each is a function of (context, caller, arguments) that returns a reply. |
| `browser` | 970 | Which browser to drive, fetching pup's browser build, launch arguments, and staging the extensions. |
| `session` | 160 | The window and tab model and the small file kept per window for recovery. |
| `identity` | 660 | Taskbar identity: names, the thread tile drawing, favicon badges, jump list contents. No OS calls. |
| `vault` | 370 | Logins and payment cards: matching, validation, the encrypted store's format. |
| `dashboard` | 450 | Every page pup serves that is not a command: `/status`, `/health`, the dashboard and its assets. |
| `cdp` | 360 | The client for the older debugging lane. |
| `core` | 390 | Shared types: settings, the reply envelope, caller identity, logging. |
| `host` | 150 | The operating-system interface, as traits and nothing else. |
| `host-win` | 570 | The Windows implementation of `host`, and the only crate allowed to call Windows directly. |
| `host-mac` | 50 | The macOS implementation, in progress. |
The rule that keeps the port possible: every Windows call lives in `host-win` behind a trait in `host`. `tools/check-borders.sh` fails the build if a Windows or macOS API name appears anywhere else. The Mac port is one crate: implement `host-mac`.
The browser extensions that pup loads into its windows live in `src/extension*/` as plain JavaScript and are built into the program, along with the dashboard (`rust/dashboard/assets/`) and the command catalog.
## Build and test
You need Rust with the Windows target. From Linux or WSL, install mingw-w64 for the linker; on Windows, use the stable toolchain.
```bash
rustup target add x86_64-pc-windows-gnu
python3 tools/gen-assets.py # embed extensions, dashboard and the command catalog
tools/check-borders.sh # Windows calls only in host-win
cd rust && cargo test --workspace # unit tests, on any OS
cargo build --release --target x86_64-pc-windows-gnu
# -> rust/target/x86_64-pc-windows-gnu/release/adom-pup-bridge.exe
```
## Add a feature
Most features are a new command or a change to one. To add `pup_something`:
1. Write the handler in the fitting file under `rust/verbs/src/` (`tabs.rs`, `input.rs`, `extras.rs`, ...): a function of `(ctx, caller, args)` that returns `ok(json!({...}))` or `err(code, message, hint)`.
2. Route it in `dispatch` in `rust/verbs/src/lib.rs` and add its name to `PHASE1_VERBS`.
3. Describe it for AIs: add an entry to `_STUBS` in `tools/gen-assets.py` with a summary, inputs, an example and a hint. The build stops if a routed command has no description, and the same list becomes both `pup_describe` and the manifest Adom Bridge reads, so they cannot drift apart.
4. If it needs the operating system, add a method to a trait in `host`, implement it in `host-win`, and give `host-mac` a stub.
5. Add a test, and run the build and tests above.
Good first changes: a clearer hint on a command that confused your AI, a new jump list task, a Settings row with a better explanation, a faster screenshot path. Open the folder in Claude Code and describe the change you want; the code's comments record why things are the way they are, often with the date and the problem that caused them.
## Send it back
Open a pull request on this page with the files you changed:
```bash
adom-wiki pr create adom/pup-bridge --title "Add pup_something" --body-file why.md \
--files rust/verbs/src/extras.rs rust/verbs/src/lib.rs tools/gen-assets.py
```
Or start a thread in the **Issues** tab first if you want to talk the idea through.
## What happens to your change
Adom maintainers review it, then build, sign and test every release before anyone gets it:
- **Foreground proof.** A cold start, navigations and new windows while the screen is sampled twice a second; it fails if a pup window is ever on top.
- **Smoke test.** Every everyday command, end to end, through Adom Bridge on a real desktop.
- **Parity.** 56 recorded reply shapes replayed and compared.
- **Jump list test.** Every jump list task fired exactly as Windows fires it, with its effect checked in the window.
A release goes first to the insiders tier on Adom's own desktops, and only reaches everyone when a person approves it in their own words.