Skip to content

Session

One running MicroVM’s control API, with the proxy auth handled for you.

agentToken(): Promise<string>;

The guest bearer credential. Store only in a private encrypted control record.

Promise<string>


connectHeaders(port: number): Promise<Record<string, string>>;

Both proxy headers for port, so a caller can open its own connection.

The { url, headers } shape a provider’s getPortEndpoint answers with: pair these with endpoint() and nothing outside this addon has to know how a proxy token is minted or when it refreshes. Minted through the session’s existing cache, so calling this does not burn a second control-plane call and does not open a second TRAP-9 schedule.

A plain Record<string, string> rather than a class, and that is the one place this crate’s own “never #[napi(object)] for anything carrying a closure” rule does not apply: there is no closure here to protect. The value is a bearer credential, and unlike the token itself it necessarily comes out as a string — a header a caller has to put on a request cannot be opaque. What is still closed is the other direction: no function in this addon takes a header map, so a caller cannot feed a forged or expired one back in.

Empty for a direct session, which is the true answer rather than a missing one: a daemon reached directly takes no proxy headers, so an empty object is exactly what its requests carry.

Parameter Type
port number

Promise<Record<string, string>>


connectSubprotocols(port: number): Promise<string[] | null>;

The three WebSocket subprotocols for port, in the order a handshake offers them.

new WebSocket(url, await session.connectSubprotocols(port)) is the whole use. A MicroVM endpoint takes the auth and the target port as Sec-WebSocket-Protocol values rather than as headers, because the browser WebSocket constructor cannot set a header — and the platform strips all three before forwarding, so a server inside the VM never negotiates them and must not be written to expect them.

null for a direct session, and deliberately not an empty array: the subprotocol form exists only for a request through the endpoint proxy, so there is nothing for a directly-reached daemon to offer. Answering ["lambda-microvms"] with no token would open a handshake refused for a reason naming neither the token nor the port.

The middle string contains the credential. Same rule as connectHeaders.

Parameter Type
port number

Promise<string[] | null>


discovery(): Promise<Discovery | null>;

Image configuration, or null if this daemon predates discovery.

Promise<Discovery | null>


downloadDir(
remote: string,
localDir: string,
globs: string[]
): Promise<DownloadedFile[]>;

Brings the files of a directory in the VM back under localDir: the regular files globs select, and nothing else.

The daemon packs remote, and the archive describes the VM’s filesystem, where untrusted work runs, so core writes only regular-file members that match a glob, never under .git whatever the globs say, and never outside localDir. A symlink, a special file or a ../ member is skipped, not refused. ['**'] brings every regular file back. Resolves to what was written; a local directory that can’t be written to rejects with ERR_INVALID_ARG.

Parameter Type
remote string
localDir string
globs string[]

Promise<DownloadedFile[]>


downloadFile(path: string, options?: DownloadFileOptions | null): Promise<Buffer<ArrayBufferLike>>;

Reads one file, or lines startLine through endLine of it.

The range is 1-based and inclusive, and the daemon slices the file, so reading lines 40 to 60 of a large log reads those lines alone. Either bound may be left out (line 1, through EOF), and an endLine past the last line reads through EOF. Line 0 and an end before the start reject with ERR_INVALID_ARG before any request.

Parameter Type
path string
options? DownloadFileOptions | null

Promise<Buffer<ArrayBufferLike>>


downloadTar(remote: string): Promise<Buffer<ArrayBufferLike>>;

The raw tar bytes of a remote tree.

Parameter Type
remote string

Promise<Buffer<ArrayBufferLike>>


egressPosture(): Promise<string>;

The launch’s egress posture: "open", "unsealed", "best-effort", or "sealed".

The value the CLI envelope’s egressPosture reports for the same launch options, and what egressPostureFor answers before the launch. A session that does not hold its launch options (Session.direct, Session.attach, an adopted sandbox) reports "unsealed". Advertise network isolation only for "sealed". Async like endpoint(), because a sandbox-held session is read under the sandbox’s lock.

Promise<string>


endpoint(): Promise<string>;

The endpoint this session addresses.

Promise<string>


exec(execId: string): Promise<ExecHandle>;

A handle for an exec started earlier, possibly by another process.

The reattach path. Nothing is checked against the daemon here — the handle is an id plus a transport, and a poll is what discovers whether the exec exists.

Parameter Type
execId string

Promise<ExecHandle>


fileExists(path: string): Promise<boolean>;

