Operating System
Processes & Shell
- One-shot execution with
execfor simple commands - Long-running processes with
spawn, stdout/stderr streaming, and stdin writing - Process lifecycle management with stop, kill, wait, and inspect
- Interactive shells with PTY support for terminal I/O
- Process tree visibility across all VM runtimes
One-shot execution
Section titled “One-shot execution”Use exec to run a command and wait for completion. Returns stdout, stderr, and exit code.
import { createClient } from "rivetkit/client";import type { registry } from "./server";
const client = createClient<typeof registry>("http://localhost:6420");const agent = client.vm.getOrCreate(["my-agent"]);
const result = await agent.exec("echo hello && ls /home/user");console.log("stdout:", result.stdout);console.log("stderr:", result.stderr);console.log("exit code:", result.exitCode);import { agentOs } from "rivetkit/agent-os";import { setup } from "rivetkit";import common from "@rivet-dev/agent-os-common";import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({ options: { software: [common, pi] },});
export const registry = setup({ use: { vm } });registry.start();Spawn a long-running process
Section titled “Spawn a long-running process”Use spawn for processes that run in the background. Output is streamed via processOutput and processExit events.
import { createClient } from "rivetkit/client";import type { registry } from "./server";
const client = createClient<typeof registry>("http://localhost:6420");const agent = client.vm.getOrCreate(["my-agent"]);
// Subscribe to process outputagent.on("processOutput", (data) => { const text = new TextDecoder().decode(data.data); console.log(`[pid ${data.pid}] ${data.stream}: ${text}`);});
agent.on("processExit", (data) => { console.log(`[pid ${data.pid}] exited with code ${data.exitCode}`);});
// Spawn a dev serverconst { pid } = await agent.spawn("node", ["/home/user/server.js"]);console.log("Started process:", pid);import { agentOs } from "rivetkit/agent-os";import { setup } from "rivetkit";import common from "@rivet-dev/agent-os-common";import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({ options: { software: [common, pi] },});
export const registry = setup({ use: { vm } });registry.start();Write to stdin
Section titled “Write to stdin”Send input to a running process.
import { createClient } from "rivetkit/client";import type { registry } from "./server";
const client = createClient<typeof registry>("http://localhost:6420");const agent = client.vm.getOrCreate(["my-agent"]);
const { pid } = await agent.spawn("cat", []);
// Write to stdinawait agent.writeProcessStdin(pid, "hello from stdin\n");
// Close stdin when doneawait agent.closeProcessStdin(pid);
// Wait for the process to exitconst exitCode = await agent.waitProcess(pid);console.log("exit code:", exitCode);import { agentOs } from "rivetkit/agent-os";import { setup } from "rivetkit";import common from "@rivet-dev/agent-os-common";import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({ options: { software: [common, pi] },});
export const registry = setup({ use: { vm } });registry.start();Process lifecycle
Section titled “Process lifecycle”import { createClient } from "rivetkit/client";import type { registry } from "./server";
const client = createClient<typeof registry>("http://localhost:6420");const agent = client.vm.getOrCreate(["my-agent"]);
const { pid } = await agent.spawn("node", ["/home/user/server.js"]);
// List all spawned processesconst processes = await agent.listProcesses();console.log(processes);
// Get info about a specific processconst info = await agent.getProcess(pid);console.log(info.running, info.exitCode);
// Graceful stop (SIGTERM)await agent.stopProcess(pid);
// Force kill (SIGKILL)await agent.killProcess(pid);import { agentOs } from "rivetkit/agent-os";import { setup } from "rivetkit";import common from "@rivet-dev/agent-os-common";import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({ options: { software: [common, pi] },});
export const registry = setup({ use: { vm } });registry.start();System-wide process visibility
Section titled “System-wide process visibility”View all processes across all VM runtimes, not just those started via spawn.
import { createClient } from "rivetkit/client";import type { registry } from "./server";
const client = createClient<typeof registry>("http://localhost:6420");const agent = client.vm.getOrCreate(["my-agent"]);
// All processesconst all = await agent.allProcesses();for (const p of all) { console.log(p.pid, p.driver, p.command, p.status);}
// Process tree (parent-child hierarchy)const tree = await agent.processTree();for (const node of tree) { console.log(node.pid, node.command, "children:", node.children.length);}import { agentOs } from "rivetkit/agent-os";import { setup } from "rivetkit";import common from "@rivet-dev/agent-os-common";import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({ options: { software: [common, pi] },});
export const registry = setup({ use: { vm } });registry.start();Interactive shells
Section titled “Interactive shells”Open an interactive shell with PTY support. Shell data is streamed via shellData events.
import { createClient } from "rivetkit/client";import type { registry } from "./server";
const client = createClient<typeof registry>("http://localhost:6420");const agent = client.vm.getOrCreate(["my-agent"]);
// Subscribe to shell outputagent.on("shellData", (data) => { const text = new TextDecoder().decode(data.data); process.stdout.write(text);});
// Open a shellconst { shellId } = await agent.openShell();
// Write commands to the shellawait agent.writeShell(shellId, "ls -la /home/user\n");
// Resize the terminalawait agent.resizeShell(shellId, 120, 40);
// Close the shell when doneawait agent.closeShell(shellId);import { agentOs } from "rivetkit/agent-os";import { setup } from "rivetkit";import common from "@rivet-dev/agent-os-common";import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({ options: { software: [common, pi] },});
export const registry = setup({ use: { vm } });registry.start();Recommendations
Section titled “Recommendations”- Use
execfor short commands where you need the full output. Usespawnfor long-running processes where you want streaming output. - Subscribe to
processOutputandprocessExitbefore callingspawnto avoid missing events. - Active processes prevent the actor from sleeping. Stop or kill them when they are no longer needed.
- Active shells also prevent sleep. Close shells when the user disconnects.
- Use
allProcessesandprocessTreefor debugging. They show everything running in the VM, including agent processes.