Arlopass is a browser extension + SDK that lets web apps use your AI providers (Ollama, Claude, GPT, Bedrock) without ever seeing your API keys. You install the extension, connect your providers, and approve each request. The app gets AI; your credentials never leave your machine.
import { ArlopassClient } from "@arlopass/web-sdk";
const client = new ArlopassClient({ transport: window.arlopass, origin: location.origin });
await client.connect({ appId: "com.acme.app" });
const { providers } = await client.listProviders();
await client.selectProvider({
providerId: providers[0].providerId,
modelId: providers[0].models[0],
});
const reply = await client.chat.send({
messages: [{ role: "user", content: "Hello!" }],
});
console.log(reply.message.content);
await client.disconnect();The Arlopass extension injects a transport at window.arlopass. The web app never sees your API keys or tokens — they stay on your machine, routed through a local bridge to your chosen provider.
How it works · Streaming · Adapters · Setup · Packages · Development
- A web app requests AI capabilities through
@arlopass/web-sdk - The Arlopass browser extension prompts the user for consent
- The user selects a provider and model from their connected accounts
- Requests route through a local bridge to the chosen provider
- Policy, audit, and telemetry are enforced at every trust boundary
- Install the extension — Chrome Web Store (or load unpacked from
apps/extensionfor development) - Start the bridge —
pnpm run dev:bridge(or download a release) - Open the demo app —
pnpm run dev:e2e-harness→ visithttp://localhost:5173 - Connect a provider — Open the extension popup, add your Ollama / OpenAI / Claude credentials
- Send a message — The demo app requests AI through the extension. You approve, pick a model, done.
Tip
No API keys? Install Ollama locally for a free, zero-cloud setup.
┌─────────────────────────────────────────────────────────────┐
│ Web Application │
│ @arlopass/web-sdk │
└──────────────────────────┬──────────────────────────────────┘
│ window.arlopass (injected transport)
┌──────────────────────────▼──────────────────────────────────┐
│ Arlopass Wallet Extension │
│ Consent UI · Permission Store · Policy Preflight │
└──────────────────────────┬──────────────────────────────────┘
│ Chrome Native Messaging (stdio)
┌──────────────────────────▼──────────────────────────────────┐
│ Local Bridge Daemon │
│ Adapter Host · Session Management · Policy Enforcement │
├─────────┬──────────┬────────────┬───────────────────────────┤
│ Ollama │ Claude │ CLI Bridge│ Amazon Bedrock / GCP / │
│ Adapter │ Adapter │ Adapter │ Azure (planned) │
└─────────┴──────────┴────────────┴───────────────────────────┘
Trust boundaries are enforced at every layer:
| Boundary | Protection |
|---|---|
| Web app ↔ Extension | Origin isolation, explicit user consent, capability-scoped permissions |
| Extension ↔ Bridge | HMAC challenge/response handshake, ephemeral session keys, anti-replay nonces |
| Bridge ↔ Adapters | Sandboxed execution, manifest-declared capabilities, egress restrictions |
| Adapter ↔ Provider | Least-privilege auth, OS keychain credential storage, request timeouts |
Requires Node.js 20+, pnpm, and Chrome (or Chromium).
git clone https://github.com/arlopass/arlopass.git
cd arlopass
pnpm installVerify the build:
pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run build# PowerShell (Windows)
.\scripts\dev\run-dev.ps1 -Mode full
# Bash (macOS/Linux)
./scripts/dev/run-dev.sh fullThis installs dependencies, starts build watchers, launches the bridge, and registers the native messaging host.
Tip
Aliases: pnpm run dev:full, pnpm run dev:setup, pnpm run dev:validate, pnpm run dev:watch, pnpm run dev:bridge.
- Build:
pnpm --filter @arlopass/extension run build - Open
chrome://extensions, enable Developer mode - Click Load unpacked, select
apps/extension
pnpm run dev:e2e-harnessOpens at http://localhost:5173 — demonstrates connect/disconnect, provider selection, chat, streaming, and error handling.
for await (const event of client.chat.stream({
messages: [{ role: "user", content: "Explain zero-trust architecture" }],
})) {
if (event.type === "chunk") process.stdout.write(event.delta);
}Skip the extension and talk to a provider directly:
import { OllamaAdapter } from "@arlopass/adapter-ollama";
const adapter = new OllamaAdapter({ baseUrl: "http://localhost:11434" });
const models = await adapter.listModels();
const sessionId = await adapter.createSession({ model: "llama3.2" });
const output = await adapter.sendMessage(sessionId, "Summarize secure coding in 5 bullets.");
console.log(output);
await adapter.shutdown();If you don't use the browser extension, supply your own ArlopassTransport:
import { ArlopassClient, type ArlopassTransport } from "@arlopass/web-sdk";
const transport: ArlopassTransport = {
async request(req) {
const res = await fetch("/api/arlopass", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(req),
});
return { envelope: await res.json() };
},
async stream(req) {
const res = await fetch("/api/arlopass/stream", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(req),
});
const reader = res.body!.getReader();
const decoder = new TextDecoder();
return {
async *[Symbol.asyncIterator]() {
while (true) {
const { done, value } = await reader.read();
if (done) break;
yield { envelope: JSON.parse(decoder.decode(value)) };
}
},
};
},
};
const client = new ArlopassClient({ transport, origin: location.origin });
## Packages
This monorepo is organized into three workspace groups:
### Core Packages (`packages/`)
| Package | Description |
|---------|-------------|
| [`@arlopass/protocol`](packages/protocol/) | Envelope format, capability model, version negotiation, error codes |
| [`@arlopass/web-sdk`](packages/web-sdk/) | `ArlopassClient` — connect, chat, stream, state machine |
| [`@arlopass/policy`](packages/policy/) | Policy evaluation — allow/deny rules, signed bundles, ed25519 verification |
| [`@arlopass/audit`](packages/audit/) | Audit events, JSONL and OTLP exporters, field redaction |
| [`@arlopass/telemetry`](packages/telemetry/) | Metrics, tracing, and sensitive-data redaction |
### Adapters (`adapters/`)
| Package | Provider | Status |
|---------|----------|--------|
| [`@arlopass/adapter-ollama`](adapters/adapter-ollama/) | Local Ollama models | Implemented |
| [`@arlopass/adapter-openai`](adapters/adapter-openai/) | OpenAI (GPT-4o, o1, etc.) | Implemented |
| [`@arlopass/adapter-claude-subscription`](adapters/adapter-claude-subscription/) | Anthropic Claude API | Implemented |
| [`@arlopass/adapter-gemini`](adapters/adapter-gemini/) | Google Gemini API | Implemented |
| [`@arlopass/adapter-perplexity`](adapters/adapter-perplexity/) | Perplexity API | Implemented |
| [`@arlopass/adapter-amazon-bedrock`](adapters/adapter-amazon-bedrock/) | Amazon Bedrock | Implemented |
| [`@arlopass/adapter-google-vertex-ai`](adapters/adapter-google-vertex-ai/) | Google Vertex AI | Implemented |
| [`@arlopass/adapter-microsoft-foundry`](adapters/adapter-microsoft-foundry/) | Azure AI Foundry | Implemented |
| [`@arlopass/adapter-local-cli-bridge`](adapters/adapter-local-cli-bridge/) | Local CLI tools (Copilot CLI, Claude Desktop) | Implemented |
| [`@arlopass/adapter-runtime`](adapters/runtime/) | Adapter host lifecycle, sandbox, health checks, manifest validation | — |
| [`@arlopass/adapter-tooling`](adapters/tooling/) | Development utilities for building adapters | — |
### Applications (`apps/`)
| Package | Description |
|---------|-------------|
| [`@arlopass/bridge`](apps/bridge/) | Native messaging daemon — routes requests between extension and adapters |
| [`@arlopass/extension`](apps/extension/) | Chrome Manifest V3 extension — consent UI, permissions, provider selection |
| [`@arlopass/e2e-harness`](apps/e2e-harness/) | Vite + React demo app — connect, chat, stream, provider selection |
### Operations (`ops/`)
[SLO definitions](ops/slo/slo-definitions.md), [alert rules](ops/slo/alert-rules.md), [runbooks](ops/runbooks/), and test suites ([chaos](ops/tests/chaos/), [release-gates](ops/tests/release-gates/), [soak](ops/tests/soak/), [version-skew](ops/tests/version-skew/)).
## Development
### Project Scripts
| Command | Description |
|---------|-------------|
| `pnpm run dev:full` | Full dev environment (deps + watchers + bridge) |
| `pnpm run dev:setup` | Install dependencies |
| `pnpm run dev:validate` | Run lint + typecheck + tests |
| `pnpm run dev:watch` | Watch builds for bridge + extension |
| `pnpm run dev:bridge` | Build and run the bridge |
| `pnpm run dev:examples` | Start the examples web app |
| `pnpm run dev:register-native-host` | Register Chrome native messaging host |
| `pnpm test` | Run all tests with Vitest |
| `pnpm run build` | Build all workspaces |
| `pnpm run lint` | Lint all workspaces |
| `pnpm run typecheck` | Type-check all workspaces |
### Running Tests
```bash
# All tests
pnpm test
# Specific workspace
pnpm --filter @arlopass/web-sdk run test
# Watch mode
pnpm exec vitest --workspace vitest.workspace.ts
# Reliability suites
pnpm run test -- ./ops/tests/chaos
pnpm run test -- ./ops/tests/release-gates
pnpm run test -- ./ops/tests/soak
pnpm run test -- ./ops/tests/version-skewpnpm install --frozen-lockfile
pnpm run lint
pnpm run typecheck
pnpm run test
pnpm run buildImportant
The bridge and extension pair automatically on first connection. No shared secret or manual configuration is needed.
For the extension to communicate with the local bridge, register the native messaging host:
pnpm run dev:register-native-hostOr manually create a com.arlopass.bridge.json manifest pointing to your bridge executable and register it in the Chrome NativeMessagingHosts registry key.
- Per-origin permissions — Each web app must be explicitly approved
- Capability-scoped grants —
provider.list,session.create,chat.completions,chat.stream - Dual enforcement — Preflight in extension + authoritative check in bridge
- OS keychain storage — Windows Credential Manager, macOS Keychain, Linux Secret Service
- Signed artifacts — Ed25519 signing for policy bundles and adapters
- Anti-replay — Nonce expiry and strict request TTL on bridge communications
- Default-deny — No auto-connect, no wildcard origins, sensitive fields redacted from logs
Note
For security vulnerabilities, please see our SECURITY.md for responsible disclosure guidelines.
| Problem | Solution |
|---|---|
| Extension can't connect to bridge | Verify com.arlopass.bridge native host is registered. Run pnpm run dev:register-native-host and reload the extension. |
auth.invalid during handshake |
Extension and bridge may have stale pairing state — delete %LOCALAPPDATA%\Arlopass\bridge\state and re-pair. |
| Popup shows no providers | Seed demo providers via the extension options page or service worker console. See the usage guide. |
window.arlopass is undefined |
Reload the unpacked extension, refresh the target tab, and verify the extension has site access for that origin. |
For detailed setup, production deployment, and advanced usage patterns, see the Running & Usage Guide.
| Component | Status |
|---|---|
| Protocol & Envelope | Complete |
| Web SDK (ArlopassClient) | Complete |
| React SDK (@arlopass/react) | Complete |
| Policy Engine | Complete |
| Audit & Telemetry | Complete |
| Adapter Runtime | Complete |
| Ollama Adapter | Complete |
| Claude Adapter | Complete |
| OpenAI Adapter | Complete |
| Gemini Adapter | Complete |
| Perplexity Adapter | Complete |
| Amazon Bedrock Adapter | Complete |
| Google Vertex AI Adapter | Complete |
| Azure AI Foundry Adapter | Complete |
| CLI Bridge Adapter | Complete |
| Bridge Daemon | Complete |
| Wallet Extension | Complete |
| Examples App | Complete |