Embedding
Run SNA inside an Electron app or Node service.
startSnaServer() forks the standalone server as a managed child
process. Two entry points, depending on host:
import { startSnaServer } from "@sna-sdk/core/node"; // Plain Node
import { startSnaServer } from "@sna-sdk/core/electron"; // ElectronThe Electron variant resolves asar-unpacked paths and locates the
consumer app's electron-rebuilt better-sqlite3 binary.
Lifecycle
const sna = await startSnaServer({
appId: "my-electron-app",
port: 3099,
dbPath: path.join(app.getPath("userData"), "sna.db"),
maxSessions: 20,
permissionMode: "acceptEdits",
runtimePaths: {
claudeCode: "/opt/homebrew/bin/claude",
},
onLog: (line) => console.log("[sna]", line),
});
// sna.process : the spawned ChildProcess
// sna.port : actual port (after auto-pick)
// sna.appId : owner ID tagged onto sessions created by this server
// sna.connection : connection object to pass to SDK clients
// sna.stop() : graceful SIGTERMIn forked mode, the child server also shuts down when the parent process
disconnects. The token belongs to that server process; keep it paired with
sna.connection instead of putting a long-lived token in user-managed config.
Electron checklist
- Add
node_modules/@sna-sdk/core/**to electron-builder'sasarUnpack. The server'sdist/must be reachable at runtime. - Rebuild native deps for the Electron runtime:
npx electron-rebuild -f -w better-sqlite3 dbPathshould land underapp.getPath("userData")so the SQLite file survives upgrades.- Store user-selected runtime CLI paths in app settings and pass them through
runtimePathswhen starting SNA. - Pass
nativeBindingif you ship a custom-builtbetter_sqlite3.nodeoutside the default location.
Connecting from the renderer
The renderer process talks to the embedded server like any other HTTP/WS host:
import { SnaClient } from "@sna-sdk/client";
const client = new SnaClient(sna.connection);A helper endpoint GET /api/sna-port is wired by <SnaProvider> for
React apps so the renderer can auto-discover the port without IPC. If your
host exposes { baseUrl, authToken } from that same trusted app endpoint,
SnaProvider uses it as the connection automatically. Treat that helper as
part of the host app boundary: the runtime's own /api/sna-port route is
protected, and the token also authenticates SSE and WebSocket traffic.