Show HN: peerd – 完全在浏览器中运行的 AI 智能体框架
Show HN: peerd – AI agent harness that runs entirely in your browser

原始链接: https://github.com/NotASithLord/peerd

**peerd** 是一款实验性的浏览器原生 AI 智能体(Chrome/Firefox 扩展程序),可直接在您现有的浏览器会话中运行。它为 AI 提供了一个安全、独立的运行环境,用于浏览网页、在沙盒 Linux 虚拟机/笔记本中执行代码,以及构建个人应用程序。 **主要功能:** * **浏览器即运行时:** 利用浏览器原生的安全机制(V8 隔离、WebCrypto、WebAuthn),peerd 确保智能体在没有经过严格的受限验证前,无法访问原始页面数据或您的 API 密钥。 * **以用户为中心的安全机制:** 采用“自带密钥”(BYOK)模式,将机密信息存储在加密的本地保险库中。数据路径中不存在任何遥测技术或云端后端。 * **验证执行:** 智能体提出操作建议,由浏览器平台进行决策;每一项操作都会根据实时页面进行准确性验证。 * **去中心化潜力:** 预览版本包含一个用于智能体间通信的点对点(dweb)层。 该项目目前处于 0.x 测试阶段,强调“无需构建”的原生 JS 架构,并采用五模块设计(提供者、出口、引擎、运行时、分布式)以保持模块化安全性。它专为能够承担自动化浏览器交互和管理敏感凭据相关风险的开发人员及早期测试者设计。

**peerd** 是一个实验性的开源 AI 智能体框架,以浏览器扩展程序的形式构建。与需要复杂集成的外部 AI 工具不同,peerd 利用浏览器原生且经过实战检验的安全沙箱,直接在网页环境中运行自主智能体。 核心功能包括: * **基础设施:** 完全在浏览器内使用原生 JavaScript 运行,支持多种提供商(Anthropic、OpenRouter、本地 Ollama 以及基于 WebGPU 的 Gemma)。 * **能力:** 使用 WebAssembly 等浏览器原语来运行隔离的 Linux 虚拟机、JS 笔记本和无头计算任务。 * **P2P 通信:** 集成 WebRTC 以实现去中心化的智能体间 (A2A) 交互,无需中间商。 * **安全性:** 采用多层方法处理智能体安全的“致命三重奏”。它将执行环境与主智能体循环分离,并将 DOM 输出和运行摘要视为不可信,以减轻提示词注入风险。 该项目目前处于 v0.x 预览阶段,强调“无需构建”的理念,方便用户通过 GitHub 进行审计和安装。开发者正在积极迭代一种新的架构,通过独立的“驻留”智能体来管理特定标签页,从而进一步改善隔离性和上下文管理。
相关文章

原文

peerd

CI License: Apache 2.0 Status: 0.x experimental Manifest V3 No build step

types: 100% ts-check PRs welcome Security policy

peerd is the first AI agent harness native to the browser. It's a Chrome/Firefox extension that runs a full agent loop inside the browser you already use — with the tabs and sessions you already have. It reads and drives your pages, spins up sandboxed compute (JS Notebooks, full Linux VMs compiled to WebAssembly, personal client-side apps), and — on the preview channel — shares what it builds over a peer-to-peer WebRTC network built for agent-to-agent communication. BYOK to the model provider of your choice. No backend, no telemetry, no cloud component in the data path.

newdemo.mp4

The bet is structural: peerd uses the browser as its runtime, its hypervisor, and its security model. It inherits decades of hardened browser platform work — V8 isolates for sandboxing, WebCrypto for the vault, WebAuthn passkeys to unlock it, opaque-origin iframes, Subresource Integrity — and writes zero lines of its own cryptographic or process-isolation code. The agent that holds your keys never reads a raw page; a disposable runner with no keys and no network does, and its output comes back fenced as untrusted. And the agent never takes its own word for success: every action it drives is verified against the live page before it counts as done — the model proposes, the browser decides. (More at peerd.ai.)

The name is always lowercase: peerd.

