Skip to content
GitHub Get Started
Operating System

Filesystem

Every VM comes with a persistent filesystem out of the box. Files written anywhere in the VM are automatically saved to the Rivet Actor’s built-in storage and restored on wake. No configuration needed.

  • Persistent by default backed by Rivet Actor storage, up to 10 GB
  • Full POSIX filesystem with read, write, mkdir, stat, move, delete
  • Batch operations for reading and writing multiple files at once
  • Mount backends for additional storage like S3, host directories, and overlays

The default filesystem persists automatically across sleep/wake cycles with no setup required (up to 10 GB). For larger storage or external data, mount additional filesystem drivers via the options.mounts config.

Each mount takes a path (where to mount inside the VM) and an optional readOnly flag. JavaScript filesystem backends like createInMemoryFileSystem() are passed as driver, while native plugin backends like createHostDirBackend(), createS3Backend(), and createGoogleDriveBackend() are passed as plugin.

import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import { createInMemoryFileSystem } from "@rivet-dev/agent-os-core";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({
options: {
software: [common, pi],
mounts: [
{ path: "/mnt/scratch", driver: createInMemoryFileSystem() },
],
},
});
export const registry = setup({ use: { vm } });
registry.start();
import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import { createHostDirBackend } from "@rivet-dev/agent-os-core";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({
options: {
software: [common, pi],
mounts: [
{ path: "/mnt/code", plugin: createHostDirBackend({ hostPath: "/path/to/repo" }), readOnly: true },
],
},
});
export const registry = setup({ use: { vm } });
registry.start();

Install @rivet-dev/agent-os-s3 for S3-compatible storage.

Use createS3Backend to mount a bucket. Pass an optional prefix to scope storage to a key path within the bucket — useful for sharing one bucket across multiple agents.

import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import { createS3Backend } from "@rivet-dev/agent-os-s3";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({
options: {
software: [common, pi],
mounts: [
{
path: "/mnt/data",
plugin: createS3Backend({
bucket: "my-bucket",
prefix: "agent-data/",
region: "us-east-1",
}),
},
],
},
});
export const registry = setup({ use: { vm } });
registry.start();

createS3Backend also accepts credentials ({ accessKeyId, secretAccessKey }) and a custom endpoint for S3-compatible providers.

Install @rivet-dev/agent-os-google-drive for Google Drive storage.

import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import { createGoogleDriveBackend } from "@rivet-dev/agent-os-google-drive";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({
options: {
software: [common, pi],
mounts: [
{
path: "/mnt/drive",
plugin: createGoogleDriveBackend({
credentials: {
clientEmail: process.env.GOOGLE_DRIVE_CLIENT_EMAIL!,
privateKey: process.env.GOOGLE_DRIVE_PRIVATE_KEY!,
},
folderId: process.env.GOOGLE_DRIVE_FOLDER_ID!,
}),
},
],
},
});
export const registry = setup({ use: { vm } });
registry.start();
// Write a file (string or Uint8Array)
await agent.writeFile("/home/user/hello.txt", "Hello, world!");
// Read a file (returns Uint8Array)
const content = await agent.readFile("/home/user/hello.txt");
console.log(new TextDecoder().decode(content));
// Batch write (creates parent directories automatically)
const writeResults = await agent.writeFiles([
{ path: "/home/user/src/index.ts", content: "console.log('hello');" },
{ path: "/home/user/src/utils.ts", content: "export function add(a: number, b: number) { return a + b; }" },
]);
// Batch read
const readResults = await agent.readFiles([
"/home/user/src/index.ts",
"/home/user/src/utils.ts",
]);
for (const result of readResults) {
console.log(result.path, new TextDecoder().decode(result.content));
}
// Create a directory
await agent.mkdir("/home/user/projects");
// List directory contents
const entries = await agent.readdir("/home/user/projects");
// Recursive listing with metadata
const tree = await agent.readdirRecursive("/home/user", {
maxDepth: 3,
exclude: ["node_modules"],
});
for (const entry of tree) {
console.log(entry.type, entry.path, entry.size);
}
// Check if a path exists
const fileExists = await agent.exists("/home/user/hello.txt");
// Get file metadata
const info = await agent.stat("/home/user/hello.txt");
console.log(info.size, info.isDirectory, info.mtimeMs);
// Move/rename
await agent.move("/home/user/old.txt", "/home/user/new.txt");
// Delete a file
await agent.delete("/home/user/new.txt");
// Delete a directory recursively
await agent.delete("/home/user/temp", { recursive: true });