Home / SG/Vault / The bridge

The window.sg bridge

Inside App Mode, the host injects a bridge object — window.sg — that gives your page mediated access to the vault and to host capabilities. It installs synchronously while <head> parses, so any inline script can use it. The app frame never holds the vault key: every operation goes through the host, which owns the crypto and the consent UI.

Namespaces at a glance

NamespaceWhat it doesGrant
sg.vfsread / readText / list / write / host-fulfilled download. Writes cap at ~3 MB (EFBIG); reads have no capfs.read / fs.write
sg.loadCss / sg.loadJsTop-level functions (not under vfs) — the sanctioned way to load vault CSS/JS; injects into <head>rides fs.read — no separate verb
sg.fsmove (grant needed on both paths) / delete / mkdirfs.* + first-use consent
sg.vaultCross-vault lifecycle: create(opts) (options object — label, seedFrom, returnKey, custody, link), getKey, openApp, list, unlink, mount, embedvault.*; embed needs none — the key is the capability
sg.historyRead-only commit history: log, list, read/readText at a commit — works on read-only opensno
sg.syncstatus / push / pull / refresh against the named branch (sg.git.* survives as a deprecated alias)writable vault
sg.authThe write gate — the server access token, separate from the encryption key: hasKey, setKey, check, clearno
sg.uiHost toasts (message), quick-look preview (incl. PDFs — in-frame PDF rendering is sandbox-blocked), requestPermissionno
sg.stateDevice-local prefs (64 KiB/key, kernel localStorage, survives reload, not a vault write — "a theme toggle shouldn't create a commit")no
sg.llmavailable / models / chat (streaming, cancel, image parts) / usage / voice listen — the vault's LLM key stays in the host; your frame never sees itllm.chat / llm.listen / …
sg.appendAppend-only transport (write verb is write): configure, write, list, fetch, markProcessed, purge. Lives outside the commit treeappend.*
sg.on / sg.offHost events pushed to the app (e.g. append.new-messages on tab focus — the kernel checks; your app does not poll)host_events allowlist (top-level key)
sg.appRead-only context: writable, selfPath, vaultName, vaultId, contextno

The permission model

Grants live in app.json (preferred location: .vault/app.json; a legacy root app.json is still read). Each permission is true | false | string[], and path lists are prefix-based, not glob: a trailing / means "this folder and everything under it"; no slash means an exact file. "data/**" is not valid — use "data/".

{
  "entry": "index.html",
  "permissions": {
    "fs":    { "read": true, "write": ["data/"], "delete": ["data/"] },
    "vault": { "create": ["runs/"] },
    "llm":   { "chat": true },
    "externalLinks": true,
    "downloads": true
  },
  "host_events": ["append.new-messages"]
}

Error codes worth branching on

CodeMeaning
EPERMverb not granted in app.json
EPROTECTEDthe floor — .vault/** or the manifest itself
ECONSENTuser declined the consent prompt
ENOENTno such file — the usual cause when loadCss/loadJs "doesn't work" (typo, or written locally but never pushed)
EFBIGsingle write over ~3 MB
EREADONLYstatic host or read-only session
EBUDGET · ENOKEY · EMODEL · EABORTllm namespace: spend cap, no key configured, model not allowed, cancelled

Host chrome vs API — two different things

Chrome you configure but never call (via app.json's hud block — mode: full | minimal | hidden | none plus per-button show.* flags): the nav row, Print, the ✨ AI chat panel (text and voice, entirely at the host origin — your frame never sees the conversation, the key, or the microphone), the file-activity meter, friendly 404 overlays, and the external-link confirm. API you call, with grants: sg.ui.preview, sg.vfs.download, sg.llm.*.

And the sovereignty rail — three things an app can never suppress, whatever its hud config: consent prompts always render; mode:"hidden" keeps a corner exit pill; and the user can force the full HUD back on from their side, at a level app code cannot reach. The HUD config is for app preferences, not app authority.

Versioning note: this page is an orientation map, verified against the app-shell bridge (v0.2.x, 2026-08). The authoritative, always-current API reference ships with the app-shell source; where they disagree, the source-side reference wins.