Status: 0.x — experimental beta. It works and the initial feature buildout is complete and integrated (see STATUS.md), but the surface is still moving: breaking changes are likely, storage formats may shift, and it drives your browser and holds your API keys — use it with care. There is no "V1" commitment; versions stay in the 0.x range until the surface stabilizes.

For the full, itemized list of what's shipped — categorized by module — see FEATURES.md.

Developer preview: Load the source tree unpacked using the steps below. This is the current source-of-truth install path for contributors and early testers.

Store packages: Chrome Web Store / Firefox Add-ons listings will be linked here once they are approved. Store packages omit preview-only dweb pieces and the preview/dev advanced automation path.

Dweb preview (research package): GitHub Releases may include signed preview artifacts. If there is no release attached yet, use the source install path below.

The preview package includes the decentralized web (dweb) layer — peer-to-peer dwapps between peerd instances. It's intended for contributors and early testers — the dweb protocol is research-grade and subject to change. Most users want one of the two store packages above. The preview installs alongside the store package as a separate extension ("peerd preview") with its own isolated storage; move state between them explicitly via Settings → Export & import.

Preview package install paths (Firefox is the smoother of the two):

  • Firefox: click peerd-preview-firefox.xpi on the release page — it's AMO-signed, installs like any extension, and auto-updates.
  • Chrome on macOS / Windows (recommended): load the zip unpacked. Chrome hard-disables off-store CRX installs on these platforms ("may have been added without your knowledge", enable toggle locked) — and field testing showed even an ExtensionInstallAllowlist policy visible in chrome://policy does NOT unlock it on an unmanaged machine (Chrome wants MDM-grade management). So don't fight it: download peerd-preview-chrome.zip, unzip it, enable Developer mode at chrome://extensions, Load unpacked, and pick the unzipped folder. Caveats: no auto-update (download the new zip per release) and the extension ID is machine-specific, not the table's CRX ID. This is a Chrome platform restriction on all self-hosted extensions, not a peerd choice.
  • Chrome on Linux (or any policy-managed Chrome): download peerd-preview-chrome.crx, enable Developer mode at chrome://extensions, and drag the file onto the page. Auto-update then follows the feed at peerd.ai/updates/.

