How VSH works¶
Think of VSH as a transaction engine for workspace transformations, not a shell with a dry-run flag. The guest executes real supported operations. Their effects are recorded in a copy-on-write virtual filesystem and only a trusted committer can apply the final change set to the host.
flowchart TD
A[Source + intent + budgets] --> B[Fresh workspace snapshot]
B --> C[Monty program and active VirtualFs overlay]
C --> D[Canonical diff + dependencies + policy]
D --> E{Decision}
E -->|Denied| F[Return evidence; do not apply]
E -->|Auto-approved preview| G[Retain in live runtime]
E -->|Needs review| H[Persist pending artifact]
H --> I[Trusted approval of exact transaction]
I --> J[Reserve and revalidate]
G --> J
J --> K[Journal, apply, verify]
The runtime owns capabilities¶
Runtime.open opens the configured workspace and protected durable storage. The
default data directory is .vsh-runtime/data. It rejects unsafe overlap and aliasing,
establishes worker supervision, and runs startup recovery. It does not merely save a
path string for later unrestricted filesystem operations.
Reuse a runtime for repeated work. This reuses capabilities and clean worker processes; it does not reuse a stale snapshot or carry an earlier preview's overlay forward.
Every request captures a new base¶
Snapshot capture eagerly traverses metadata for the entire configured workspace. Contents are lazy: a read materializes bytes only when needed, verifies their identity against the captured stamp, and stores immutable content. The snapshot is not an eager full-byte copy and is not a retained operating-system snapshot.
Only the root .vsh-runtime directory is excluded by this capture path. .gitignore
does not automatically exclude .venv, target, node_modules or other large trees.
Choose the smallest workspace root that contains all required inputs and outputs.
The guest sees one active overlay¶
Monty runs a constrained Python subset in a supervised subprocess. Supported pathlib
operations suspend into typed calls answered by Rust. In VSH,
the ten VSH functions use the same mechanism and the
same VirtualFs instance.
vsh_write('/workspace/result.txt', 'first')
from pathlib import Path
assert Path('/workspace/result.txt').read_text() == 'first'
Path('/workspace/result.txt').write_text('second')
assert vsh_read('/workspace/result.txt') == 'second'
There is no inner runtime, nested MCP request or second simulation. Intermediate
generated files are visible within this program. A separate preview() starts from
the host again, so dependent staging steps belong in one program.
Effects and final changes are different evidence¶
The effect ledger records attempted operations and observed dependencies. The canonical diff compares final virtual state to the base. Creating and then deleting a temporary file can yield no final change, while still recording effects. A semantic rename can escalate policy even when it only rearranged newly generated files.
The transaction identity binds source, intent, snapshot, policy/configuration, dependencies and canonical diff. Approvals refer to this exact artifact. Changing source and rerunning creates another execution, not an update to an existing approval.
Only commit changes user files¶
Preview always stops before application. Auto mode proceeds only for deterministic auto-approval. A pending transaction needs an independent trusted-host approval; hard policy denial cannot be overridden with approval.
Commit reserves the transaction once, serializes the same-workspace mutation window, revalidates recorded reads/writes and capabilities, applies a journaled plan, and verifies the result. Input drift produces a stale failure. Interrupted commit may require recovery; do not equate this with database-wide isolation from arbitrary external processes or instantaneous multi-file visibility.
One engine, separate adapters¶
| Layer | Responsibility |
|---|---|
| Rust runtime and component crates | Snapshot, execution dispatch, diff, policy, state, commit, recovery |
| Python PyO3 binding | One native call per request; typed result and exception conversion |
| CLI / MCP adapter | Request construction and JSON-safe receipt projection |
| Your trusted application | Authentication, workspace selection, budget ceilings, reviewer decisions |
The guest has no exposed shell, network, environment or host-mount capability. This is not a general-purpose VM or kernel isolation boundary. Read security before embedding VSH around untrusted users or agent-produced code.