Skip to main content

Overview

SmolVM provides seamless command execution inside microVMs via SSH. The run() method handles SSH connection management automatically, supporting both login shell and raw execution modes.

Basic Command Execution

The simplest way to run commands:
from smolvm import SmolVM

with SmolVM() as vm:
    result = vm.run("echo 'Hello from SmolVM'")
    print(result.stdout.strip())
    # Output: Hello from SmolVM

CommandResult Object

Every run() call returns a CommandResult with:
result = vm.run("ls -la /tmp")

# Exit code (0 = success)
print(result.exit_code)  # 0

# Standard output
print(result.stdout)

# Standard error
print(result.stderr)

# Convenience properties
print(result.ok)      # True if exit_code == 0
print(result.output)  # Stripped stdout
result = vm.run("whoami")
if result.ok:
    print(f"Current user: {result.output}")
    # Output: Current user: root

Shell Modes

SmolVM supports two execution modes controlled by the shell parameter:

Login Shell Mode (Default)

Runs commands through the guest’s login shell, loading profile and environment:
# Uses login shell - env vars from /etc/profile.d/ are loaded
result = vm.run("echo $PATH", shell="login")
This mode:
  • Sources /etc/profile and user profile scripts
  • Loads environment variables from /etc/profile.d/smolvm_env.sh
  • Best for commands that need full shell environment
  • Default behavior when shell parameter is omitted

Raw Mode

Executes commands directly without shell wrapping:
# Direct execution - no shell environment loading
result = vm.run("hostname", shell="raw")
Raw mode:
  • Skips profile loading
  • Faster execution
  • Useful for simple commands that don’t need environment
  • Required for non-shell binaries
from smolvm import SmolVM

with SmolVM() as vm:
    # Set environment variable
    vm.set_env_vars({"API_KEY": "secret-123"})
    
    # Login shell loads the env var
    result = vm.run("echo $API_KEY", shell="login")
    print(result.output)  # secret-123

Timeout Handling

Control execution timeout with the timeout parameter (in seconds):
from smolvm.exceptions import OperationTimeoutError

try:
    # Long-running command with 60s timeout
    result = vm.run(
        "apt-get update && apt-get install -y curl",
        timeout=60
    )
except OperationTimeoutError as e:
    print(f"Command timed out: {e.message}")
Default timeout is 30 seconds. Adjust based on expected command duration.

Error Handling Patterns

Check Exit Codes

result = vm.run("./install.sh")
if not result.ok:
    raise RuntimeError(
        f"Installation failed (exit {result.exit_code}): {result.stderr}"
    )

Handle SSH Unavailability

from smolvm.exceptions import CommandExecutionUnavailableError

try:
    result = vm.run("whoami")
except CommandExecutionUnavailableError as e:
    print(f"SSH not available: {e.message}")
    print(f"Remediation: {e.remediation}")
Commands can only run on VMs with SSH support. Auto-configured VMs and images built with ImageBuilder include SSH by default.

Comprehensive Error Handling

from smolvm import SmolVM
from smolvm.exceptions import (
    SmolVMError,
    CommandExecutionUnavailableError,
    OperationTimeoutError
)

with SmolVM() as vm:
    try:
        result = vm.run("complex-command", timeout=30)
        
        if not result.ok:
            print(f"Command failed with exit code {result.exit_code}")
            print(f"stderr: {result.stderr}")
            # Decide how to handle based on exit code
            
    except OperationTimeoutError:
        print("Command exceeded 30 second timeout")
    except CommandExecutionUnavailableError as e:
        print(f"SSH not ready: {e.remediation}")
    except SmolVMError as e:
        print(f"VM error: {e}")

Multi-Step Commands

Sequential Commands

# Run commands in sequence
vm.run("apt-get update")
vm.run("apt-get install -y python3-pip")
vm.run("pip3 install requests")

Chained Commands

# Chain with && for atomic operations
result = vm.run(
    "apt-get update && "
    "apt-get install -y python3-pip && "
    "pip3 install requests",
    timeout=120
)

Multi-line Scripts

script = """
set -e  # Exit on error
apt-get update
apt-get install -y curl jq
curl -s https://api.example.com | jq '.data'
"""

