Solari

VMs

A VM is a full Linux computer with a graphical screen. Watch and control it right in your browser, or drive it from the SDK to automate anything a person could do on screen.

Create one

Start a VM from the console under VMs → New, or from the SDK. It's ready almost instantly, usually in about a second.

npm install @solarisdk/desktop
import { DesktopClient } from "@solarisdk/desktop"

const desktops = new DesktopClient({
  apiKey: process.env.SOLARI_API_KEY!, // your Solari API key
  baseUrl: "https://api.getsolari.com",
})

// Starts in about a second.
const desktop = await desktops.create({
  template: "default",
  resolution: "1280x720",
  cpu: 4,                             // number of CPUs, 1-16 (default 2)
  memMb: 8192,                        // memory in MB, up to 65536 (default 2048)
  timeoutMs: 15 * 60 * 1000,          // pause after 15 min of no activity
  lifecycle: { onTimeout: "pause" },  // when idle: pause (resumable), or "kill"
})

console.log("watch it live:", desktop.streamUrl)

Choose its size

When you create a VM you can pick how many CPUs it has (from 1 to 16, default 2) and how much memory (from 2 GB up to 64 GB, default 2 GB). Set cpu and memMb at create time. The size sticks: if you pause the VM and come back later, it resumes at the same size, so you don't need to set it again.

// A bigger VM for a heavier workload.
const big = await desktops.create({
  template: "default",
  cpu: 8,
  memMb: 16384,
})
Size survives pause/resume
The size you chose is remembered when a VM pauses, so it comes back at the same CPU and memory. You don't re-pass cpu/memMb on resume.

Drive it

connect() opens the connection so you can control the VM. From there you have the full toolkit: mouse and keyboard, screenshots, a shell, files, the clipboard, running processes, and launching apps. Wait for health() before your first action so the screen is up and ready.

await desktop.connect()

const health = await desktop.health()   // { ready, display, vnc }
if (!health.ready) throw new Error("VM not ready")

Mouse & keyboard

The VM responds to real mouse and keyboard input. Pass humanize: true for a natural, curved mouse path instead of an instant jump. This helps on sites that watch how the pointer moves.

// Mouse: move, click, press-drag, scroll.
await desktop.mouse.move(640, 360, { humanize: true })
await desktop.mouse.click(640, 360, { button: "left", humanize: true })
await desktop.mouse.down(640, 360, "left")
await desktop.mouse.move(720, 360, { humanize: true })
await desktop.mouse.up(720, 360, "left")          // drag
await desktop.mouse.scroll(640, 360, { humanize: true })

// Keyboard: type text, or press key combinations.
await desktop.keyboard.type("hello world")
await desktop.keyboard.press(["ctrl", "s"])       // chord
await desktop.keyboard.down(["shift"])
await desktop.keyboard.up(["shift"])

Screenshots

screenshot() returns an image of the screen as a Uint8Array. PNG by default, or JPEG with a quality setting for smaller images when you capture in a loop.

const png = await desktop.screenshot({ format: "png" })
const jpg = await desktop.screenshot({ format: "jpeg", quality: 70 })

Shell & files

exec runs a command and waits for it to finish; pass an onChunk callback to stream the output as it arrives. The fs tools read and write files directly.

// One-shot command.
const { exitCode, stdout, stderr } = await desktop.exec("uname", {
  args: ["-a"],
})

// Streamed command.
await desktop.execStream("apt-get",
  ({ stream, text }) => process.stdout.write(text),
  { args: ["install", "-y", "jq"] })

// Files: read, write, list.
await desktop.fs.write("/tmp/note.txt", "hello")
const text = await desktop.fs.readText("/tmp/note.txt")
const entries = await desktop.fs.list("/home")

Clipboard, apps & processes

// Copy and paste between your app and the VM.
await desktop.clipboard.set("paste me")
const clip = await desktop.clipboard.get()

// Launch an app by name; returns its pid.
const pid = await desktop.open("firefox", ["https://example.com"])

// Inspect and manage the process table.
const procs = await desktop.process.list()
await desktop.process.kill(pid)

// Resize the display on the fly.
await desktop.display.set(1920, 1080)

Watch it live

Every VM comes with a live view you can watch and control. streamUrl is ready when you create the VM; open it in a viewer (the console does this for you in the in-browser View tab) to watch and take over interactively.

const { streamUrl } = await desktop.stream.start()
// Open streamUrl in a viewer to watch and control the VM.

Re-attach later

Every VM has a stable id. connect(id) reconnects to a VM you started earlier, and resumes it if it was paused.

const box = await desktops.connect("dsk_abc123")
await box.connect()
await box.exec("whoami")

Idle timeout

A VM stays running as long as you're using it. Set timeoutMs at create time to say how long it can sit idle; every action and every open connection resets the clock. When that time passes with no activity, lifecycle decides what happens: onTimeout: "pause" (the default) parks the VM and its state is saved, so the next connect() picks up right where you left off, while onTimeout: "kill" shuts it down. If you don't set timeoutMs, it defaults to 30 minutes.

A busy VM won't time out, and pausing frees up your plan
The idle timer resets whenever the VM is in use, so it won't disappear mid-task. A paused VM doesn't count against your plan's limit on running VMs; resuming it counts again.
// Change how long it can sit idle (ms).
await desktop.setTimeout(15 * 60 * 1000)

// Pause it now: state is saved, resumes on the next connect().
await desktop.pause()

Tear down

close() ends your connection; destroy(id) shuts the VM down for good. It can't be recovered.

desktop.close()
await desktops.destroy(desktop.sessionId)
Sandboxes are the screen-free sibling
Just need to run code, with no screen? See Sandboxes and its @solarisdk/sandbox package. Same idea and same lifecycle, just SandboxClient instead of DesktopClient. Want both from one client plus the solari CLI? Install @solarisdk/sdk and use solari.desktops / solari.sandboxes.