Extension IDs (verify which package you're running):

package id
peerd (Chrome store) verify from the store listing or chrome://extensions after install
peerd (Firefox store) [email protected]
peerd preview (Chrome) lpdkhfeldihoejbbfonnbekpjclkknoc (CRX installs only — an unpacked load gets a machine-specific ID)
peerd preview (Firefox) [email protected]

peerd has no build step — you load the extension/ folder straight into Chrome as it is on disk. You need a Chromium-based browser (Chrome, Edge, Brave, Arc, …) and a model to talk to: a key from Anthropic and/or OpenRouter, or a local Ollama (keyless, no bill, nothing leaves your machine). BYOK: any key lives encrypted in a local vault and is only ever sent to that provider.

1. Get the code

git clone https://github.com/NotASithLord/peerd.git
cd peerd

2. Load the extension in Chrome

  1. Open chrome://extensions.
  2. Turn on Developer mode (toggle, top-right).
  3. Click Load unpacked.
  4. Select the extension/ folder inside the repo — not the repo root. (The folder with manifest.json in it.)

peerd now appears in your extensions list. Click the puzzle-piece icon in the toolbar and pin peerd so its icon is always visible.

3. Open peerd and set up the vault

Click the peerd toolbar icon — the side panel opens. On first run you create a local vault: unlock with Touch ID / a passkey (recommended) or a recovery passphrase. Keys, chat history, and the audit log are all encrypted on this device; nothing leaves your machine except the calls to your model provider.

4. Add your API key(s)

Open Settings (gear icon) → API keys. Paste a key for Anthropic (sk-ant-…) and/or OpenRouter (sk-or-…). You can set both at once — each is stored independently. Choose a default under Default model for new chats, and switch the model per chat from the picker above the message box.

5. Chat

Back in the chat, type a message. peerd can read and drive your open tabs, run shell commands in a sandboxed in-browser Linux VM, build small apps, search the web, and more. Turn on Confirm before actions in Settings if you want to approve each tab/automation step first (off by default).

Updating after a code change. Hit the reload icon on the peerd card in chrome://extensions. The side panel, offscreen document, and any open VM/JS/App tabs reload with it.

Firefox (temporary). about:debugging#/runtime/this-firefoxLoad Temporary Add-on → pick extension/manifest.json. Re-load on each edit. Firefox parity is still being polished — Chrome is the primary target for now.

Generated files. extension/manifest.json and extension/shared/channel-config.js are GENERATED (the checked-in copies are the dev defaults — preview channel, dweb on). Don't hand-edit them; change manifests/*.json or packaging/default-settings.mjs and run bun run gen:dev. CI fails if they drift.

Why the permissions? peerd asks for broad host access (<all_urls>, and debugger on the preview/dev channels) because driving arbitrary tabs and reading the page the agent is acting on is the whole point. Each permission, why it's needed, and what the store build strips is spelled out in docs/store/PERMISSION-JUSTIFICATIONS.md — and the trust boundaries (BYOK vault, egress allowlist, untrusted-content handling, no telemetry) in SECURITY.md.

Project conventions (the short version)

  • Plain vanilla JS, ES2024+. No TypeScript, no JSX, no bundler, no npm inside extension/.
  • ES modules only. Strict mode by default.
  • Pure functions and reducers over classes. Classes only where lifecycle is real (vault, VM, ports).
  • safeFetch / webFetch for all outbound HTTP — bare fetch is forbidden.
  • Comments explain why, not what. The codebase is security-sensitive and is meant to be read carefully.

The full version of these conventions and the architectural rationale lives in CLAUDE.md (orientation), ARCHITECTURE.md (module organization), and DESIGN.md (the full technical design record — vault crypto, dispatcher gates, prompt-injection defenses, the MV3 keepalive trick; long, historical, and worth searching before reopening a settled question).

The five-letter wordmark is the architecture — each colored letter is one top-level module. Each module has its own README with how it works today, its public API, known limitations, and TODOs:

Module Role
p · cyan peerd-provider Model adapters — Anthropic, OpenRouter, Ollama (streaming, caching, cost, retries)
e · red peerd-egress Security — the vault, the egress chokepoint, the denylist, the audit log
e · amber peerd-engine Sandboxes — WebVMs, Notebooks, Apps, and the headless worker
r · green peerd-runtime The agent — loop, tools, do/get/check, memory, skills, review, goal mode, voice
d · magenta peerd-distributed The dweb — the peer-to-peer network (preview channel only)

The brand IS the architecture: cross-module imports go through each module's index.js, never deep paths; nothing outside peerd-distributed/ imports it at all. See ARCHITECTURE.md for the dependency graph.

peerd's safety is who is allowed to do what — small, legible boundaries enforced by the browser platform, not by peerd's own crypto. Two principles run through all of it: the agent that holds your keys never touches a raw page or runs untrusted code, and the agent never gets the final word on correctness — every action is verified against the live page before it counts as done.

Actor Trusted with Never
The vault (peerd-egress/vault) your API keys + secrets, decrypted only after Touch ID / passkey / passphrase unlock; idle auto-lock leaving the device — keys go only to the provider you chose
The main agent (peerd-runtime/loop) the conversation, planning, tool dispatch reading raw page bytes or running untrusted code directly
The disposable runner (peerd-runtime/runner) driving + reading the page via do/get/check holding keys or its own network; its output returns wrapUntrusted-fenced
The egress chokepoint (safeFetch / webFetch) every outbound byte — provider allowlist + denylist + SSRF guard being bypassed; a bare fetch is lint-forbidden
The sandboxes (WebVM · Notebook · App) running code — V8 isolates + opaque-origin iframes extension access; their HTTP routes back through egress
Web content nothing by default being trusted — all of it is fenced as untrusted input

The shape is proposes vs. decides: the AI proposes and drives; the browser platform (WebCrypto vault, WebAuthn unlock, V8 isolates, SRI) and the live DOM are what actually decide. Full detail in SECURITY.md and DESIGN.md.

Read CLAUDE.md for quick orientation, ARCHITECTURE.md for the five-module organization, ARCHITECTURE-CHANGES.md if you're picking up work from a previous session, FEATURES.md for what's shipped, PACKAGING.md for the dual-distribution packaging system, and docs/DECISIONS.md for the recorded design tradeoffs.

The five-letter wordmark is the architecture (see ARCHITECTURE.md). Each colored letter maps to a top-level module:

peerd/
├── extension/                # the extension itself — load this dir unpacked
│   ├── manifest.json
│   ├── peerd-provider/       # p · cyan    — model adapters (Anthropic, OpenRouter, Ollama; OpenAI later)
│   ├── peerd-egress/         # e · red     — vault, allowlist, denylist, confirm, audit
│   ├── peerd-engine/         # e · amber   — execution-instance registries (WebVM, Notebook, App). Tab runtimes in <kind>-tab/; the headless js_run worker in offscreen/.
│   ├── peerd-runtime/        # r · green   — agent loop, tools + do/get/check runner, sessions, permissions, composer, skills, memory, review, goal mode, cost, transfer, subagent, voice, clock, dom, edit
│   ├── peerd-distributed/   # d · magenta — the dweb layer between peerd instances (ships ONLY in preview packages)
│   ├── background/           # chassis: service worker + per-kind tab trackers + clients
│   ├── offscreen/            # chassis: SW keepalive + voice host
│   ├── sidepanel/            # chassis: chat UI (Mithril)
│   ├── vm-tab/               # chassis: WebVM tab page (CheerpX + bash + xterm)
│   ├── notebook-tab/         # chassis: Notebook tab page (Web Worker + OPFS)
│   ├── app-tab/              # chassis: App tab page (stored HTML in sandboxed iframe)
│   ├── eval/                 # live end-to-end eval harness (runner.html)
│   ├── shared/               # base types and utilities (importable everywhere)
│   ├── tests/                # in-browser test runner — open runner.html
│   ├── vendor/               # third-party deps, committed as-is (CheerpX, xterm, mithril, Moonshine)
│   └── permissions/          # permission-grant pages (mic, etc.)
├── manifests/                # base manifest + per-channel patch documents (PACKAGING.md)
├── packaging/                # Bun packaging scripts: manifest gen, channel artifacts, signing, feeds
├── tests/                    # Bun test suite (bun test ./tests)
├── update-feeds/             # generated auto-update feeds served at peerd.ai/updates/ (copied to peerd-site to deploy)
├── docs/                     # DECISIONS.md, distributed/, store/, and friends
├── signaling-node/           # dweb rendezvous server shells (share the pure signaling reducer)
├── v1-deliverables/          # V1 buildout record: INTEGRATION-LOG.md, TEST-PLAN.md
└── scripts/                  # dev helpers (cdp/ headless harness, dev-server.sh, vendor-*)

peerd ships from this one tree in two channels: peerd (Chrome Web Store / Firefox Add-ons, no dweb code in the artifact) and peerd preview (GitHub Releases, dweb enabled, signed, auto-updating). Same source, same version, same release — the channel only decides whether the dweb module ships. PACKAGING.md has the whole story.

Cross-module imports go through each module's index.js — never deep paths. ESLint enforces. Within a module, deep imports are fine.

peerd-engine hosts Sandboxes — four execution kinds (taxonomy in DESIGN.md §8.5). Three are discrete, persistent browser tabs the user can see, focus, and close, grouped under "peerd" in the tab strip and surviving browser restarts: the WebVM, the Notebook, and the App. The fourth, the headless worker (js_run), runs the Notebook's sealed worker offscreen with no tab — ephemeral, for the agent's own quick compute. The agent picks the lightest kind that fits the task.

WebVM — CheerpX-emulated Debian (sandboxed Linux). Own disk (IDB overlay), own bash, own POSIX. ~10s first boot. The heavy hitter; use when you need real binaries, a shell, multi-language stacks.

vm_list   vm_create   vm_boot   vm_import   vm_write_file   vm_delete

HTTP egress from the VM (curl / wget / git clone) is intercepted by bash function wrappers that route every request through peerd-egress before it leaves the browser.

Notebook — a sealed Web Worker with its own JS realm and an OPFS file tree, in a visible tab. ~hundreds of ms boot. peerd.egress.fetch is the worker's only network, routed through peerd-egress so it's honest. Each js_notebook run spawns a fresh worker, so in-memory state (globalThis, let/const) does NOT carry between runs — persist via peerd.self.writeFile/readFile to the OPFS file tree.

js_list   js_create   js_notebook   js_run   js_write_file   js_read_file   js_delete

Headless worker — the same sealed worker as a Notebook, but headless: js_run runs it in the offscreen document with no tab, ephemeral scratch discarded after. It's the agent's own quick compute and peerd's code mode (one script instead of a chain of tool/MCP calls), not a workspace you watch — a distinct kind from the Notebook, same substrate.

App — a stored HTML document the agent built for the user, rendered in a sandboxed iframe (own opaque origin, no extension access). Metadata in chrome.storage.local; body in IndexedDB; substring search across name, tags, and body. app_update auto-reloads the open tab so iterations show live.

app_list   app_create   app_update   app_open   app_search   app_delete

Two surfaces, different jobs (see CLAUDE.md):

In-browser — things that need a real browser (DOM, chrome.*, IDB, side-panel components, the SW). Open chrome-extension://<ext-id>/tests/runner.html in a tab and refresh to re-run. Tiny custom framework covering the vault, the tool dispatcher, introspection tools, provider streaming + tool_use, the session store, agent loop, denylist matcher, egress, and more. The same suite runs headless in CI via the CDP harness (scripts/cdp/run-inbrowser-tests.mjs — headless Chrome over the DevTools Protocol, no MCP).

Bun — pure logic that runs without a browser (registries, the module resolver, the Markdown renderer, the OpenAI/OpenRouter format layer). Fast and runnable from the terminal:

bun install        # once — pulls the dev-only test deps (e.g. fake-indexeddb)
bun test ./tests

(Bun is only needed for these terminal tests and for re-vendoring third-party deps — running the extension itself needs no toolchain at all.)

Types — JSDoc + // @ts-check, mandatory for browser files. The extension is no-build vanilla JS, so types come from JSDoc checked by a // @ts-check directive, not a .ts toolchain. bun run typecheck (strict tsc) checks every annotated file; bun run check:tscheck is a CI gate on coverage. Every browser file (extension/**/*.js) now carries // @ts-check — 100% — and it is required on new ones: add the directive and make the file type-clean (bun run typecheck), or CI fails. (The Bun tests under tests/ are real TypeScript — Bun runs .ts directly; only code the browser loads is JSDoc-on-JS.)

peerd stands on a lot of excellent open-source work. The MV3 CSP forbids remote script execution (script-src 'self' 'wasm-unsafe-eval'), so every third-party runtime dependency is vendored — committed pre-built under extension/vendor/, pinned to a version, and SHA-verified by a scripts/vendor-*.sh (or .ts) re-vendor step. Each directory carries a SOURCE.txt recording the upstream, the pinned version, the hash, and the update procedure. A fresh clone runs with no build and no network fetch for code. You only touch the vendor scripts when updating a dependency, and the regenerated bytes are checked in; peerd's own code is plain ES modules loaded directly, never bundled.

Thank you to the maintainers of all of these projects.

Vendored runtime dependencies

Component Version License Used for
CheerpX (docs) 1.2.8 Proprietary — license your responsibility¹ x86 Linux in WebAssembly — the WebVM sandbox runtime (peerd-engine, vm-tab/)
xterm.js (@xterm/xterm + @xterm/addon-fit) 5.5.0 / 0.10.0 MIT In-browser terminal emulator rendering the WebVM's PTY (vm-tab/)
Mithril.js 2.3.8 MIT UI framework for the side panel and Apps
CodeMirror 6 (@codemirror/*) 6.x MIT Code editor in the App tab (peerd-engine/editor.js)
Moonshine (@moonshine-ai/moonshine-js) 0.1.29 MIT Local, in-browser speech-to-text for voice input (peerd-runtime/voice/)
ONNX Runtime Web (onnxruntime-web) 1.22.0 MIT WASM/WebGPU inference backend Moonshine runs on (vendor/onnxruntime-web/)
Silero VAD (@ricky0123/vad-web) 0.0.24 MIT Voice-activity detection / speech endpointing for Moonshine (vendor/vad-web/)
hash-wasm (Argon2 bundle) 4.12.0 MIT Argon2id KDF deriving the vault's key-encryption key (peerd-egress/vault/)
webextension-polyfill 0.12.0 MPL-2.0 One promise-based browser.* API across Chrome and Firefox
Transformers.js (@huggingface/transformers) 4.2.0 Apache-2.0 WebGPU runtime for the on-device local-inference runner (offscreen/local-model.js

¹ CheerpX is proprietary, closed-source software — the one vendored dependency here that is not under an open-source license, and the only one with a paid tier. Per Leaning Technologies' EULA and licensing terms, the free Community tier covers individuals and one-person companies for any purpose (including revenue-generating, public-facing products); organizations of more than one person may use it for free only for evaluation and testing — production use requires a paid Commercial License (contact-sales; no public price list). Separately, bundling and redistributing the CheerpX runtime — which peerd does by vendoring it into extension/vendor/cheerpx/ — and self-hosting it off Leaning's CDN is gated: their terms state that downloading a CheerpX build to host it elsewhere is not permitted without a commercial license. peerd ships the runtime as a convenience and makes no licensing grant. If you run, fork, distribute, or build a commercial offering on peerd, obtaining whatever CheerpX license your use requires is your responsibility, not peerd's — contact Leaning Technologies before any commercial launch. ² Local in-browser WebGPU inference is early but proven — one model (Gemma-4-E2B) ships behind an opt-in download, WebGPU-only; broader model support is staged. Design notes: docs/LOCAL-INFERENCE.md.

Models and data fetched at runtime

These are data, not script, so they're fetched lazily on first use and cached locally (IndexedDB / OPFS) rather than shipped in-package — but they're open assets worth crediting:

  • CheerpX Debian image — CheerpX's stock Debian ext2 disk, streamed lazily over WebSocket from disks.webvm.io (the only relaxed connect-src origin). The disk content is unmodified Debian under Debian's own (free) licensing — a separate concern from the proprietary CheerpX runtime that streams it (note ¹ above).
  • Moonshine STT modelsUsefulSensors/moonshine ONNX weights (the base variant, ~250 MB), SRI-pinned to specific Hugging Face commits (peerd-runtime/voice/model-store.js).
  • Silero VAD modelsilero_vad ONNX weights, served same-origin from the vendored vad-web package.
  • Gemma on-device modelonnx-community/gemma-4-E2B-it-ONNX weights (~1.3 GB), the model behind the early on-device WebGPU runner. It's Google's Gemma converted to ONNX by the onnx-community / Xenova (Transformers.js) ecosystem, downloaded opt-in and run in the offscreen doc (offscreen/local-model.js). The Gemma weights are under Google's Gemma Terms of Use — a custom license with use restrictions, not a standard OSI-approved one — so they're a credited runtime download, never bundled.

The brand mark on monochrome, the spinner cadence, and the rest of peerd's own design are first-party. Everything above is third-party and credited to its upstream.

Apache 2.0 — see LICENSE.

peerd is provided "as is", without warranty of any kind, express or implied — including, without limitation, the implied warranties of merchantability, fitness for a particular purpose, title, and non-infringement. The entire risk as to the quality and performance of the software is with you.

In no event shall the authors or copyright holders be liable for any claim, damages, or other liability — whether in contract, tort, or otherwise — arising from, out of, or in connection with the software or its use.

This is early, actively-developed software that drives your browser, executes code, and handles your API keys and other secrets on your behalf. Use it at your own risk. The controlling terms are the Disclaimer of Warranty and Limitation of Liability in LICENSE (Apache 2.0, sections 7 and 8).

联系我们 contact @ memedata.com