Capsa is experimental software. APIs may change without notice.
Skip to content

Core Concepts

This page explains the key concepts in Capsa and when to use each approach.

Sandbox vs Raw VM

Capsa offers two ways to run code in a VM:

AspectSandboxRaw VM
SetupZero configBring your own kernel/initrd
Command executionAgent RPCConsole scraping
File operationsagent.read_file(), agent.write_file()Manual via console
Shared directoriesAuto-mountedManual mount required
Best forMost use casesCustom OS, specialized kernels

Use Sandbox When You Need

  • Isolated code execution (AI agents, untrusted code)
  • Integration testing
  • Build environments
  • Structured command output (exit codes, stdout, stderr)

Use Raw VM When You Need

  • Custom kernel configuration
  • Non-Linux operating systems
  • Specific kernel modules
  • Full control over the boot process

Agent vs Console

The agent and console serve different purposes:

The agent is a built-in RPC service that runs inside sandboxes:

rust,no_run
// Structured command execution
let result = agent.exec("ls").arg("/").run().await?;
println!("stdout: {}", result.stdout);
println!("stderr: {}", result.stderr);
println!("exit_code: {}", result.exit_code);

// Direct file operations
let data = agent.read_file("/etc/hostname").await?;
agent.write_file("/tmp/output.txt", b"hello").await?;

Advantages:

  • Structured output (no parsing required)
  • Proper exit codes
  • File read/write operations
  • System information queries
  • Clean shutdown

Console

The console provides raw serial port access:

rust,no_run
// Wait for boot
console.wait_for("login:", Duration::from_secs(30)).await?;

// Manual interaction
console.write_line("root").await?;
let output = console.read_available().await?;

Use for:

  • Waiting for boot output
  • Interactive troubleshooting
  • VMs without agent support

Boot Configurations

Linux Direct Boot

Boots a Linux kernel directly without a bootloader:

rust,no_run
let boot = LinuxDirectBoot::new("./kernel", "./initrd")
    .with_root_disk("./rootfs.raw");

let vm = capsa::vm(boot)
    .cmdline_arg("console", "ttyS0")
    .build()
    .await?;

Used by both sandboxes (internally) and raw VMs.

UEFI Boot (macOS only)

Boots from a disk image using UEFI:

rust,no_run
let boot = UefiBoot::new("./disk.img");

Networking

VirtualNetwork

Provides NAT networking with optional policies:

rust,no_run
let policy = NetworkPolicy::deny_all()
    .allow_domain("api.github.com")
    .allow_domain("*.rust-lang.org");

let network = VirtualNetwork::with_gateway(
    Gateway::new("10.0.2.0/24").unwrap().policy(policy).unwrap()
);

No Network

Completely isolated - no network access:

rust,no_run
let vm = capsa::sandbox()
    .no_network()
    .build()
    .await?;

Shared Directories

Share host directories with the VM using virtio-fs:

rust,no_run
let vm = capsa::sandbox()
    .share("./src", "/mnt/src", AccessMode::ReadOnly)
    .share("./output", "/mnt/output", AccessMode::ReadWrite)
    .build()
    .await?;

In sandbox mode, directories are automatically mounted. In raw VMs, you must mount them manually inside the guest.

Next Steps

Released under the MIT License.