README.md
August 28, 2026 · View on GitHub
A Secure, Auditable Browser for AI Agents
h5i (pronounced high-five) is a lightweight browser for policy-controlled, auditable agent access to the web. Every session records allowed and denied network requests in a reviewable receipt. Run it directly, sandbox only the browser, or contain the agent’s entire workflow in one disposable environment.
|
Pure Rust No Chromium or V8 |
~80% less peak memory In our benchmarks |
~5× faster reads In our benchmarks |
Sandboxed & auditable Browser-only or full workflow |
Pure Rust. No Chromium. No V8.
h5i browser open https://example.com
h5i browser snapshot # the page as a model should read it
h5i browser click @e3
h5i browser requests # what it asked for, and what was refused
h5i browser audit # the whole session: verbs, fetches, handovers, ending
h5i browser close
h5i browser read https://example.com # or: one page, no session
1. Install
curl -fsSL https://h5i.dev/install.sh | sh
# curl -fsSL https://raw.githubusercontent.com/h5i-dev/h5i/main/install.sh | sh # if you would rather not add a domain to the chain:
# cargo install --path . # build from source
The agent-facing interface is a skill, and the binary carries it:
npx skills add h5i-dev/h5i # if you do not have the binary yet
# h5i skill install # writes it where your runtime looks
# h5i skill show policy # or just read a page
Two optional runtimes add stronger sandbox tiers: rootless
Podman provides container, while
microsandbox (msb) provides microvm on a host
with hardware virtualization (/dev/kvm on Linux or Apple Silicon on macOS).
2. Use it
2.1. A headless browser
A session is the whole agent-facing surface: one page state, one cookie jar, one request log, one policy:
h5i browser open https://docs.rs/ --allow docs.rs
h5i browser snapshot # outline, with @ref handles
h5i browser snapshot --delta # only what changed since the last read
h5i browser click @e3
h5i browser type @e5 "serde"
h5i browser extract '{"titles": ["h2"]}' # structured, by selector
h5i browser markdown # the page a reader would read
h5i browser login # hand the page to the human at the viewer
h5i browser close
Running several at once is what names are for:
h5i browser open https://example.com/login --session auth --new
h5i browser open https://example.com/ --session public --new
h5i browser snapshot --session auth
Read the record:
h5i browser requests # every request, including the refusals
h5i browser audit # the whole session: verbs, fetches, handovers, ending
h5i browser status # placement, policy digest, who saw the network
h5i browser list # every session on this machine, and which is default
Watch the browser it drives:
h5i box view <name> # the box's page, through a loopback-only forward
h5i box view <name> --term # draw it in this terminal instead (needs kitty)
2.2. The configurable sandbox
While h5i runs in a light-weight sandbox by default, we can further specify
fine-grained setting in .h5i/env.toml.
[profile.reading]
isolation = "supervised" # workspace | process | supervised | container | microvm
[profile.reading.net]
mode = "host"
egress = ["docs.rs", "static.crates.io"] # everything else is refused
[profile.reading.fs]
read = ["/usr", "/etc"] # replaces the defaults, so grant what it needs
write = []
[profile.reading.resources]
mem = "512M"
procs = 64
secrets = ["ACME_PASS"] # the only $H5I_SECRET_* it may substitute
Give it to a browser session through a box:
h5i box --profile reading --name docs
h5i browser open https://docs.rs/ --in docs
2.3. A sandbox holds more than a browser
The top rung of that ladder is a whole environment. It can hold the code, the toolchain, the dev server and the agent itself, which is what you want when the agent is building the app it is about to browse.
h5i box create alpha --profile agent-claude # a sandboxed git worktree
h5i box shell alpha # an interactive confined session
h5i box run alpha -- cargo test # one command; the exit code passes through
h5i box propose alpha # freeze the work into a reviewable snapshot
h5i box apply alpha # merge it onto the parent branch
h5i box export alpha # patch, report and receipts you can read
h5i box rm alpha # throw it away
h5i box share alpha --port 3000 # end-to-end encrypted P2P sharing
h5i box share alpha --port 3000 --tunnel # or a browser-ready demo link
h5i join <ticket> # what the recipient runs
h5i forum create "fix the auth refresh race" --ceiling code-review # create a message forum for multu-agent team
h5i forum attach claude-box --as claude-worker --role worker
h5i forum status
h5i ui # watch the whole fleet in a browser
3. What confinement means here
h5i box probe reports the tiers your host can run. h5i never silently
downgrades: an unsatisfiable request fails closed.
A browser session uses process by default, without a box. The rows below it
are what --in <box> reaches for, and the difference that matters to a session
is the one thing process cannot do: enforce which addresses may be reached, at
a boundary outside the engine.
| Tier | What enforces it |
|---|---|
workspace | a separate git worktree, no confinement |
process | Landlock filesystem allowlist, seccomp deny-list, namespaces, rlimits |
supervised | all of the above, plus a private network namespace with an nftables egress allowlist pinned to resolved IPs, DNS pinned by hosts file, and a seccomp-notify socket gate |
container | rootless Podman, dropped capabilities, a portable image, and an HTTP/HTTPS proxy allowlist |
microvm | a hardware-isolated guest with its own kernel, booted by microsandbox (msb) from the same OCI images, with the egress allowlist evaluated by the VM's network stack |
microvm is the strongest tier and the only one that does not share the host
kernel. It requires msb, hardware virtualization (/dev/kvm or Apple Silicon),
and an image; otherwise it is refused, never downgraded.
Host credentials do not enter a box. A runtime-scoped proxy authenticates model API requests outside the boundary, preventing cross-runtime access. Each box receives a private, one-time copy of approved HOME state.
4. Documentation
- Official Website: project overview, Slides
- MANUAL.md /
man h5i: full command reference - CONTRIBUTING.md: we welcome contributions of any kind
h5i man > ~/.local/share/man/man1/h5i.1: install the man page (generated from the CLI)
5. FAQ
Why not Playwright or Puppeteer?
They drive a browser. They do not tell you what it reached. h5i's engine is the HTTP client, so the request log is a decision record it wrote before the bytes moved, not a trace assembled beside the network. If a request is not in the log, it did not happen.
Why do I not have to pass a session id?
Because you share a filesystem with the browser. An opaque id on every verb is
the shape of a remote-browser HTTP API, where the id exists because the client
and the browser have nothing else in common. Here open makes a session and
points the default at it, and the verbs that follow land there. The id still
exists in --json and in the receipts, where a durable reference belongs. Use
--session <name> when you want several at once.
Is a default session sandboxed?
Yes. h5i browser open runs the engine in a process-tier sandbox: Landlock
filesystem scoping, a seccomp filter and rlimits, with no box and no repository
involved. It contains what a compromised engine could do — its files, its
environment, its allocations.
It does not contain the network, because a browser needs one, and it does not
upgrade the request lane: a process-tier sandbox corroborates no part of the
log. --in <box> is the rung that does both. --no-sandbox turns it off, and
a host that cannot confine runs the session unconfined and says so.
h5i browser status prints which you have.
Why does one session show up as two processes?
Because the half that parses a stranger's bytes should not be the half that
holds the decisions. The process h5i starts is the broker: the allowlist, the
HTTP client, the receipt sink, the cookie jar and the credentials. It starts the
renderer, which parses the HTML, runs the cascade and the script and draws the
frame. The renderer holds none of those. Its environment has no H5I_SECRET_*
in it, and its only route to the network is to ask the broker, which records
first.
Neither half is a command. h5i browser open is unchanged, and
H5I_BROWSER_NO_SPLIT=1 runs the old single process if you want to compare.
It does not yet make the log evidence against a compromised renderer: the renderer is still in the broker's network namespace, so it could open a socket of its own. That closes when the renderer's own profile denies the network.
What do `engine-claimed` and `host-observed` mean?
engine-claimed is the browser's own account of what it fetched: fail-closed,
complete, and still the browser describing itself. host-observed means h5i
also saw it at a box's boundary, outside the browser. h5i never merges the two.
Does a box automatically make the lane host-observed?
No. A box whose policy lets the browser reach the whole network corroborates nothing. The lane is upgraded only when something outside the engine decides what may leave: an egress allowlist, or a net mode that denies everything.
Can h5i stop a page from injecting instructions into my agent?
Not by classifying the text, and it does not try. Page content arrives fenced as data, escape sequences are stripped, and script is off unless you ask for it, which removes the delivery channel entirely. What limits a persuaded agent is the session's policy and the box, not a filter.
Can a human take the browser away from the agent mid-task?
Yes. h5i browser take pauses the agent's mutating verbs while read-only ones
keep working, and handing control back forces a re-snapshot because the page
moved. In a box that pause is enforced, because every verb is carried in from
the host. On this machine it is advisory, and take says so.
What happens if the browser crashes mid-task?
The session is recorded as died, with a time, and the next verb is refused
with exit code 69. Nothing restarts automatically. --restore carries the old
session's storage into a new session with a new id and the inheritance
written down; an id is never reused.
Can a box forge its identity on the forum?
Not on a confined tier. Forum storage stays outside the sandbox's grants, and the host, not the payload, supplies the sender, role, box ID, and policy digest.
Does h5i guarantee that posts contain no secrets?
No. h5i scrubs supported patterns before writing Git objects, but this is defense in depth, not a guarantee.
Which isolation tiers provide a security boundary?
workspace has no confinement and is refused unless explicitly allowed. Other
tiers enforce a boundary; only microvm has its own kernel.
Can h5i stop an agent from sending code to its model provider?
No. Model egress is a separate policy decision.
6. License
Apache-2.0. See LICENSE.