Transfer Modes & VM Isolation
Transfer Modes & VM Isolation
mentu provides two orthogonal isolation axes: transfer modes control where files live during execution, and VM isolation controls where code runs. They compose independently, so you can use either, both, or neither.
Transfer Modes
A transfer mode determines how mentu creates an isolated copy of your project before running a recipe. Four modes are available:
| Mode | What it does | When to use |
|---|---|---|
none |
Runs in-place on the working directory | Quick tasks, trusted recipes |
worktree |
Creates a git worktree, runs there, merges back via canary | Default for pipelines, any multi-step work |
mirror |
Pushes to a bare repo clone, works there, fetches back | Remote targets or when worktrees are unavailable |
rsync |
Rsync-based copy with standard excludes (.git, .build, node_modules) | Large repos where worktree is slow, or non-git projects |
CLI usage
All three execution commands accept --transfer:
mentu sequence my-recipe --transfer worktree
mentu pipeline my-pipeline --transfer mirror
mentu compound my-compound --transfer rsyncThe --worktree flag is shorthand for --transfer worktree:
mentu sequence my-recipe --worktreeRecipe-level
Set the transfer mode in the recipe JSON so it always runs isolated:
{
"name": "my-recipe",
"transfer_mode": "worktree",
"steps": [...]
}Resolution order
--transferon the CLI (highest priority)--worktreeon the CLI (shorthand for--transfer worktree)transfer_modein the recipe JSONnoneif nothing else is set (in-place execution)
If the CLI passes --transfer, it wins. Otherwise the recipe's transfer_mode field is used. If neither is set, execution runs in-place.
VM Isolation
The --vm flag sends each step's tool execution to a VM sandbox via mentu-runtime. The agent (Claude) runs on the host, but all tool calls (file reads, writes, bash commands) execute inside the VM. Recipe orchestration stays on the host.
mentu sequence my-recipe --vmIf the mentu-runtime daemon is not running, mentu starts it automatically. If the daemon is unavailable, the step runs without VM sandboxing and prints a warning.
Recipe-level and step-level
VM isolation can be set at the recipe level, overridden per step:
{
"name": "my-recipe",
"vm": true,
"steps": [
{ "label": "trusted-step", "vm": false },
{ "label": "untrusted-step", "vm": true }
]
}Resolution order
--vmon the CLI (highest priority, applies to all steps)vmfield on a step (per-step override)vmfield on the recipe (recipe-level default)falseif nothing else is set (no VM)
The CLI flag is a global override. If not set, each step checks its own vm field, then falls back to the recipe-level vm field, then defaults to false.
Composition
Both axes compose. --transfer worktree --vm creates a git worktree AND runs each step in a VM sandbox. They are independent:
mentu sequence audit-pipeline --transfer worktree --vmThe two axes form a 2x4 grid. Rows are VM isolation, columns are transfer mode.
none |
worktree |
mirror |
rsync |
|
|---|---|---|---|---|
| VM off | in-place | isolated copy | bare-repo copy | rsync copy |
| VM on | VM only | VM + isolated | VM + bare-repo | VM + rsync |
Every cell is a valid mode. Pick the row that matches your trust in the tool calls and the column that matches your filesystem needs.
Pick each axis based on what you need:
- Filesystem isolation only (
--transfer worktree): protect your working tree from multi-step recipes that create, modify, or delete files. Changes merge back only if the canary passes. - Process isolation only (
--vm): run untrusted tool calls in a sandbox while keeping files in-place. - Both (
--transfer worktree --vm): full isolation. The recipe operates on an isolated copy, and tool execution is sandboxed.
Canary Checks
When using worktree, mirror, or rsync, mentu runs a canary before merging changes back to your working tree. The canary runs these checks in order:
- Build (
swift build -c release). Only runs if Swift files changed. Skipped for recipes that only produce docs or reports. - Tests (
swift test). Only runs if a test target exists and Swift files changed. - CIR contradiction check. Fails if unresolved contradictions exist in the CIR store.
- Ratchet check. If
ratchets.jsonexists, verifies quality metrics have not regressed. - Plugin
before_mergehook. Any registered plugin can abort the merge. - Git conflict check. Attempts direct merge, falls back to rebase-then-fast-forward if the base branch moved.
If any check fails, changes stay in the isolated branch. Nothing merges to your working tree.
When a canary fails during a sequence, mentu automatically re-runs the last step up to 3 times with the canary error injected as MENTU_CANARY_ERROR so the agent can attempt a fix. If all 3 attempts fail, the branch is preserved for manual resolution.
Manual recovery
If a canary blocks the merge, the worktree branch is preserved:
# See what the agent produced
git log mentu/<recipe-name>
# Merge manually after fixing
git merge mentu/<recipe-name>
# Or discard
git branch -d mentu/<recipe-name>Workspace Locking
When running in none mode (in-place), mentu acquires an exclusive workspace lock. A second sequence targeting the same directory will fail with an error. Transfer modes avoid this because each sequence gets its own isolated copy, so multiple sequences can run concurrently.
# These can run simultaneously. Each gets its own worktree.
mentu sequence recipe-a --transfer worktree &
mentu sequence recipe-b --transfer worktree &In Scripts
mentu.sequence.run('my-recipe', {
transfer: 'worktree',
vm: true,
vars: { TARGET: 'production' },
});See SDK Reference for the full SequenceRunOptions type.