SNA

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";  // Electron

The 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 SIGTERM

In 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's asarUnpack. The server's dist/ must be reachable at runtime.
  • Rebuild native deps for the Electron runtime:
    npx electron-rebuild -f -w better-sqlite3
  • dbPath should land under app.getPath("userData") so the SQLite file survives upgrades.
  • Store user-selected runtime CLI paths in app settings and pass them through runtimePaths when starting SNA.
  • Pass nativeBinding if you ship a custom-built better_sqlite3.node outside 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.

On this page