.html page, or a .tsx / .jsx component - rendered in an isolated preview. Inside that preview, @arg-ai/sdk resolves without a package install: HTML hosts inject an import map, and the React preview compiler resolves the modules locally. Your source never receives an API key and never chooses which workspace it talks to. The host does, and the viewer decides what it may touch. The earlier @arg/sdk spelling remains an alias for saved apps.
import { arg } from "@arg-ai/sdk" gives you every namespace on one object plus arg.ready, a promise that settles once the host has delivered the app’s context. Named imports are lazy, so awaiting arg.ready is only required before reading arg.context (the workspace id, the app’s path and its folder).
Static imports of workspace files are bundled when a React preview builds, and a changed file
restarts the app. Read data that changes at runtime through
fs, and subscribe with fs.watch,
so the app keeps its state.Permissions
Every preview starts with Workspace access off. The viewer switches it on from the preview’s Permissions menu (on iOS and Android, from the … file menu), and picks two things:
Arg reads the app’s source and suggests the grant it appears to need, so a viewer sees a matching prompt on first open. The prompt is informational only; the bridge enforces every call, whatever the scan said. A refused call rejects with:
permission_deniedwhen the path or the namespace is outside the granted scope,read_onlywhen the grant is read-only and the call would change something,disabledwhen the call needs the Actions switch and it is off.
Files, folders and ids
Relative paths resolve beside the app file;/ is the workspace root. Under This folder scope a path that escapes the folder is refused, and fs.list and fs.glob are clamped to it. Cloud workspaces give every file a stable id: fs.getId(path) and fs.resolveId(id) convert between the two, and each read method has a ById twin for links that must survive a rename. The files guide covers every method.
fs.assetUrl(path) returns a signed URL you can put in an <img> or <video> tag. It expires; do not store it as a share link. fs.open(path) asks Arg to open the file in its own editor.
Embedded SQLite
db runs SQL against a .sqlite or .db file in the workspace, inside the preview:
db.exec needs Read and write. Servers and agent scripts do not serve db; it is an embedded capability only.
Identity and team
auth.principal() is the signed-in viewer. users.list() returns the workspace’s members with their role, so an app can assign work or show avatars without its own directory.
Chats and Actions
With Workspace scope and Actions on, an app can run Actions, start agent runs and open chats as the viewer:openPanel: true reveals the conversation beside the app: the docked chat panel on web and desktop, the native chat on iOS and Android. See chats and Actions and agents.
App chrome and navigation
ui registers the toolbar, inspector and bottom-bar descriptors an app may contribute to the surface around it, the same contract as @arg/ui without the React components:
host.open(path) opens a workspace file in Arg’s editor. Both are host capabilities: outside an Arg application host they report unsupported_capability, and ui.available is false.
Where it works
Web, the desktop app, iOS and Android all provide this bridge for HTML and React apps, with the same permissions menu. A folder the desktop app has opened straight from disk is a local workspace:fs reads the disk, stable ids and db are unavailable, and the only chats are the desktop’s own Claude Code and Codex sessions. The desktop harness section explains that case.
Existing apps written against window.arg keep working unchanged; the two are the same objects. window.arg.chat and window.arg.workspace are new on every platform, so an HTML app can adopt them without switching to imports.