Laan Tungir 372339aa35 v0.0.12 - MCP server: 100 tools, Streamable HTTP transport, favicons, refresh button, webview sizing fix
- MCP protocol compliance: ping, resources/list, prompts/list, logging/setLevel, 202 notifications
- Screenshot tool: WebKit snapshot to PNG to base64 MCP image content
- Session management: Mcp-Session-Id header, SSE response format, GET/DELETE endpoints
- Phase 3: 70 new tools across 8 batches (extended interaction, get/state, find elements, wait/batch, cookies/storage, mouse/clipboard/settings, frames/dialogs/debug, complex)
- Favicon support: enabled WebKitFaviconDatabase, notify::favicon signal handler
- Tab UI: favicons in tab labels, evenly distributed tabs, immediate title from URL host
- Refresh button: left-click reload, right-click hard reload menu (bypass cache, clear site data)
- Webview sizing fix: gtk_widget_set_vexpand/hexpand to prevent 1px height blank page
- Updated Roo Code MCP config (100 tools in alwaysAllow)
- Updated plans: mcp-server.md, agent-tools.md, phase3-tools.md
2026-07-12 09:20:14 -04:00

sovereign_browser

A Linux x86 web browser built in C99 on WebKitGTK, designed around sovereign identity instead of the traditional web's permissioned infrastructure.

The thesis: the browser's security model (DNS/domains, TLS/CAs, same-origin policy, CORS, cookie sandboxing) is what forces you to rely on permissioned domains, certificate authorities, and centralized account systems. By deprecating that model and replacing it with Nostr identity and FIPS mesh transport, you get a browser that's more capable, not less safe — because trust moves to the layer where it belongs: your keys.

"Not your keys, not your browser." Walk up to a computer with your Nostr identity (via n_signer) and the browser is yours — your identity, your relays, your mesh.

Goals

  1. A real browser. Loads any normal HTTP/HTTPS page via WebKitGTK.
  2. FIPS addresses are first-class. http://<npub>.fips/ and fips:// resolve over the FIPS mesh, not DNS/IP. Reach any FIPS node by its Nostr npub, no domain, no public IP, no TLS cert.
  3. Built-in Nostr signing. The browser injects window.nostr (the nos2x surface) into every page, backed by n_signer — a foreground, RAM-only, human-attended signing program. The browser never holds your private key; every signature is approved at the signer's terminal.
  4. Deprecated web security, deliberately. Same-origin policy, CORS, and certificate enforcement are stripped so pages (and the agent runtime to come) can freely call any endpoint — including FIPS mesh services — without the workarounds traditional browsers force on automators.

Non-goals (for now)

  • Agent integration, multi-window agent hosts, didactyl hosting, and the broader "browser as agent runtime" vision are documented in docs/architecture.md and the linked plans, but not in scope for the first build. First: a usable browser with basic Nostr signing. Then the rest.

Current status

Working browser: a C99 + WebKitGTK window with multi-tab support, a URL bar per tab, Nostr login, and window.nostr injection. Verified loading https://laantungir.net cleanly. See docs/webkit-poc-findings.md for the friction report from the POC phase (and the Servo fallback exploration).

[loaded] https://laantungir.net/ -- title: Laan Tungir

Build

Requires Debian 13 (trixie) or similar with WebKitGTK 4.1 dev headers:

sudo apt install libwebkit2gtk-4.1-dev
make
./sovereign_browser [url]

Architecture (summary)

┌─────────────────────────────────────────────────────┐
│ sovereign_browser host (C99)                        │
│  ┌─────────┐  ┌──────────┐  ┌────────────────────┐  │
│  │ UI /    │  │ Request  │  │ Nostr signer shim  │  │
│  │ tabs    │  │ router   │  │ (nostr_core_lib →  │  │
│  │ URL bar │  │          │  │  n_signer socket)  │  │
│  └─────────┘  └────┬─────┘  └─────────┬──────────┘  │
│                    │                   │             │
│         ┌──────────┼───────────┬───────┘             │
│         ▼          ▼           ▼                     │
│   http/https    fips://     nostr://                 │
│   (WebKit net)  (FIPS TUN)  (relays)                 │
└─────────────────────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────────────────────┐
│ WebKitGTK (system lib, ~35 MB)                      │
│  Blink-grade renderer + V8 + libsoup network stack  │
└─────────────────────────────────────────────────────┘

Full architecture, engine comparison, and roadmap in docs/architecture.md.

Custom URI scheme layer

The browser registers custom URI schemes via webkit_web_context_register_uri_scheme(). This is the network/content layer — it controls what bytes get loaded into the web view. One infrastructure, multiple uses:

Scheme Purpose Status
sovereign://nostr/* window.nostr bridge — web pages call fetch('sovereign://nostr/signEvent') to sign via the C-side nostr_signer_t Planned
sovereign://settings Browser-internal pages (like chrome://settings) Planned
fips:// / *.fips Route to FIPS mesh nodes via TUN interface Planned
nostr:// Fetch Nostr events from relays, render as HTML Planned

A WebKitWebExtension (separate .so loaded into the web process) will be added later for the script manipulation layer — security stripping (CORS/SOP removal), synchronous NIP-07 calls, and content injection. The URI scheme and WebExtension serve different layers and will coexist. See plans/nostr-login-integration.md for the full decision rationale.

Nostr login

Login is a native GTK dialog (not a web page) that calls nostr_core_lib directly. Supported methods:

