The TLSNotary clients — a Chrome extension and a native mobile app (iOS + Android) that generate cryptographic proofs of API responses — plus a plugin SDK, a shared plugin registry, and a verifier server.
Built on the TLSNotary protocol (the core MPC-TLS Rust implementation lives in that repo; this repo consumes it via tlsn-wasm and the native mobile prover).
Important
When running a client against a notary/verifier server, ensure the server's version matches the version of the client.
- Clients
- Demo
- Tutorial
- Monorepo Structure
- Architecture Overview
- Getting Started
- Development
- Production Build & Publishing
- End-to-End Testing
- Websockify Integration
- Building Plugins with Claude Code
- Resources
- License
This monorepo ships two TLSNotary clients that share one plugin system, one plugin registry (@tlsn/plugins), and the same verifier server:
| Client | Where | Platforms | Prover |
|---|---|---|---|
| Browser extension | packages/extension |
Chrome / Chromium (MV3) | WASM (tlsn-wasm) in an offscreen document |
| Mobile app | app/mobile |
iOS + Android | Native Rust prover (packages/tlsn-mobile) via UniFFI |
Both run the same JavaScript plugins (sandboxed in QuickJS WASM on the extension; evaluated with new Function() under Hermes on mobile), capture auth from a logged-in session, and produce selectively-disclosed proofs against a verifier server.
Browser extension — try TLSNotary live at demo.tlsnotary.org: install the extension and run any of the bundled plugins against the hosted verifier.
To run the extension demo locally (verifier + demo site via Docker):
npm run docker:up # verifier on :7047, demo site on :80
npm run docker:downOr serve just the demo site against your own verifier:
npm run demo # http://localhost:8080Mobile app — build and launch on a simulator/emulator or device:
npm run mobile:ios # build deps + native libs + launch iOS
npm run mobile:android # build deps + native libs + launch AndroidThe mobile app presents a plugin gallery (Swiss Bank, Spotify, Duolingo, Discord — work-in-progress plugins appear behind the Debug toggle), lets the user log in via an embedded WebView, and generates proofs with the native prover. See app/mobile/README.md for the full toolchain and build pipeline.
The extension demo uses .env files for configuration:
.env- Local development defaults (localhost:7047).env.production- Production settings (demo.tlsnotary.org, SSL enabled)
For Docker deployments, override via environment variables:
# Local development (default)
npm run docker:up
# Production with custom verifier
VITE_VERIFIER_HOST=verifier.example.com VITE_SSL=true docker compose up --buildFor the mobile app, point plugins at a remote verifier by rebuilding them with MOBILE_VERIFIER_URL (see app/mobile/README.md).
Want to write your own plugin? The tutorial package is an interactive 15-30 minute, hands-on walkthrough of building TLSNotary plugins — starting from a working Twitter plugin, then adapting it for a Swiss Bank balance proof (choosing what to reveal vs. redact). An optional "fool the verifier" challenge shows why careful server-side verification matters.
npm run tutorial
# Open http://localhost:8080 in your browserThis repository is an npm workspaces monorepo (packages/* and app/*) plus a Rust Cargo workspace (servers/):
tlsn-extension/
├── packages/ # npm workspaces (TypeScript)
│ ├── extension/ # Chrome Extension (Manifest V3) — browser client
│ ├── plugin-sdk/ # SDK for developing/running TLSN plugins (QuickJS sandbox)
│ ├── plugins/ # Shared plugins + registry, built for demo (browser) and mobile (Hermes)
│ ├── common/ # Shared utilities (logging system)
│ ├── demo/ # Extension demo frontend + Docker setup
│ ├── tutorial/ # Tutorial examples for plugin development
│ ├── eas-webhook/ # Demo service: turns verifier webhooks into EAS attestations
│ ├── tlsn-mobile/ # Native Rust prover for mobile (iOS .xcframework + Android .so via UniFFI)
│ ├── tlsn-wasm/ # Local TLSN WebAssembly build helper (optional)
│ ├── tlsn-wasm-pkg/ # Output of the local WASM build (gitignored)
│ └── ts-plugin-sample/ # Minimal TypeScript plugin sample
│
├── app/ # npm workspaces (applications)
│ └── mobile/ # React Native / Expo app — iOS + Android client
│ ├── app/ # Expo Router screens (plugin gallery + runner)
│ ├── components/tlsn/ # WebView login, native prover bridge, plugin renderer
│ ├── modules/ # Expo native modules: tlsn-native (prover), quickjs-native
│ └── build.sh # Unified build script (JS deps + native libs + run)
│
├── servers/ # Rust Cargo workspace (deployable servers)
│ ├── verifier/ # WebSocket server for TLSNotary verification (:7047)
│ └── swissbank/ # Fake Swiss bank with dashboard UI (demo target, :3000)
│
├── package.json # Root npm workspace configuration
└── README.md
The browser client. Key features:
- Multi-Window Management: Track multiple browser windows with request interception
- Request Interception: Capture HTTP/HTTPS requests from managed windows
- Plugin Execution: Run sandboxed JavaScript plugins using QuickJS (in an offscreen document)
- TLSN Overlay: Visual display of intercepted requests
Entry points: Background (service worker), Content (page injection + overlay), Popup, and Offscreen (DOM operations + WASM prover).
React Native / Expo client with a native Rust prover. Key features:
- Plugin gallery: Select a plugin, log in via embedded WebView, generate a proof
- Native prover: Rust (
packages/tlsn-mobile) bridged via UniFFI — Swift/XCFramework on iOS, Kotlin/.soon Android - Plugin execution: Plugin JS is evaluated with
new Function()under Hermes via the plugin SDK'sNativeFunctionEvaluator(a vendored native QuickJS module exists inmodules/quickjs-nativebut is not currently in the plugin execution path)
See app/mobile/README.md for prerequisites, the build pipeline, and architecture.
Single source of truth for plugin code and metadata, consumed by both clients:
- Plugin sources in
src/*.plugin.tsand a sharedsrc/registry.ts(per-pluginplatforms: ('demo' | 'mobile')[]) build.jsproduces two targets:dist/demo/(browser bundle for the extension) anddist/mobile/(Hermes-compatiblees2016, noasync/awaitin dynamically-evaluated code)
SDK for developing and running TLSN plugins with QuickJS sandboxing:
- Secure JavaScript execution in an isolated environment
- Host capability system for controlled plugin access
- React-like hooks:
useHeaders(),useRequests(),useEffect(),useState(),setState() - Isomorphic package for Node.js and browser environments, with full TypeScript declarations
Centralized logging system used across packages (DEBUG/INFO/WARN/ERROR, timestamped output, singleton).
Rust prover compiled for mobile and bridged via UniFFI:
- iOS: static library packaged as
TlsnMobile.xcframework+ Swift bindings (build-ios.sh) - Android: shared library
.so+ Kotlin bindings (build-android.sh)
Built automatically by app/mobile/build.sh; only rebuild when changing the Rust code.
Rust HTTP/WebSocket server for TLSNotary verification (shared by both clients):
GET /health,WS /session,WS /verifier?sessionId=<id>,WS /proxy?token=<host>(compatible with notary.pse.dev)- Webhook API for POST notifications, YAML config (
config.yaml), CORS enabled - Runs on
localhost:7047by default
React + Vite frontend (with Docker Compose: verifier + nginx) that drives the extension against the bundled plugins.
Receives verifier webhooks and creates EAS attestations on Sepolia testnet. Demo-only; see packages/eas-webhook/README.md.
The extension depends on the published tlsn-wasm npm package by default. For local development against an unreleased tlsn revision, packages/tlsn-wasm/build.sh clones the tlsn repo and builds packages/tlsn-wasm-pkg/ (gitignored). Run npm link from there and npm link tlsn-wasm inside packages/extension to override the published package.
Both clients run the same plugins and talk to the same verifier; they differ only in how the plugin sandbox and the prover are hosted.
The extension uses a message-passing architecture with five entry points:
┌───────────────────────────────────────────────────────────────┐
│ Browser Extension │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Background │◄────►│ Content │◄──── Page Scripts │
│ │ (SW) │ │ Script │ │
│ └──────┬───────┘ └──────────────┘ │
│ │ │
│ ├─► Window Management (WindowManager) │
│ ├─► Request Interception (webRequest API) │
│ ├─► Session Management (SessionManager) │
│ └─► Message Routing │
│ │
│ ┌──────────────┐ │
│ │ Offscreen │ ← QuickJS plugin sandbox + WASM prover │
│ └──────────────┘ │
└───────────────────────────────────────────────────────────────┘
│
▼
┌──────────────┐
│ Verifier │
│ (localhost: │
│ 7047) │
└──────────────┘
Opening a managed window:
Page → window.tlsn.open(url)
↓ window.postMessage(TLSN_OPEN_WINDOW)
Content Script → browser.runtime.sendMessage(OPEN_WINDOW)
Background → WindowManager.registerWindow() → browser.windows.create()
Request interception:
Browser → HTTP request in managed window
↓ webRequest.onBeforeRequest
Background → WindowManager.addRequest()
↓ browser.tabs.sendMessage(UPDATE_TLSN_REQUESTS)
Content Script → Update TLSN overlay UI
┌──────────────────────────────────────────────────────────────┐
│ Mobile App (Expo / RN, Hermes) │
│ │
│ PluginScreen ──► MobilePluginHost (runs plugin JS) │
│ │ │ │
│ │ openWindow() │ prove() │
│ ▼ ▼ │
│ PluginWebView NativeProver ──► Rust prover (UniFFI) │
│ (login + cookie/ (Swift / Kotlin) packages/tlsn-mobile │
│ header capture) │
└──────────────────────────────────────────────────────────────┘
│ MPC-TLS over WebSocket
▼
┌──────────────┐
│ Verifier │ (localhost:7047;
│ │ 10.0.2.2 on Android emulator)
└──────────────┘
See app/mobile/README.md for the full plugin flow and native-bridge details.
- Node.js >= 18
- Rust (for the verifier server and the native mobile prover) — install from rustup.rs
- Chrome/Chromium browser
- iOS: Xcode (+ iOS simulator), CocoaPods
- Android: Android Studio (SDK, emulator, JDK) and the Android NDK
- Expo / EAS tooling (used via
npx)
Rust cross-compilation targets, cargo-ndk, and the tlsn repo are auto-installed by app/mobile/build.sh. See app/mobile/README.md for the full tables and environment setup.
git clone https://github.com/tlsnotary/tlsn-extension.git
cd tlsn-extension
npm installThis installs dependencies for all workspaces and sets up package links.
Both clients need a verifier. Run it in a separate terminal:
cd servers
cargo run -p tlsn-verifier-server # http://localhost:7047Verifier API endpoints:
GET /health- Health checkWS /session- Create new verification sessionWS /verifier?sessionId=<id>- WebSocket verification endpointWS /proxy?token=<host>- WebSocket proxy for TLS connections (compatible with notary.pse.dev)
Webhook configuration — configure servers/verifier/config.yaml to receive POST notifications after successful verifications:
webhooks:
'api.x.com':
url: 'https://your-backend.example.com/webhook/twitter'
headers:
Authorization: 'Bearer your-secret-token'
'*': # Wildcard for unmatched server names
url: 'https://your-backend.example.com/webhook/default'npm run dev # builds deps, then webpack-dev-server on :3000 (HMR)Then load it in Chrome:
- Navigate to
chrome://extensions/ - Enable "Developer mode" (top right)
- Click "Load unpacked" and select
packages/extension/build/
The extension auto-reloads on file changes (manual refresh needed for manifest changes).
Package-specific scripts:
cd packages/extension
npm run dev | test | test:watch | test:coverage | lint | lint:fixnpm run mobile:ios # build deps + native libs + launch iOS
npm run mobile:android # build deps + native libs + launch AndroidOr run the full pipeline from app/mobile/ with options (--no-run, --skip-deps, --rebuild-native, --clean):
cd app/mobile
./build.sh ios
./build.sh androidNotes:
- The verifier at
localhost:7047is reachable as-is on the iOS simulator; on the Android emulator the app rewriteslocalhostto10.0.2.2. - The app uses native modules, so use
expo run:ios/expo run:android(viabuild.sh) — not Expo Go. - Plugin code runs under Hermes, which can't parse
async/awaitin dynamically-evaluated code; mobile plugins are compiled toes2016. If you see "async functions are unsupported", rebuild plugins:npm run build:plugins.
See app/mobile/README.md for emulator clock sync, native logs, and troubleshooting.
Plugins live in packages/plugins and are built for both clients:
npm run build:plugins # writes dist/demo (browser) and dist/mobile (Hermes)From the repository root:
NODE_ENV=production npm run buildThis builds dependencies, builds the extension with production optimizations, and creates packages/extension/zip/extension-{version}.zip (ready for the Chrome Web Store).
The easiest way to install the extension is from the Chrome Web Store. For the full release process (versioning, CI, store upload), see RELEASING.md.
Mobile builds and submissions run on EAS (Expo Application Services). In short:
cd app/mobile
npx eas-cli build --profile production --platform all
npx eas-cli submit --profile production --platform allFor versioning (note the mobile-specific 0.1.AABB scheme), credentials, and store promotion, see app/mobile/RELEASING.md.
cd servers
cargo build --release -p tlsn-verifier-server # binary in servers/target/release/To test the complete TLSN workflow with the extension:
-
Start the verifier and confirm it's up:
cd servers && cargo run -p tlsn-verifier-server curl http://localhost:7047/health # → ok
-
Start the extension in dev mode (
npm run dev) and loadpackages/extension/build/in Chrome. -
Run a test plugin via the demo:
npm run demo # http://localhost:8080Select a plugin; it opens a managed window to the target site, intercepts requests, connects to the verifier, shows a progress overlay, and runs the proof.
For the mobile end-to-end flow, start the verifier as above, then npm run mobile:ios / npm run mobile:android and run a plugin from the gallery.
- Background service worker logs:
chrome://extensions/→ Extension Details → "Inspect views: service worker" - Multiple windows: the extension supports up to 10 concurrent managed windows
- Mobile native logs:
xcrun simctl spawn booted log stream | grep -i tlsn(iOS) oradb logcat | grep -i tlsn(Android) - Verifier connection: ensure the verifier is reachable before running proofs
For WebSocket proxying of TLS connections (optional):
git clone https://github.com/novnc/websockify && cd websockify
./docker/build.sh
# For X.com
docker run -it --rm -p 55688:80 novnc/websockify 80 api.x.com:443This proxies HTTPS connections through WebSocket for browser-based TLS operations.
This repo includes a Claude Code slash command that scaffolds TLSNotary plugins interactively — API discovery, auth interception strategy, and a complete plugin file added to packages/plugins (usable by both clients).
# Add the TLSNotary marketplace
/plugin marketplace add tlsnotary/tlsn-extension
# Install the create-plugin command
/plugin install tlsn-create-plugin@tlsnotary/create-plugin Garmin Connect badges
/create-plugin Reddit karma score
/create-plugin GitHub contribution countSee PLUGIN.md for the plugin architecture, capabilities, and authoring guide.
- TLSNotary Documentation
- Chrome Extension Documentation · Manifest V3 · webextension-polyfill
- Expo Documentation · React Native · EAS Build
- App Store Connect · Google Play Console
This repository is licensed under either of:
at your option.