If you can't run winapp yourself (no shell, or the command is denied), give the user the exact winapp command(s) for their project instead of only describing the steps.
Before acting
- Confirm the user wants Sandbox execution. Do not drop
--on sandboxto bypass an error. - Builds, project evaluation, and restore still run on the host. Do not build untrusted projects on the assumption that Sandbox isolates them.
- Windows supports one Sandbox; all apps inside it share a user, desktop, and state. Do not treat separate workflows as mutually isolated.
- Windows 11 24H2+ on a supported edition and hardware virtualization are required. Guest winapp supports x64/Arm64; x86 apps need guest support and matching dependencies.
- winapp only checks host prerequisites: it does not enable features, install the
client, request elevation, or reboot.
--on sandboxselects the target, not setup consent. - On
sandbox_setup_required, explain the required Windows feature and restart. Decide whether to offer agent-assisted setup or give the user manual steps; obtain explicit approval before running the suggested command in an elevated terminal. Use/NoRestartand let the user choose when to reboot:dism.exe /Online /Enable-Feature /FeatureName:Containers-DisposableClientVM /All /NoRestart. - On
sandbox_setup_requires_restart, ask the user to save work and restart when ready. Never restart automatically or treat setup approval as reboot approval. - On
sandbox_setup_incomplete, direct the user to open Windows Sandbox from Start and finish its client setup/update. Do not repeatedly retry an unchanged prerequisite. - Connection or reconnect may briefly take focus; do not promise zero desktop interruption.
- Existing Sandbox instances are reused and changed, not discarded. Never close one
or run
wsb stopwithout user consent. Closing the window of a Sandbox winapp started asks for confirmation, then ends it and discards its state; the next command starts a fresh one. A Sandbox started withwsb startkeeps running when its window is closed.
Launch, inspect, act, verify
winapp run . --on sandbox --detach
winapp ui list-windows --on sandbox
winapp ui inspect --on sandbox -a MyApp
winapp ui invoke --on sandbox SubmitButton -a MyApp
winapp ui screenshot --on sandbox -a MyApp -o .\result.png
- Use
--detachwhen subsequent commands must inspect the running app; without it,runwaits for exit. Use--jsonwhen consuming the launch result programmatically. - Replace
MyAppwith the discovered name or copy the returnedUiTargetArgs. Keep--on sandboxon every guest UI command, including commands using a PID/HWND. - Inspect before acting and verify the result. Use
winapp-ui-automationfor selectors and input methods. Real input and recording need a connected, nonminimized client; read-only inspection can still work when input cannot. - Rebuild by rerunning the same command. Add
--cleanonly when clearing that app's data is intended.--debug-outputis supported only for packaged Sandbox apps. - Rediscover targets after the Sandbox is recreated. A detached unpackaged app can also end during guest-agent repair; rerun it if it disappears.
For parallel packaged worktrees, opt into
winapp run . --unique-identity --on sandbox --detach --json. Use the returned
UiTargetArgs. All copies share one Sandbox. See
unique identity for parallel checkouts.
Coordinate a recording with actions
Choose one explicit workflow ID and inject the same value into every cooperating invocation, including fresh tool-call shells. Different workflows need different IDs.
Recording invocation:
$env:WINAPP_UI_WORKFLOW_ID = 'myapp-checkout-01'
winapp ui record --on sandbox -a MyApp --duration-sec 20 --frames -o .\checkout.mp4
While it records, in another invocation:
$env:WINAPP_UI_WORKFLOW_ID = 'myapp-checkout-01'
winapp ui invoke --on sandbox SubmitButton -a MyApp
After both recording and actions finish:
$env:WINAPP_UI_WORKFLOW_ID = 'myapp-checkout-01'
winapp ui yield --on sandbox
The forwarded identity is hashed and scoped to this Sandbox generation. Without an ID, each command is a one-shot that releases immediately; a no-ID recording blocks other desktop-changing workflows for its duration. An explicit ID keeps a four-second idle grace. Yield at the end instead of making another workflow wait. After a reasoning gap, inspect again and reopen transient UI before acting.
Choose evidence by scope
winapp target snapshot sandbox
winapp target screenshot sandbox -o .\sandbox.png
winapp target record sandbox --duration-sec 20 --frames -o .\sandbox.mp4
- Start with
target snapshotwhen an app never appeared or a command failed. It does not create a VM, reconnect the client, or repair an agent. For error windows or ambiguous readiness, follow the desktop readiness guidance; do not close windows or reconnect automatically to make a snapshot succeed. target screenshot/target recordcapture the native guest desktop, not the host client window.ui screenshot/ui record --on sandboxcapture an app window.- Outputs, including default filenames when
-ois omitted, are delivered to the host.--framesreturns a frame directory alongside the MP4 after recording finishes. - Use the PNG's native coordinates plus its reported screen origin for guest input.
For scaled recording frames, use
coordinates.sourceBoundsandcoordinates.contentRectfrom the JSON/manifest, not raw image coordinates. The mapping is documented in Sandbox capture.display_changedmeans capture stopped before the desktop bounds changed its mapping. - Prefer a positive
--duration-secfor unattended CLI recording. npm helpers requiredurationSec(integer 1–86400); abort signals cancel forcefully, not gracefully. - Choose a fresh output path. Request
--overwriteonly when replacement is intended: it replaces the MP4 after the new take finishes and archives any previous frame directory. Do not delete partial evidence to make a retry pass. - Read
stopReason, preserved paths, andrecoveryHintbefore reporting success. Acapture_unavailablestop can leave useful evidence but is not a full take. Ctrl+C can finalize withstopReason: cancelledand a successful exit. - If delivery fails, keep the Sandbox running and follow the error's recovery action. Preserve both the received host files and guest originals until recovery finishes.
- Treat frames, screenshots, and video as potentially sensitive.
Guest setup and file transfer
$copy = winapp target push sandbox .\setup.ps1 Setup\setup.ps1 --json | ConvertFrom-Json
winapp target exec sandbox --cwd (Split-Path -Parent $copy.targetPath) -- powershell -ExecutionPolicy Bypass -File .\setup.ps1
winapp target pull sandbox Results .\results
Use target exec only for necessary setup or diagnostics, not instead of winapp run.
It streams the command's output and is not a full terminal. The example's execution-policy
override is scoped to that PowerShell process; run only a trusted script.
Push/pull target paths are relative to the target's managed work area; absolute, rooted, and UNC
paths are rejected. A single-file destination includes the filename. Use the reported
resolved guest path to choose --cwd (its parent directory for a single file).
See the transfer guide
for path reporting and missing-root errors. Directory copies skip linked entries; directly named
linked sources and paths through destination links are rejected. Deployment rejects links.
Cleanup and recovery
winapp unregister . --on sandbox
Pass the project or folder you passed to run (with or without --unique-identity),
or its manifest; a .cs input isn't supported here. This does not stop the Sandbox.
Never use --force to bypass target ownership.
Follow the error's userAction, not just its exit number: infrastructure failures and
an application's own exit can both be 70. Human setup progress goes to stderr and is
suppressed with --quiet/--json.
- Prerequisite errors: follow the setup guidance above; keep elevation and restart under user control.
- Input unavailable: restore the existing client or use the error's reconnect command.
- "Only one running instance of Windows Sandbox is allowed" from the Start menu: a Sandbox
is already running. Point the user to Windows Sandbox in the taskbar; if it has no
window,
wsb listthenwsb connect --id <id>. Never stop it without consent. - Incompatible CLI: follow the error; upgrade the installed CLI through its install method,
not
winapp update. Obtain consent before stopping a Sandbox (wsb stop --id <id>) for a version change; it works however the Sandbox was started. - Missing/unsupported runtime: use the named requirement and configuration in the error. Do not assume any newer same-major runtime is compatible or substitute architectures.
- Folder share refused (
sandbox_transport_failed,0x80070005): Sandbox shares as SYSTEM. Grant it access to the reported folder with the error'sicaclscommand, then retry. - Incomplete deployment/transfer: retry. Busy: wait. Partial recording: keep reported evidence.
- Package conflict: do not remove external or inbox packages to force registration.
See Windows Sandbox execution for prerequisites, runtime support, lifecycle, output recovery, and known limitations.