Whether a path exists, distinguishing absence from every other refusal.

Parameter Type
path string

Promise<boolean>


health(): Promise<Health>;

Unauthenticated liveness.

Promise<Health>


keepAwake(options?: KeepAwakeOptions | null): Promise<KeepAwake>;

Keeps the VM awake by polling health from this process until stopped.

The platform counts only inbound requests as activity, so an exec working with no client traffic is suspended once maxIdleDurationSeconds passes. Resolves at once with a running handle. On a sandbox-held session a suspend or terminate through the sandbox ends the keepalive before its next poll; stop it before suspending through anything else, or the next poll auto-resumes the VM.

Parameter Type
options? KeepAwakeOptions | null

Promise<KeepAwake>


kill(execId: string): Promise<boolean>;

Signals an exec’s whole process group. Returns whether anything was signalled.

Parameter Type
execId string

Promise<boolean>


launchMetrics(): Promise<LaunchMetrics | null>;

Launch observations, absent for sessions not created by a launch.

Promise<LaunchMetrics | null>


port(): Promise<number>;

The port the proxy token is scoped to.

Promise<number>


portForward(guestPort: number, options?: ServeOptions | null): Promise<PortForward>;

Serves a local port as an HTTP and WebSocket forward to guestPort in the VM, on a background task, and resolves at once with its handle: microvm port-forward’s loop.

Connections are served at once rather than one after another, so a slow request doesn’t hold the next. A request the endpoint proxy refuses is listed in the report with its status while the forward keeps serving.

Parameter Type
guestPort number
options? ServeOptions | null

Promise<PortForward>


procs(): Promise<ProcGroup[]>;

Process accounting: every registered exec with its group’s live pids.

The daemon reads /proc itself, so this needs no ps in the guest. A ProcGroup with childExited and a non-empty pids is a command that finished while something it backgrounded did not; pass its execId to kill.

Promise<ProcGroup[]>


proxyMintCount(): Promise<number | null>;

How many proxy tokens this session has minted, or null for a direct session.

Exposed because it is the only observable that distinguishes a client which re-minted after a resume from one that kept a stale token (STATE-8). The token itself is not exposed and cannot be: the core’s ProxyToken has no Display, no as_str, and no Deref, so “treat authToken as a string” is as inexpressible here as it is there (TRAP-7).

Promise<number | null>


run(command: string | string[], options?: ExecOptions | null): Promise<ExecHandle>;

Starts a command and returns its handle. Does not wait.

Parameter Type
command string | string[]
options? ExecOptions | null

Promise<ExecHandle>


runSync(command: string | string[], options?: ExecOptions | null): Promise<ExecResult>;

Start, wait, ack. The one-shot shape, for when output is all you want.

Parameter Type
command string | string[]
options? ExecOptions | null

Promise<ExecResult>


runToCompletion(
command: string | string[],
options?: CompletionRequest | null,
onOutput?:
| ((chunk: StreamEvent) => unknown)
| null
): Promise<ExecResult>;

Start, stream, and collect one command: exactly one ExecResult back (BIND-6..10).

With onOutput, each output chunk (a StreamEvent of kind "output") is handed to it as it arrives. The result then comes from the ack that follows the terminal exit event, or, when the stream ends without one, from a wait and ack. When timeoutSec + clientGraceSec passes first (or, with no timeoutSec, the VM’s maximum lifetime), the process group is killed and the exec waited for and acked within clientGraceSec once more; if that fails too the result is synthesized with posixExitCode 124.

A throwing onOutput stops delivery; the exec is still waited for and acked so nothing is left behind, and then the promise rejects with the callback’s message. shell: true runs /bin/sh -c; for bash semantics pass shell: "bash" with a script string, or ["bash", "-c", script] for a daemon that predates named shells.

Parameter Type
command string | string[]
options? CompletionRequest | null
onOutput? | ((chunk: StreamEvent) => unknown) | null

Promise<ExecResult>


spawn(command: string | string[], options?: SpawnOptions | null): Promise<ExecProcess>;

Starts a command and returns it as two byte streams, a wait(), and a kill().

The process shape, as against [Self::run]’s handle shape. Same start request and the same ExecOptions (cwd, env, user, group, shell, execId, timeoutSec all apply), so this is a different view of one exec rather than a different exec: spawn and run with the same execId address the same server-side child, and the daemon starts one.

