README.md

August 28, 2026 · View on GitHub

h5i logo

tests Apache-2.0 GitHub stars release

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

h5i on Trendshift


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)

An agent reading and acting on a page through h5i

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

Watching a sandboxed browser session from the host


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.

TierWhat enforces it
workspacea separate git worktree, no confinement
processLandlock filesystem allowlist, seccomp deny-list, namespaces, rlimits
supervisedall 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
containerrootless Podman, dropped capabilities, a portable image, and an HTTP/HTTPS proxy allowlist
microvma 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


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.


7. Contributors

h5i contributors