Implement the 2.8.0 workspace milestone with named snapshots and full-sandbox reset across the CLI, Python SDK, and MCP server. Persist the immutable baseline plus named snapshot archives under each workspace, add workspace reset metadata, and make reset recreate the sandbox while clearing command history, shells, and services without changing the workspace identity or diff baseline. Refresh the 2.8.0 docs, roadmap, and Python example around reset-over-repair, then validate with uv lock, UV_CACHE_DIR=.uv-cache make check, UV_CACHE_DIR=.uv-cache make dist-check, and a real guest-backed create/snapshot/reset/diff smoke test outside the sandbox.
7.2 KiB
Install
Support Matrix
Supported today:
- Linux x86_64
- Python 3.12+
uv/dev/kvm
Optional for outbound guest networking:
ipnftoriptables- privilege to create TAP devices and configure NAT
Not supported today:
- macOS
- Windows
- Linux hosts without working KVM at
/dev/kvm
If you do not already have uv, install it first:
python -m pip install uv
Use these command forms consistently:
- published package without install:
uvx --from pyro-mcp pyro ... - installed package:
pyro ... - source checkout:
uv run pyro ...
Fastest Evaluation Path
Use either of these equivalent evaluator paths:
# Package without install
uvx --from pyro-mcp pyro doctor
uvx --from pyro-mcp pyro env list
uvx --from pyro-mcp pyro env pull debian:12
uvx --from pyro-mcp pyro run debian:12 -- git --version
# Already installed
pyro doctor
pyro env list
pyro env pull debian:12
pyro run debian:12 -- git --version
If you are running from a repo checkout instead, replace pyro with uv run pyro.
1. Check the host first
uvx --from pyro-mcp pyro doctor
Expected success signals:
Platform: linux-x86_64
Runtime: PASS
KVM: exists=yes readable=yes writable=yes
Environment cache: /home/you/.cache/pyro-mcp/environments
Capabilities: vm_boot=yes guest_exec=yes guest_network=yes
Networking: tun=yes ip_forward=yes
If Runtime: FAIL, stop here and use troubleshooting.md.
2. Inspect the catalog
uvx --from pyro-mcp pyro env list
Expected output:
Catalog version: 2.8.0
debian:12 [installed|not installed] Debian 12 environment with Git preinstalled for common agent workflows.
debian:12-base [installed|not installed] Minimal Debian 12 environment for shell and core Unix tooling.
debian:12-build [installed|not installed] Debian 12 environment with Git and common build tools preinstalled.
3. Pull the default environment
uvx --from pyro-mcp pyro env pull debian:12
The first pull downloads an OCI environment from public Docker Hub, requires outbound HTTPS
access to registry-1.docker.io, and needs local cache space for the guest image. See
host-requirements.md for the full host requirements.
Expected success signals:
[pull] phase=install environment=debian:12
[pull] phase=ready environment=debian:12
Pulled: debian:12
...
4. Run one command in a guest
uvx --from pyro-mcp pyro run debian:12 -- git --version
Expected success signals:
[run] phase=create environment=debian:12
[run] phase=start vm_id=...
[run] phase=execute vm_id=...
[run] environment=debian:12 execution_mode=guest_vsock exit_code=0 duration_ms=...
git version ...
The guest command output and the [run] ... summary are written to different streams, so they
may appear in either order in terminals or capture tools. Use --json if you need a
deterministic structured result.
If guest execution is unavailable, the command fails unless you explicitly pass
--allow-host-compat.
5. Optional demo proof point
uvx --from pyro-mcp pyro demo
pyro demo proves the one-shot create/start/exec/delete VM lifecycle works end to end.
Example output:
{
"cleanup": {
"deleted": true,
"reason": "post_exec_cleanup",
"vm_id": "..."
},
"command": "git --version",
"environment": "debian:12",
"execution_mode": "guest_vsock",
"exit_code": 0,
"stdout": "git version ...\n"
}
For a fuller copy-pasteable transcript, see first-run.md.
When you are done evaluating and want to remove stale cached environments, run pyro env prune.
Installed CLI
If you already installed the package, the same evaluator path works with plain pyro ...:
uv tool install pyro-mcp
pyro --version
pyro doctor
pyro env list
pyro env pull debian:12
pyro run debian:12 -- git --version
After the CLI path works, you can move on to:
- persistent workspaces:
pyro workspace create debian:12 --seed-path ./repo - live workspace updates:
pyro workspace sync push WORKSPACE_ID ./changes - baseline diff:
pyro workspace diff WORKSPACE_ID - snapshots and reset:
pyro workspace snapshot create WORKSPACE_ID checkpointandpyro workspace reset WORKSPACE_ID --snapshot checkpoint - host export:
pyro workspace export WORKSPACE_ID note.txt --output ./note.txt - interactive shells:
pyro workspace shell open WORKSPACE_ID - long-running services:
pyro workspace service start WORKSPACE_ID app --ready-file .ready -- sh -lc 'touch .ready && while true; do sleep 60; done' - MCP:
pyro mcp serve - Python SDK:
from pyro_mcp import Pyro - Demos:
pyro demoorpyro demo --network
Persistent Workspace
Use pyro workspace ... when you need repeated commands in one sandbox instead of one-shot pyro run.
pyro workspace create debian:12 --seed-path ./repo
pyro workspace sync push WORKSPACE_ID ./changes --dest src
pyro workspace exec WORKSPACE_ID -- cat src/note.txt
pyro workspace diff WORKSPACE_ID
pyro workspace snapshot create WORKSPACE_ID checkpoint
pyro workspace reset WORKSPACE_ID --snapshot checkpoint
pyro workspace reset WORKSPACE_ID
pyro workspace export WORKSPACE_ID src/note.txt --output ./note.txt
pyro workspace shell open WORKSPACE_ID
pyro workspace shell write WORKSPACE_ID SHELL_ID --input 'pwd'
pyro workspace shell read WORKSPACE_ID SHELL_ID
pyro workspace shell close WORKSPACE_ID SHELL_ID
pyro workspace service start WORKSPACE_ID web --ready-file .web-ready -- sh -lc 'touch .web-ready && while true; do sleep 60; done'
pyro workspace service start WORKSPACE_ID worker --ready-file .worker-ready -- sh -lc 'touch .worker-ready && while true; do sleep 60; done'
pyro workspace service list WORKSPACE_ID
pyro workspace service status WORKSPACE_ID web
pyro workspace service logs WORKSPACE_ID web --tail-lines 50
pyro workspace service stop WORKSPACE_ID web
pyro workspace service stop WORKSPACE_ID worker
pyro workspace logs WORKSPACE_ID
pyro workspace delete WORKSPACE_ID
Workspace commands default to the persistent /workspace directory inside the guest. If you need
the identifier programmatically, use --json and read the workspace_id field. Use --seed-path
when the workspace should start from a host directory or a local .tar / .tar.gz / .tgz
archive. Use pyro workspace sync push for later host-side changes to a started workspace. Sync
is non-atomic in 2.8.0; if it fails partway through, prefer pyro workspace reset to recover
from baseline or one named snapshot. Use pyro workspace diff to compare the current workspace
tree to its immutable create-time baseline, pyro workspace snapshot * to capture named
checkpoints, and pyro workspace export to copy one changed file or directory back to the host. Use
pyro workspace exec for one-shot commands and pyro workspace shell * when you need an
interactive PTY that survives across separate calls. Use pyro workspace service * when the
workspace needs long-running background processes with typed readiness probes. Service metadata and
logs stay outside /workspace, so the service runtime itself does not show up in workspace diff or
export results.
Contributor Clone
git lfs install
git clone <repo>
cd pyro
git lfs pull
make setup