Quickstart
This page takes an existing Vite app to a working Userspace VM: one file written into the VM’s workspace and read back by a Linux program. It takes about five minutes.
Local development needs no account or token. Before publishing this app, register a public license and pass its token as runtime.license.
-
Install the SDK.
Terminal window npm install @oxidevm/sdkThe package holds no engine. The engine and the default Linux image load from the hosted runtime frame, so there is nothing else to install or serve.
-
Serve with the right headers. The engine needs a cross-origin isolated page, so every response needs two headers. In Vite:
vite.config.ts import { defineConfig } from "vite";const headers = {"Cross-Origin-Opener-Policy": "same-origin","Cross-Origin-Embedder-Policy": "require-corp",};export default defineConfig({optimizeDeps: { exclude: ["@oxidevm/sdk"] }, // keeps the SDK's worker URLs intactworker: { format: "es" },server: { headers },preview: { headers },});Restart the dev server, open your app and check that
crossOriginIsolatedistruein the browser console. -
Create your first VM. Call
createVMfrom browser code, never during server rendering:src/main.ts import { createVM } from "@oxidevm/sdk";const vm = await createVM({ mode: "userspace", runtime: { hosting: "frame" } });try {await vm.workspace.writeText("hello.txt", "Hello from Linux\n");const result = await vm.exec({ command: "cat", args: ["hello.txt"] });console.log(new TextDecoder().decode(result.stdout), result.exit);} finally {await vm.dispose();}runtime: { hosting: "frame" }runs the engine in a hidden frame fromhttps://run.oxidevm.dev, which also serves the default image.Run the same two steps on this page’s own VM:
Write a file, read it backUserspaceNot started Hello from Linuxexit: {"kind":"exited","code":0}
Downloads Linux into this tab when you click.
What you have now
Section titled “What you have now”vm.workspacereads and writes files under/workspacein the VM. See Workspace files.vm.execruns a short command and returns its output and exit status. See Run commands.result.exitis{ kind: "exited", code }or{ kind: "signaled", signal, signalNumber }. A non-zero exit code is a normal result, not an error.- Your site serves only your app. Deploying covers the headers on your host, a Content Security Policy, and serving the engine yourself.
Next, open an interactive terminal or decide between Userspace and System.