stdout and stderr come out as independent ReadableStream<Uint8Array>, which is deliberately the AI SDK harness’s SandboxProcess shape — see [crate::process] for what that compatibility is and is not, for how one interleaved SSE channel becomes two streams, and for why an evicted byte range errors the streams by default instead of being reported out-of-band.

The reconnect-at-cursor behaviour is unchanged from stream(): a stream cut by a suspend/resume rejoins at the byte offset rather than ending, so a suspend does not look like a clean exit.

Parameter Type
command string | string[]
options? SpawnOptions | null

Promise<ExecProcess>


syncDir(localDir: string, options?: SyncDirOptions | null): Promise<SyncReport>;

Syncs localDir into the VM’s /workspace once, uploading only what changed.

Core’s one pass, microvm sync’s: the local tree is hashed and diffed against the manifest the last sync left in the VM, the changed members travel as one archive, the paths gone locally are removed in the VM with one rm whose deadline is deleteTimeout seconds (core’s default when omitted), and the manifest is rewritten. full: true ignores the manifest and uploads everything. .git, target, node_modules and .venv never travel. A tree over the daemon’s budgets rejects with ERR_INVALID_ARG before anything is sent.

Parameter Type
localDir string
options? SyncDirOptions | null

Promise<SyncReport>


tunnel(
guestPort: number,
options?: ServeOptions | null,
verifyIdentity?: TunnelIdentity | null
): Promise<Tunnel>;

Serves a local TCP port as a tunnel to guestPort in the VM, on a background task, and resolves at once with its handle: microvm tunnel’s loop.

Each local connection gets a WebSocket of its own through the endpoint proxy, and a connection the daemon refuses is listed in the report while the tunnel keeps serving. With verifyIdentity (a TunnelIdentity, such as sandbox.tunnelIdentity()), each connection first proves the far end is the daemon of the VM that identity was launched with, and a connection that can’t is refused. A separate parameter rather than an option, for the reason buildImage’s guarded values are: a class in an options object can’t cross an async call.

Parameter Type
guestPort number
options? ServeOptions | null
verifyIdentity? TunnelIdentity | null

Promise<Tunnel>


uploadFile(
path: string,
data: Uint8Array,
mode?: string | null
): Promise<void>;

Writes one file, creating parents. mode is an octal string ("0755"), which is the daemon’s shape — a number here would be ambiguous between 0o755 and 755.

Parameter Type
path string
data Uint8Array
mode? string | null

Promise<void>


uploadTar(remote: string, archive: Uint8Array): Promise<void>;

Extracts pre-built tar bytes under remote.

Bytes rather than a local path: packing a directory is the caller’s, because the symlink and permission decisions in a pack belong to whoever knows what the tree means.

Parameter Type
remote string
archive Uint8Array

Promise<void>


waitUntilReady(timeout?: number | null): Promise<Health>;

Polls health until the daemon reports bootstrapped.

Connection errors on the way are expected rather than exceptional: a VM that has just reached RUNNING commonly refuses a connection or two before the proxy path is wired up. A fatal error ends the wait at once, because retrying a 401 until the deadline is the mistake the retryable split exists to prevent.

Parameter Type
timeout? number | null

Promise<Health>


static attach(
region: Region,
microvmId: string,
endpoint: string,
agentToken: string,
port?: number | null,
requestTimeout?: number | null
): Promise<Session>;

Reattach using a private control record, without bootstrapping again. Owns its transport independently of sandbox locks; use a separate attach with a short requestTimeout for keepalives. Never publish or log agentToken.

Parameter Type
region Region
microvmId string
endpoint string
agentToken string
port? number | null
requestTimeout? number | null

Promise<Session>


static direct(endpoint: string, agentToken: string): Session;

A session against a daemon reached directly, with no proxy headers.

The shape for a local binary, a test server, or a VM reached over a tunnel. There is deliberately no constructor that takes a proxy token: minting one is the control plane’s job and it happens inside every request (TRAP-9), so a caller handing a token in would be handing in one that expires.

Parameter Type
endpoint string
agentToken string

Session

This page is generated from bindings/microvms-js/index.d.ts by TypeDoc 0.28.20 and typedoc-plugin-markdown 4.13.1, run from site/scripts/gen-reference.mjs on every pnpm run sync, so an edit made here is overwritten by the next run.

To change the page, change the doc comment in the binding’s Rust source, then regenerate the declarations with mise run dts. mise run dts:check fails when the committed file no longer matches the source.