Skip to main content

Sandboxes And Previews

Sandbox commands validate and start runtime environments for a workspace. Preview commands expose selected service ports through private tailnet URLs.

Sandbox Commands​

x4 sandbox run "frontend, backend, and admin dashboard"
x4 sandbox up
x4 sandbox wait
x4 sandbox status
x4 sandbox logs
x4 sandbox down
x4 sandbox destroy
x4 sandbox clear

x4 sandbox run is the agentic, goal-first interface. It asks the X4 AI harness to prepare a runnable profile for the current workspace goal, validates the proposed registry profile, writes it, and then calls the same deterministic x4 sandbox up runner.

If startup or readiness fails, sandbox run collects the failure message, sandbox state, remote SSH logs, and Docker Compose logs when available. It then starts another AI profile attempt with that feedback. The default limit is three attempts; change it with --ai-attempts <count>. Each attempt writes a separate harness run under .x4/ai/runs/, and failed sandbox state is cleaned before the next attempt. The AI still cannot run arbitrary shell or change the selected repo set; it can only propose a revised validated sandbox profile.

x4 sandbox run "frontend, backend, and admin dashboard" \
--repo-env-source web=/path/to/web/.env.test \
--repo-env-source api=/path/to/api/.env.test \
--ai-attempts 3

Use x4 sandbox up when you already know the profile and want a deterministic scriptable command with no AI preparation.

Common startup:

x4 sandbox up \
--profile azure-remote \
--wait

azure-remote and env-file are metadata-only starter profiles unless the registry adds services. They validate workspace/env wiring and write sandbox metadata, but they do not start frontend, API, worker, database, or dashboard servers.

For a user-ready sandbox, add a profile with sandboxProfiles.<id>.services[], then run it on a host with Docker Compose:

x4 sandbox up \
--profile local-preview \
--repo-env-source app=/path/to/app/.env.test \
--repo-env-source api=/path/to/api/.env.test \
--filter-forbidden-env \
--serve-preview \
--preview-backend tailnet-proxy \
--wait

If the current host is a control server without Docker, run the same profile on a Docker-capable X4 worker/testbox instead:

x4 sandbox up \
--backend ssh \
--target x4-testbox-standard-1 \
--profile local-preview \
--serve-preview \
--preview-backend tailnet-proxy \
--wait

Inspect the running sandbox:

x4 sandbox status
x4 sandbox logs --tail 100

x4 sandbox status prints the profile, compose project, local service URLs, private preview routes, runtime env file paths, and Docker Compose state. Secret values are never printed. For service profiles, status also checks Docker for X4-labeled containers before it reports a sandbox as running. If the workspace state says running but the containers are gone or stopped, X4 marks the sandbox and preview stopped and hides service and preview URLs from the normal status output.

AI can draft the first service profile when the selected workspace repos do not have a deterministic setup yet. It does not select the repos; it infers startup commands, ports, routes, and dependencies for the repo set already in the workspace:

x4 ai sandbox-plan --entry "$PWD" --run
x4 ai sandbox-profile \
--entry "$PWD" \
--profile local-preview \
--ai-engine codex-sdk \
--write
x4 registry validate --registry ./registry/x4-pilot-registry.yaml

The model returns strict JSON for a registry profile. X4 validates the proposed repo ids, service ids, commands, ports, preview routes, and inline environment values before writing anything to the registry.

For the longer-term tool loop and Mastra harness boundary, see AI Harness.

For trial workflows and lower-level debugging, sandbox up also accepts an experimental --ai flag. It is shorthand for generating and writing the selected profile with x4 ai sandbox-profile --write, then continuing with normal deterministic sandbox startup. x4 sandbox run is the preferred human-facing wrapper around this shape:

x4 sandbox up \
--profile local-preview \
--ai \
--ai-engine codex-sdk \
--backend ssh \
--target x4-testbox-standard-1 \
--serve-preview \
--preview-backend tailnet-proxy \
--wait

--ai does not execute arbitrary AI output. AI output must still validate as a registry sandbox profile before sandbox up runs. The AI goal, prompt, response, validated proposal, and run state are written under .x4/ai/runs/<run-id>/.

AI engines:

EngineUse
codex-sdkPreferred when the host is already authenticated with Codex/ChatGPT. No X4 API key is needed.
direct-modelUses the X4 configured OpenAI-compatible or Azure OpenAI chat-completions provider.

--ai always initializes a Mastra Harness session with inspect, propose-profile, and verify modes before running the selected engine.

For remote sandbox execution:

x4 sandbox up \
--backend ssh \
--target x4-testbox-standard-1 \
--profile local-preview \
--install eager \
--git-auth app

Clearing Running Sandboxes​

Use destroy when you are cleaning the current workspace:

x4 sandbox destroy --force --prune-artifacts

Use clear when a Docker host or worker has leftover X4 sandbox containers from multiple workspaces. Always inspect first:

x4 sandbox clear --all --dry-run

Then remove only X4-labeled sandbox resources on the current Docker host:

x4 sandbox clear --all --force

For a worker/testbox:

x4 sandbox clear \
--target x4-testbox-standard-1 \
--all \
--dry-run

x4 sandbox clear \
--target x4-testbox-standard-1 \
--all \
--force

Narrow the cleanup when needed:

x4 sandbox clear --all --repo-set x4-demo --dry-run
x4 sandbox clear --all --workspace-id x4-demo-app-npm-2026-06-17-259515 --force

sandbox clear removes Docker containers carrying X4 labels, their Compose networks and volumes, and X4 tailnet preview proxy processes. It does not remove repo worktrees. Use x4 cleanup --dry-run for workspace worktree cleanup. After a forced clear, x4 sandbox status should report the affected workspace as stopped rather than continuing to show live preview URLs.

Preview Commands​

x4 preview up
x4 preview serve
x4 preview down

Tailnet preview:

x4 preview serve \
--host x4-devbox-main.tailbba365.ts.net \
--http-port 80

URL Safety Rule​

X4 must not post these as tester-facing GitHub URLs:

  • localhost
  • 127.0.0.1
  • 0.0.0.0
  • Docker-internal hostnames
  • container-only URLs
  • placeholder preview URLs

GitHub comments should include only recognized private tailnet URLs, such as Tailscale 100.64.0.0/10 addresses or MagicDNS .ts.net hostnames. Backend services should post health/API/log evidence instead of fake frontend previews.