2026-09-08 11:59:44 +02:00
<!doctype html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< title > theseus.x — Extensions< / title >
< meta name = "description" content = "Signed over-the-air update endpoint for Theseus's bundled add-ons. Each entry is Ed25519-signed by the Silent Mode operator; verified on every install without waiting for a Theseus release." >
< link rel = "icon" href = "/assets/favicon.svg" type = "image/svg+xml" >
< link rel = "mask-icon" href = "/assets/favicon.svg" color = "#d6ff3d" >
< meta property = "og:type" content = "website" >
< meta property = "og:site_name" content = "theseus.x" >
< meta property = "og:title" content = "theseus.x — Extensions" >
< meta property = "og:description" content = "Signed OTA update endpoint for Theseus's bundled add-ons. Ed25519, no cert authority, no app-store gatekeeper." >
< meta property = "og:url" content = "https://theseus.x/extensions/" >
< style >
:root{
--bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
--ok:#4fd1a5;
}
*{box-sizing:border-box}
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh}
a{color:var(--acid)}
.wrap{max-width:900px;margin:0 auto;padding:0 1.2rem}
.topnav{position:sticky;top:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
padding:10px 1.2rem;background:rgba(11,14,20,.82);backdrop-filter:blur(10px);
border-bottom:1px solid var(--line)}
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;letter-spacing:.2px;display:flex;align-items:center;gap:8px}
.topnav .brand .g{color:var(--acid)}
.topnav .brand svg{width:20px;height:20px}
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px}
.topnav a:hover{color:var(--ink);background:var(--panel)}
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
header.hero{text-align:center;padding:3.5rem 1.2rem 1rem}
h1{font-size:clamp(1.8rem,4.5vw,2.4rem);margin:.6rem 0 .3rem;letter-spacing:-.3px}
h1 .g{color:var(--acid)}
.tag{color:var(--mut);font-size:1.02rem;max-width:640px;margin:0 auto}
section{padding:2rem 0;border-top:1px solid var(--line);margin-top:1.6rem}
section:first-of-type{border-top:none;margin-top:1rem}
h2{font-size:1.35rem;margin:0 0 .5rem}
.lede{color:var(--mut);margin:0 0 1.2rem;max-width:720px}
code,.mono{background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-family:ui-monospace,monospace;font-size:13px}
pre{background:#0e131b;border:1px solid var(--line);border-radius:10px;padding:12px 14px;overflow-x:auto;
font-family:ui-monospace,monospace;font-size:12.5px;color:var(--ink);margin:.8rem 0}
.ext{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:20px 22px;margin:1rem 0}
.ext h3{margin:0 0 .3rem;font-size:1.15rem;display:flex;align-items:center;gap:10px}
.ext h3 .icon{font-size:1.4rem}
.ext .cur{color:var(--acid);font-size:12px;font-weight:600;letter-spacing:.14em;text-transform:uppercase}
.ext .desc{color:var(--mut);font-size:14px;margin:.3rem 0 .8rem}
.ext .verifybox{margin-top:.9rem;padding-top:.8rem;border-top:1px solid var(--line);font-size:11.5px;color:var(--dim)}
.ext .verifybox .lbl{color:var(--mut);font-size:12px;margin-bottom:6px}
.ext .h{display:flex;gap:8px;flex-wrap:wrap;align-items:baseline;margin-top:4px}
.ext .h b{color:var(--mut);font-weight:600;min-width:70px}
.ext .h code{font-family:ui-monospace,monospace;font-size:10.5px;color:#c9d4e3;word-break:break-all;background:transparent;border:none;padding:0}
.ext .meta{color:var(--dim);font-size:12.5px;margin-top:.4rem}
.note{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--acid);
border-radius:10px;padding:14px 18px;color:var(--mut);font-size:14px;margin:1.4rem 0}
.note b{color:var(--ink)}
.pubkey{background:#0e131b;border:1px solid var(--line);border-radius:8px;padding:10px 12px;
font-family:ui-monospace,monospace;font-size:11px;color:#c9d4e3;word-break:break-all;margin:.6rem 0}
.flow{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px 20px;margin-top:1rem;color:var(--mut);font-size:14px}
.flow ol{margin:0;padding-left:20px}
.flow li{margin:.4rem 0}
.flow b{color:var(--ink)}
footer{color:var(--dim);font-size:12.5px;margin:3rem 0 2rem;text-align:center}
footer a{color:var(--mut)}
< / style >
< / head >
< body >
< nav class = "topnav" >
< a class = "brand" href = "/" >
< svg viewBox = "0 0 64 64" aria-hidden = "true" >
< rect width = "64" height = "64" rx = "12" fill = "#0b0e14" / >
< path d = "M32 6 L38 32 L26 32 Z" fill = "#e04e4e" / >
< path d = "M38 32 L32 58 L26 32 Z" fill = "#d6ff3d" / >
< path d = "M6 32 L32 27 L58 32 L32 37 Z" fill = "#d6ff3d" opacity = ".55" / >
< circle cx = "32" cy = "32" r = "3" fill = "#0b0e14" / >
< / svg >
< span > theseus< span class = "g" > .x< / span > < / span >
< / a >
< a href = "/" > Home< / a >
< a href = "/#download" > Download< / a >
< a class = "here" href = "./" > Extensions< / a >
< a href = "https://sirius.x/" > sirius.x< / a >
< / nav >
< header class = "hero" >
< h1 > Theseus < span class = "g" > Extensions< / span > < / h1 >
< p class = "tag" > Signed over-the-air update endpoint for Theseus's bundled add-ons.
Every entry is Ed25519-signed by the Silent Mode operator, verified on the
device before install. No cert authority, no app-store gatekeeper.< / p >
< / header >
< div class = "wrap" >
< section >
< h2 > Available extensions< / h2 >
2026-09-20 14:39:07 +02:00
< p class = "lede" > What ships inside Theseus today. Versions and hashes on this page are read from each
add-on's signed < code > updates.json< / code > when the page loads, so they match what the browser
would install. First-party components show up under < b > Settings › Plug-ins< / b > in Theseus,
everything else under < b > Settings › Extensions< / b > .< / p >
2026-09-08 11:59:44 +02:00
2026-09-20 14:39:07 +02:00
< div class = "ext" id = "aegis" data-ext = "aegis" >
< h3 > < span class = "icon" > 🛡️< / span > Aegis < span class = "cur" style = "margin-left:auto" > current < span data-live = "version" > 0.6.21< / span > < / span > < / h3 >
< div class = "desc" > Multi-chain wallet (BCH, BTC, TRX, ETH, SOL, SC, DGB) derived from your Theseus vault, with
a dApp bridge for the pages you visit. Bundled; updates over this signed channel and through the
panel's own "Stage → Restart" flow.< / div >
< div class = "meta" > Plug-in · Settings › Plug-ins · < span data-live = "count" > < / span > < / div >
< div class = "verifybox" >
< div class = "lbl" > Signed update manifest — SHA-256 verified before install< / div >
< div class = "h" > < b > updates.json< / b > < code > < a href = "./aegis/updates.json" > theseus.x/extensions/aegis/updates.json< / a > < / code > < / div >
< div class = "h" > < b > Tarball< / b > < code > < a data-live = "url" href = "./aegis/aegis-0.6.21.tar.gz" > aegis-0.6.21.tar.gz< / a > < / code > < / div >
< div class = "h" > < b > sha256< / b > < code data-live = "sha256" > —< / code > < / div >
< / div >
< / div >
< div class = "ext" id = "screenshot" data-ext = "screenshot" >
< h3 > < span class = "icon" > 📸< / span > Screenshot < span class = "cur" style = "margin-left:auto" > current < span data-live = "version" > 0.6.5< / span > < / span > < / h3 >
2026-09-08 11:59:44 +02:00
< div class = "desc" > Capture the current tab — visible viewport, entire scrollable page, or a rectangle
2026-09-20 14:39:07 +02:00
you draw. The capture opens in a full-tab editor: crop, annotate, line tool, resizable text,
redact, save.< / div >
< div class = "meta" > Extension · Settings › Extensions · < span data-live = "count" > < / span > < / div >
2026-09-08 11:59:44 +02:00
< div class = "verifybox" >
< div class = "lbl" > Signed update manifest — SHA-256 verified before install< / div >
2026-09-20 14:39:07 +02:00
< div class = "h" > < b > updates.json< / b > < code > < a href = "./screenshot/updates.json" > theseus.x/extensions/screenshot/updates.json< / a > < / code > < / div >
< div class = "h" > < b > Tarball< / b > < code > < a data-live = "url" href = "./screenshot/screenshot-0.6.5.tar.gz" > screenshot-0.6.5.tar.gz< / a > < / code > < / div >
< div class = "h" > < b > sha256< / b > < code data-live = "sha256" > 87ae730d329ff9f552bbf513efba19bd14bb016bb90e24f7b62868434dadda60< / code > < / div >
2026-09-08 11:59:44 +02:00
< / div >
< / div >
2026-09-20 14:39:07 +02:00
< div class = "ext" id = "notepad" >
< h3 > < span class = "icon" > 📝< / span > Notepad < span class = "cur" style = "margin-left:auto" > bundled 0.1.0< / span > < / h3 >
< div class = "desc" > Right-sidebar notes. Text lives on this machine only and autosaves as you type.< / div >
< div class = "meta" > Extension · Settings › Extensions · no update channel yet — ships with each Theseus release.< / div >
< / div >
< div class = "note" > < b > Installing something else.< / b > An extension is a folder with an < code > addon.json< / code > .
Drop it into the extensions directory (Settings › Extensions › < i > Open extensions folder< / i > ), press
< i > Reload< / i > , and it is live. Extensions run with full app access — treat one like an unsigned executable
and load only what you trust.< / div >
2026-09-08 11:59:44 +02:00
< / section >
2026-09-20 14:39:07 +02:00
< script >
// Fill each card from its signed manifest. Relative URLs keep this working on
// every origin the page is served from (navigate.st relay, bns:// in Theseus).
(async () => {
for (const card of document.querySelectorAll(".ext[data-ext]")) {
const id = card.dataset.ext;
try {
const r = await fetch("./" + id + "/updates.json", { cache: "no-store" });
if (!r.ok) continue;
const m = await r.json();
const list = (m.addons || []).slice().sort((x, y) => cmp(y.version, x.version));
const top = list[0]; if (!top) continue;
const set = (k, f) => card.querySelectorAll('[data-live="' + k + '"]').forEach(f);
set("version", (el) => { el.textContent = top.version; });
set("sha256", (el) => { el.textContent = top.sha256 || "—"; });
set("url", (el) => { el.href = top.url; el.textContent = String(top.url).split("/").pop(); });
set("count", (el) => { el.textContent = list.length + " signed version" + (list.length === 1 ? "" : "s") + " on the channel"; });
} catch {}
}
function cmp(a, b) { const x = String(a).split(".").map(Number), y = String(b).split(".").map(Number); for (let i = 0; i < Math.max ( x . length , y . length ) ; i + + ) { const d = (x[i] | | 0 ) - ( y [ i ] | | 0 ) ; if ( d ) return d ; } return 0 ; }
})();
< / script >
2026-09-08 11:59:44 +02:00
< section >
< h2 > How updates work< / h2 >
< p class = "lede" > Same mechanism a Firefox XPI update uses, cut down to what a name-native browser needs.< / p >
< div class = "flow" >
< ol >
< li > Every 30 seconds after boot Theseus fetches < code > updates.json< / code > for each installed add-on that declares an < code > updateURL< / code > in its manifest.< / li >
< li > Each entry carries an Ed25519 signature over < code > silentmode.addon-update-v1|< id> |< version> |< sha256> < / code > . Theseus verifies against a small set of operator public keys baked into the build. Unsigned or badly-signed entries are dropped silently.< / li >
< li > If a signed version beats what's installed, Theseus downloads the tarball, re-checks its sha256, and stages the new copy under < code > < userData> /addons-updates-staged/< id> -< version> /< / code > .< / li >
< li > On the next Theseus launch, < code > promoteStagedUpdates< / code > moves the staged copy into < code > addons/< id> /< / code > . Any prior copy is renamed to < code > addons-backups/< id> -< oldver> -< timestamp> /< / code > so hand-edits survive.< / li >
2026-09-20 14:39:07 +02:00
< li > Settings › Extensions has a < b > Check for updates< / b > button and shows what is staged; first-party plug-ins (Aegis) can also stage and restart from their own panel.< / li >
2026-09-08 11:59:44 +02:00
< / ol >
< / div >
< / section >
< section >
< h2 > Operator key< / h2 >
< p class = "lede" > The Ed25519 public key baked into Theseus 0.3.19+.
Rotation is by adding a new pubkey and shipping a Theseus release that carries both, then a follow-up release removing the old — during the overlap, entries can be signed by either.< / p >
< div class = "pubkey" > 732b1263a236b0030383a2376597cfa43c3624b3ca2912a46134f8f2a06e6012< / div >
< p style = "color:var(--dim);font-size:12.5px;margin-top:.6rem" > Generated 2026-09-07. Held offline by the Silent Mode operator.< / p >
< / section >
< section >
< h2 > Roadmap< / h2 >
< p class = "lede" > The endpoint is generic — any bundled add-on can advertise an < code > updateURL< / code > .
Concrete next-steps:< / p >
< ul style = "color:var(--mut);font-size:14px;line-height:1.7" >
< li > On-BCNR pubkey publication so rotation is auditable end-to-end.< / li >
< li > Multi-sig (N-of-M operator keys) so a single compromised private key can't push code.< / li >
2026-09-20 14:39:07 +02:00
< li > Extend the channel to < b > Notepad< / b > (bundled, no channel yet).< / li >
2026-09-08 11:59:44 +02:00
< / ul >
< / section >
< footer >
Silent Mode · < a href = "https://code.silentmode.st/silentmode/theseus/src/branch/master/TheseusNavigator/docs/ADDON-UPDATES.md" > source & operator brief< / a >
< / footer >
< / div >
< / body >
< / html >