result = vm.run(script, timeout=60)
if result.ok:
    print("Script completed successfully")

Real-World Examples

Installing Software

from smolvm import SmolVM

with SmolVM(mem_size_mib=1024) as vm:
    # Update package lists
    vm.run("apk update", timeout=30)
    
    # Install packages
    result = vm.run("apk add --no-cache python3 py3-pip", timeout=60)
    if not result.ok:
        raise RuntimeError(f"Failed to install packages: {result.stderr}")
    
    # Verify installation
    result = vm.run("python3 --version")
    print(f"Installed: {result.output}")

Running Python Code

with SmolVM() as vm:
    # Install dependencies
    vm.run("apk add --no-cache python3 py3-pip")
    
    # Run inline Python
    python_code = '''
import sys
import platform
print(f"Python {sys.version}")
print(f"Platform: {platform.system()}")
'''
    
    result = vm.run(f"python3 -c '{python_code}'")
    print(result.output)

File Operations

with SmolVM() as vm:
    # Create directory
    vm.run("mkdir -p /app/data")
    
    # Write file
    vm.run("echo 'Hello World' > /app/data/test.txt")
    
    # Read file
    result = vm.run("cat /app/data/test.txt")
    print(result.output)  # Hello World
    
    # Check file exists
    result = vm.run("test -f /app/data/test.txt && echo 'exists'")
    print(result.output)  # exists

Network Operations

with SmolVM() as vm:
    # Install curl
    vm.run("apk add --no-cache curl")
    
    # Test connectivity
    result = vm.run("curl -s https://api.github.com/zen", timeout=10)
    if result.ok:
        print(f"GitHub says: {result.output}")
    
    # Download file
    vm.run(
        "curl -L -o /tmp/data.json https://api.example.com/data",
        timeout=30
    )

SSH Connection Management

SmolVM handles SSH connections automatically:
  1. Lazy Connection: SSH client is created on first run() call
  2. Connection Reuse: Same SSH client is reused for all commands
  3. Automatic Reconnection: Handles connection failures gracefully
  4. Cleanup: Connections are closed when VM stops or context exits

Waiting for SSH

For custom boot sequences, explicitly wait for SSH:
vm = SmolVM(config)
vm.start()

# Wait up to 60 seconds for SSH to be ready
vm.wait_for_ssh(timeout=60.0)

# Now safe to run commands
result = vm.run("hostname")

SSH Commands for External Tools

Get ready-to-run SSH command strings:
with SmolVM() as vm:
    commands = vm.ssh_commands(
        ssh_user="root",
        key_path="~/.smolvm/keys/id_ed25519"
    )
    
    print(commands["ssh"])
    # ssh -i ~/.smolvm/keys/id_ed25519 [email protected]
    
    print(commands["scp_to_guest"])
    # scp -i ~/.smolvm/keys/id_ed25519 <local> [email protected]:<remote>

Checking Command Capability

Before running commands, verify SSH support:
if vm.can_run_commands():
    result = vm.run("whoami")
else:
    print("This VM doesn't support command execution")
    print("Rebuild with SSH_BOOT_ARGS or use SmolVM() auto-config")
Command execution requires:
  • VM booted with init=/init in boot args
  • SSH server running in the guest
  • Network connectivity
Auto-configured VMs and ImageBuilder images have SSH by default. Custom images without SSH support cannot execute commands.

Performance Tips

1

Batch related commands

Chain commands with && instead of multiple run() calls:
# Faster: single SSH session
vm.run("cmd1 && cmd2 && cmd3")

# Slower: three SSH sessions
vm.run("cmd1")
vm.run("cmd2")
vm.run("cmd3")
2

Use raw mode when possible

Skip shell initialization for simple commands:
vm.run("hostname", shell="raw")  # Faster
3

Set appropriate timeouts

Don’t use unnecessarily long timeouts:
vm.run("echo hi", timeout=5)  # Quick command
vm.run("apt-get update", timeout=60)  # Longer operation

Next Steps

Environment Variables

Manage persistent environment variables for commands

Port Forwarding

Expose guest services to the host

AI Agent Integration

Use command execution for AI agent tools

Build docs developers (and LLMs) love