Method nostr_core_lib API
Local key (nsec) nostr_signer_local(), nostr_decode_nsec()
Seed phrase (BIP-39) nostr_derive_keys_from_mnemonic()
Read-only (npub) nostr_decode_npub()
NIP-46 remote signer nostr_nip46_client_session_init()
n_signer hardware nostr_signer_nsigner_serial/unix/tcp/qrexec() + nostr_signer_nsigner_set_nostr_index()

See plans/nostr-login-integration.md for the full implementation plan.

Browser tabs

The browser supports multiple tabs via a GtkNotebook. Each tab has its own toolbar (hamburger menu + URL entry) and WebKitWebView. All tabs share a single WebKitWebContext, so the sovereign:// Nostr bridge, security settings, and TLS policy apply to every tab automatically.

Tab features:

  • New tab: Ctrl+T or the + button at the end of the tab strip
  • Close tab: Ctrl+W, per-tab close button, or middle-click on the tab label
  • Switch tabs: Ctrl+Tab / Ctrl+Shift+Tab, Ctrl+PageUp / Ctrl+PageDown
  • Focus URL bar: Ctrl+L
  • Right-click tab context menu: New Tab, Close Tab, Close Other Tabs, Close Tabs to the Right, Duplicate Tab, Reload Tab
  • Drag tabs to reorder
  • Tab titles update from page load
  • Session save/restore: open tabs are saved on exit and restored on next launch (configurable in Settings)

Settings dialog (hamburger menu → Settings…):

  • Restore session on startup (default: on)
  • New tab URL (default: https://example.com)
  • Tab bar position: Top / Bottom / Left / Right (default: Top)
  • Show tab close buttons (default: on)
  • Middle-click to close tab (default: on)
  • Ctrl+Tab to switch tabs (default: on)
  • Maximum tabs (default: 50)
  • Allow drag to reorder tabs (default: on)

Settings are persisted to ~/.sovereign_browser/settings.conf. Session state is saved to ~/.sovereign_browser/session.txt.

See plans/browser-tabs.md for the full implementation plan.

Agent tools

The browser embeds a WebSocket server (using libsoup) that allows external AI agents to control the browser programmatically. Connect to ws://localhost:17777/agent and send JSON tool commands.

The server starts before the login dialog and remains available throughout the browser's lifecycle. The browser starts normally with the GTK login dialog — no blocking wait. An agent can log in at any time: while the dialog is showing, or after the browser is already running. If an agent logs in while the dialog is open, the agent's login takes priority.

Login tools (available before login):

  • login_status — check if logged in
  • login — authenticate with method: local (nsec), seed (BIP-39 mnemonic), readonly (npub), nip46 (bunker:// URL), or nsigner (hardware signer via serial/unix/tcp/qrexec transport)
  • logout — clear signer and reset state
  • switch_identity — change identity (same params as login)

Browser tools (available after login):

  • Navigation: open, back, forward, reload, get_url, get_title
  • Inspection: snapshot (accessibility tree with element refs), get_text, get_html, get_attr, eval (run JavaScript)
  • Interaction: click, fill, type, press, scroll, hover, focus, close
  • Tabs: tab_list, tab_new, tab_switch, tab_close
  • Wait: wait (ms), wait_for (selector)

Snapshot + ref workflow (same pattern as agent-browser):

# Using websocat (cargo install websocat)
# 1. Login
echo '{"id":1,"tool":"login","params":{"method":"readonly","npub":"npub1..."}}' | websocat ws://localhost:17777/agent

# 2. Open a page
echo '{"id":2,"tool":"open","params":{"url":"https://example.com"}}' | websocat ws://localhost:17777/agent

# 3. Snapshot — get accessibility tree with refs
echo '{"id":3,"tool":"snapshot","params":{"interactive":true}}' | websocat ws://localhost:17777/agent

# 4. Click by ref
echo '{"id":4,"tool":"click","params":{"ref":"@e2"}}' | websocat ws://localhost:17777/agent

HTTP status endpoint: curl http://localhost:17777/ returns server status (running, port, client count, logged in).

Agent settings (in Settings dialog or ~/.sovereign_browser/settings.conf):

  • agent_server_enabled (default: true)
  • agent_server_port (default: 17777)
  • agent_allowed_origins (default: *)
  • agent_login_timeout_ms (default: 30000)

See plans/agent-tools.md for the full implementation plan and tool comparison with agent-browser.

Roadmap

  1. Base browser (WebKitGTK + C99, loads pages)
  2. Browser tabs (GtkNotebook, per-tab toolbar, session restore, settings)
  3. Agent tools Phase 1 (WebSocket server, login tools, 31 browser automation tools)
  4. Nostr login (GTK dialog → nostr_core_lib → nostr_signer_t)
  5. window.nostr injection (sovereign:// URI scheme bridge)
  6. Security strip (disable SOP/CORS, accept any cert, shared context)
  7. FIPS URI scheme (fips:// / *.fips via WebKitGTK scheme handler)
  8. nostr:// content scheme
  9. Agent tools Phase 2 (refinements) and Phase 3 (extended tool catalog)
  10. Future: agent runtime (didactyl hosting), multi-window, FIPS-distributed

License

MIT (to match nostr_core_lib / n_signer / didactyl).

S
Description
No description provided
Readme
262 MiB
v0.0.62
Latest
2026-07-29 14:41:13 +00:00
Languages
C 77.5%
JavaScript 11.6%
HTML 4.1%
Shell 3.7%
CSS 2.6%
Other 0.5%