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:
| Aspect | Sandbox | Raw VM |
|---|---|---|
| Setup | Zero config | Bring your own kernel/initrd |
| Command execution | Agent RPC | Console scraping |
| File operations | agent.read_file(), agent.write_file() | Manual via console |
| Shared directories | Auto-mounted | Manual mount required |
| Best for | Most use cases | Custom 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:
Agent (Recommended)
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
- Running Commands - Detailed agent usage
- Working with Files - File operations and shares
- Custom VMs - When you need raw VM access