mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-18 05:39:50 +08:00
* feat(workspace): implement workspace model (Phase 1 of RFC 0011) Implements workspace and membership model providing hard isolation boundaries for multi-player OpenShell deployments. Workspace CRUD with Kubernetes-style Terminating phase for graceful deletion. All resources scoped by workspace via ObjectMeta. Membership RPCs for workspace access control. Persistence migration shifts name uniqueness to (object_type, workspace, name). Provider profiles support platform and workspace scoping. Service routing uses workspace-prefixed DNS labels. Inference routes renamed and workspace-scoped with DeleteInferenceRoute RPC. Python SDK with WorkspaceClient, two-method list pattern (workspace-scoped and for_all_workspaces), and workspace parameter on all methods. CLI workspace flags, TUI workspace cycling. K8s driver filters unmanaged CRs and uses delete preconditions. Podman driver uses immutable container IDs. Label serialization fixed across all put_if call sites. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(cli): delegate sandbox upload command to existing upload function The standalone `sandbox upload` command reimplemented upload logic inline with two bugs: it used `Path::exists()` which follows symlinks (rejecting dangling symlinks), and it ran git-aware filtering on symlink sources. The `run::sandbox_upload()` function already handles both cases correctly via `sandbox_upload_plan()`. Replace the inline logic with a call to the existing function. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(e2e): shorten sandbox names and fix test compatibility Shorten the sandbox name in initial_sparse_policy_is_acknowledged_as_loaded from 'e2e-2159-sparse-enrich' (22 chars) to 'e2e-sparse-enrich' (17 chars) to comply with MAX_ROUTABLE_NAME_LEN (19 chars). Also capture stderr in create_keep_with_args so future sandbox creation failures include the actual CLI error instead of reporting empty output. Signed-off-by: Derek Carr <decarr@redhat.com> * test(workspace): add test coverage for workspace CRUD and persistence isolation Add unit tests for workspace create happy path, get round-trip, get not-found, get empty-name rejection, already-exists error, and resolve_workspace not-found. Add persistence test proving cross-workspace name uniqueness (same name in different workspaces produces separate records). Add workspace name max-length boundary tests. Fix e2e harness to include stderr in name-parse-failure error path. Align Python e2e test_workspace_crud with try/finally pattern. Document provider profile catalog workspace scoping gap in RFC 0011. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(examples): update examples for workspace model compatibility Shorten sandbox names in demo scripts to fit the 19-character MAX_ROUTABLE_NAME_LEN limit: policy-demo prefix to pd-, multi-agent notepad derives a short SANDBOX_TAG from the run ID, governance interceptor uses gs-PID-RANDOM. Update vscode-remote-sandbox.md SSH host aliases from openshell-{name} to openshell-{name}.{workspace} format. Signed-off-by: Derek Carr <decarr@redhat.com> * feat(sdk): add workspace-scoped client and workspace CRUD Add WorkspaceScopedClient modeled after kube::Api::namespaced — captures workspace once and injects it into every sandbox request. Add workspace CRUD methods (create, get, list, delete) and list_sandboxes_all_workspaces on OpenShellClient. Extend SandboxRef with workspace field and add WorkspaceRef type. Include mock tests for all new operations. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(lint): resolve clippy warnings in workspace test assertions Signed-off-by: Derek Carr <decarr@redhat.com> * fix(docs): convert indented code blocks to fenced in RFC 0011 Signed-off-by: Derek Carr <decarr@redhat.com> * fix(lint): resolve clippy warnings and apply cargo fmt across workspace Auto-format with cargo fmt and fix clippy warnings exposed by the reformat: unnecessary qualifications, map_unwrap_or, identical match arms, unused variable prefix, dead code annotations, and let-unit-value in e2e harness. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(workspace): address workspace scoping issues from review - Add workspace field to settings JSON output (CLI) - Skip Podman containers missing workspace label instead of defaulting to empty string, matching K8s driver behavior - Add resource_version to list_by_scope SELECT in both SQLite and Postgres backends, with regression test - Gate PolicyLocalContext proposal/lookup routes on workspace readiness, returning 503 when workspace is not yet discovered - Block sandbox and provider creation in TUI all-workspaces mode - Clear workspace vectors in TUI reset_sandbox_state Signed-off-by: Derek Carr <decarr@redhat.com> * fix(workspace): make provider profile catalog workspace-aware Thread workspace through snapshot_catalog so the EffectiveProviderProfileCatalog enforces workspace boundaries on both read and write paths. UserProviderProfileSource now loads platform-scoped profiles (workspace "") plus the target workspace's profiles, preventing cross-workspace duplicate profile ID collisions that previously caused global catalog failures. Update RFC 0011 to reflect catalog scoping is implemented in Phase 1 rather than deferred to future work. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(persistence): include workspace column in atomic policy revision INSERT put_policy_revision_atomic omitted the workspace column from the INSERT into the objects table in both SQLite and Postgres backends, causing atomically-written policy revisions to lose their workspace association. Add workspace field to AtomicPolicyRevisionWrite and thread it through both backend INSERT statements, matching the non-atomic put_policy_revision path which already included it. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(proxy): skip ancestor walk when socket owner is the entrypoint collect_ancestor_identities walked the entire process tree above the entrypoint when the connecting process was the entrypoint itself, SHA256-hashing every ancestor binary (IDE, shell, container runtime). On dev machines with large binaries in the ancestor chain this exceeded the 30-second test timeout. When start_pid == stop_pid there are no intermediate ancestors to verify, so return an empty list immediately. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(workspace): make provider profile catalog scope-aware Allow the same profile ID at platform and workspace scopes by introducing layered catalog entries where workspace profiles shadow platform profiles. Add source and scope fields to the ProviderProfile proto and CLI output. Migrate List/Get handlers to the catalog, fixing divergence with runtime profile resolution. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(e2e): align podman e2e labels with centralized driver constants The podman driver moved its container labels to the centralized openshell.ai/ prefix, but the e2e test harness and cleanup script still referenced the old openshell.sandbox-* keys, causing the local_driver_token_restart test to fail on container lookup. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(e2e): align python profile isolation test with scope-aware catalog Platform profiles are now visible in workspace listings as fallbacks per the layered catalog design. Update the assertion to match. Signed-off-by: Derek Carr <decarr@redhat.com> * fix(workspace): honor profile_workspace in runtime profile resolution Runtime profile lookups now consult provider.profile_workspace via get_type_profile_for_scope. Providers created with --global-profile (profile_workspace="") resolve to the platform profile even when a workspace profile shadows the same ID. All 6 runtime call sites updated; type-only call sites remain scope-agnostic. Signed-off-by: Derek Carr <decarr@redhat.com> --------- Signed-off-by: Derek Carr <decarr@redhat.com>
449 lines
17 KiB
Plaintext
449 lines
17 KiB
Plaintext
---
|
||
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||
# SPDX-License-Identifier: Apache-2.0
|
||
title: "Manage Sandboxes"
|
||
sidebar-title: "Sandboxes"
|
||
description: "Create sandboxes, understand sandbox isolation, and manage the full sandbox lifecycle."
|
||
keywords: "Generative AI, Cybersecurity, Gateway, Sandboxing, AI Agents, Sandbox Management, CLI"
|
||
position: 1
|
||
---
|
||
|
||
A sandbox is the OpenShell data plane: a safe, private execution environment where an AI agent runs. Each sandbox combines runtime isolation with OpenShell policy controls that prevent unauthorized data access, credential exposure, and network exfiltration.
|
||
|
||
<Info>You need an active gateway before creating a sandbox.</Info>
|
||
|
||
## Create a Sandbox
|
||
|
||
Create a sandbox with a single command. For example, to create a sandbox with Claude, run:
|
||
|
||
```shell
|
||
openshell sandbox create -- claude
|
||
```
|
||
|
||
Every sandbox requires a gateway. Register or select one before running sandbox commands:
|
||
|
||
```shell
|
||
openshell gateway add http://127.0.0.1:18080 --local --name local
|
||
openshell gateway select local
|
||
```
|
||
|
||
### CPU and Memory
|
||
|
||
Set per-sandbox CPU and memory amounts with `--cpu` and `--memory`:
|
||
|
||
```shell
|
||
openshell sandbox create --cpu 2 --memory 4Gi -- claude
|
||
```
|
||
|
||
CPU values use Kubernetes-style quantities such as `500m`, `1`, or `2.5`.
|
||
Memory values use byte quantities such as `512Mi`, `4Gi`, or `8G`.
|
||
|
||
Docker and Podman apply these values as runtime limits. Kubernetes applies each
|
||
value as both the request and the limit so the scheduler reserves the same
|
||
amount the sandbox can use. The VM driver currently accepts these flags but
|
||
does not change VM allocation.
|
||
|
||
### Driver-Specific Configuration
|
||
|
||
Pass experimental driver-owned settings with `--driver-config-json`. The value
|
||
must be a JSON object keyed by driver name. The gateway forwards only the block
|
||
for its configured compute driver:
|
||
|
||
Nested keys inside each driver block use snake_case. The top-level envelope keys
|
||
are driver names, such as `kubernetes`, and are not part of the nested schema.
|
||
|
||
```shell
|
||
openshell sandbox create \
|
||
--driver-config-json '{"kubernetes":{"pod":{"runtime_class_name":"kata-containers","node_selector":{"pool":"gpu"}}}}' \
|
||
-- claude
|
||
```
|
||
|
||
Use this only for driver-specific fields that do not have a stable CLI flag.
|
||
Prefer stable flags such as `--cpu`, `--memory`, and `--gpu` when they cover
|
||
the same behavior.
|
||
|
||
### GPU Resources
|
||
|
||
To request GPU resources, add `--gpu`:
|
||
|
||
```shell
|
||
openshell sandbox create --gpu -- claude
|
||
```
|
||
|
||
Request a specific number of GPUs by passing a count to `--gpu`:
|
||
|
||
```shell
|
||
openshell sandbox create --gpu 2 -- claude
|
||
```
|
||
|
||
When you omit the count, OpenShell treats the request as `--gpu 1`.
|
||
Kubernetes honors counted `--gpu` requests by setting the `nvidia.com/gpu`
|
||
limit. Docker and Podman select the requested number of default NVIDIA CDI
|
||
devices in round-robin order. VM gateways accept only one GPU, either through
|
||
`--gpu` or `--gpu 1`; a single `gpu_device_ids` entry works with either form.
|
||
|
||
For Docker-backed sandboxes, GPU injection uses Docker CDI. If you enable Docker
|
||
CDI after the gateway starts, restart the gateway so OpenShell can detect the
|
||
updated Docker daemon capability.
|
||
|
||
Docker and Podman refresh the CDI inventory before validating or creating a
|
||
default GPU request, so CDI devices added or removed after the driver starts can
|
||
be reflected in later sandbox creates. On WSL2 all-only runtimes, the default
|
||
can fall back to `nvidia.com/gpu=all`; that fallback counts as one selectable
|
||
device.
|
||
|
||
Exact GPU device selection is driver-specific and still requires `--gpu`. For
|
||
Docker or Podman, pass CDI IDs through `cdi_devices`. The top-level key must
|
||
match the active driver; replace `docker` with `podman` when using Podman. CDI
|
||
IDs are treated as opaque strings. The list must not contain duplicate IDs, and
|
||
its length must match the effective GPU count:
|
||
|
||
```shell
|
||
openshell sandbox create \
|
||
--gpu \
|
||
--driver-config-json '{"docker":{"cdi_devices":["nvidia.com/gpu=0"]}}' \
|
||
-- claude
|
||
```
|
||
|
||
### Custom Containers
|
||
|
||
Use `--from` to create a sandbox from the base image, another pre-built sandbox name, a local directory, or a container image:
|
||
|
||
```shell
|
||
openshell sandbox create --from base
|
||
openshell sandbox create --from ollama
|
||
openshell sandbox create --from ./my-sandbox-dir
|
||
openshell sandbox create --from my-registry.example.com/my-image:latest
|
||
```
|
||
|
||
Bare names such as `base` and `ollama` resolve to images under `ghcr.io/nvidia/openshell-community/sandboxes`. Set `OPENSHELL_COMMUNITY_REGISTRY` when you need to use an internal mirror.
|
||
|
||
Local directories and Dockerfiles require a local gateway because the CLI builds
|
||
through the local Docker daemon. Use a registry image reference for remote
|
||
gateways.
|
||
|
||
## Base Sandbox Container
|
||
|
||
The `base` sandbox container is the default runtime image for standard OpenShell sandboxes unless the gateway overrides its default sandbox image. It is published as `ghcr.io/nvidia/openshell-community/sandboxes/base:latest` and maintained in the [OpenShell Community](https://github.com/NVIDIA/OpenShell-Community/tree/main/sandboxes/base) repository.
|
||
|
||
The base container includes common development tooling, supported agent CLIs, and the default sandbox policy. Use it when you want a general-purpose agent environment without a workflow-specific image:
|
||
|
||
```shell
|
||
openshell sandbox create --from base
|
||
```
|
||
|
||
For default policy coverage by agent, refer to [Default Policy](/reference/default-policy). For the supported agent list, refer to [Supported Agents](/about/supported-agents).
|
||
|
||
## Connect to a Sandbox
|
||
|
||
Open an SSH session into a running sandbox:
|
||
|
||
```shell
|
||
openshell sandbox connect my-sandbox
|
||
```
|
||
|
||
Launch VS Code or Cursor directly into the sandbox workspace:
|
||
|
||
```shell
|
||
openshell sandbox create --editor vscode --name my-sandbox
|
||
openshell sandbox connect my-sandbox --editor cursor
|
||
```
|
||
|
||
When `--editor` is used, OpenShell keeps the sandbox alive and installs an
|
||
OpenShell-managed SSH include file instead of cluttering your main
|
||
`~/.ssh/config` with generated host blocks.
|
||
|
||
## Execute a Command in a Sandbox
|
||
|
||
Run a one-shot command inside a running sandbox without opening an interactive shell:
|
||
|
||
```shell
|
||
openshell sandbox exec -n my-sandbox -- ls -la /workspace
|
||
```
|
||
|
||
Pipe stdin into the command:
|
||
|
||
```shell
|
||
echo "hello" | openshell sandbox exec -n my-sandbox -- cat
|
||
```
|
||
|
||
The command's exit code is propagated to the CLI, so `exec` works in scripts that check return codes.
|
||
|
||
Run an interactive shell with a TTY:
|
||
|
||
```shell
|
||
openshell sandbox exec -n my-sandbox --tty -- /bin/bash
|
||
```
|
||
|
||
OpenShell allocates a TTY automatically when both stdin and stdout are terminals. Force the behavior with `--tty` or disable it with `--no-tty`.
|
||
|
||
| Flag | Purpose |
|
||
| -------------- | -------------------------------------------------------- |
|
||
| `-n`, `--name` | Sandbox to target. |
|
||
| `--workdir` | Working directory for the command inside the sandbox. |
|
||
| `--timeout` | Command timeout in seconds. `0` disables the timeout. |
|
||
| `--tty` | Force TTY allocation. |
|
||
| `--no-tty` | Disable TTY allocation even when attached to a terminal. |
|
||
| `--env` | Set an environment variable for the command (`KEY=VALUE`, repeatable). |
|
||
|
||
## Set Environment Variables
|
||
|
||
Inject environment variables into the sandbox at creation time:
|
||
|
||
```shell
|
||
openshell sandbox create --env API_KEY=sk-test --env DEBUG=1 -- my-agent
|
||
```
|
||
|
||
Variables set with `--env` are available to all processes in the sandbox, including interactive shells and exec commands.
|
||
|
||
You can also set per-command environment variables with `sandbox exec`:
|
||
|
||
```shell
|
||
openshell sandbox exec -n my-sandbox --env MY_VAR=hello -- printenv MY_VAR
|
||
```
|
||
|
||
Per-command variables override the sandbox-level environment for that command only.
|
||
|
||
Environment variable names starting with `OPENSHELL_` are reserved. Keys must match `[A-Za-z_][A-Za-z0-9_]*`.
|
||
|
||
## Label a Sandbox
|
||
|
||
Attach labels when you create a sandbox to track ownership, environment, or workflow grouping:
|
||
|
||
```shell
|
||
openshell sandbox create --label env=dev --label team=platform -- claude
|
||
```
|
||
|
||
List only the sandboxes that match a label selector:
|
||
|
||
```shell
|
||
openshell sandbox list --selector env=dev
|
||
openshell sandbox list --selector env=dev,team=platform
|
||
```
|
||
|
||
The Python SDK accepts the same gateway labels and selectors. Labels passed to
|
||
`create` are stored on the gateway sandbox object and are returned on
|
||
`SandboxRef.labels`, so selector-based listing finds Python-created sandboxes:
|
||
|
||
```python
|
||
from openshell import SandboxClient
|
||
|
||
with SandboxClient.from_active_cluster() as client:
|
||
sandbox = client.create(workspace="default", name="deep-research-1", labels={"env": "dev", "team": "platform"})
|
||
assert sandbox.labels["team"] == "platform"
|
||
|
||
matches = client.list(workspace="default", label_selector="env=dev,team=platform")
|
||
assert sandbox.id in {s.id for s in matches}
|
||
```
|
||
|
||
## Expose Long Running Services
|
||
|
||
Service forwarding makes a long-running process inside a sandbox reachable through a gateway-managed URL. Use it for development servers, notebooks, dashboards, or other services that keep listening after the sandbox starts. Run the service on loopback inside the sandbox, expose its port, then open the URL printed by OpenShell.
|
||
|
||
Expose a service that listens on loopback inside the sandbox:
|
||
|
||
```shell
|
||
openshell service expose my-sandbox 8080
|
||
```
|
||
|
||
Pass an optional service name to create a named service URL:
|
||
|
||
```shell
|
||
openshell service expose my-sandbox 8080 web
|
||
```
|
||
|
||
List exposed endpoints:
|
||
|
||
```shell
|
||
openshell service list
|
||
```
|
||
|
||
List endpoints for one sandbox:
|
||
|
||
```shell
|
||
openshell service list my-sandbox
|
||
```
|
||
|
||
Show or delete one endpoint:
|
||
|
||
```shell
|
||
openshell service get my-sandbox web
|
||
openshell service delete my-sandbox web
|
||
```
|
||
|
||
Omit the service name to manage the unnamed endpoint:
|
||
|
||
```shell
|
||
openshell service get my-sandbox
|
||
openshell service delete my-sandbox
|
||
```
|
||
|
||
<Note>
|
||
Loopback gateways return local `openshell.localhost` URLs. Remote gateways return HTTPS URLs that require normal gateway authentication. For gateway service-domain configuration, refer to [Manage Gateways](/sandboxes/manage-gateways#configure-service-forwarding).
|
||
</Note>
|
||
|
||
## Monitor and Debug
|
||
|
||
List all sandboxes:
|
||
|
||
```shell
|
||
openshell sandbox list
|
||
```
|
||
|
||
Filter the list by labels when you want a narrower view:
|
||
|
||
```shell
|
||
openshell sandbox list --selector team=platform
|
||
```
|
||
|
||
Use `-o json` or `-o yaml` for machine-readable output:
|
||
|
||
```shell
|
||
openshell sandbox list -o json
|
||
openshell sandbox list -o yaml
|
||
```
|
||
|
||
Get detailed information about a specific sandbox. The output lists **Policy source** (`sandbox` or `global`), **Revision** (the active policy’s row version for that source), and the formatted active policy YAML:
|
||
|
||
```shell
|
||
openshell sandbox get my-sandbox
|
||
```
|
||
|
||
Print only that policy YAML for scripting (same effective policy, no metadata):
|
||
|
||
```shell
|
||
openshell sandbox get my-sandbox --policy-only
|
||
```
|
||
|
||
Stream sandbox logs to monitor agent activity and diagnose policy decisions:
|
||
|
||
```shell
|
||
openshell logs my-sandbox
|
||
```
|
||
|
||
| Flag | Purpose | Example |
|
||
| ---------- | ---------------------------- | ---------------------------------- |
|
||
| `--tail` | Stream logs in real time | `openshell logs my-sandbox --tail` |
|
||
| `--source` | Filter by log source | `--source sandbox` |
|
||
| `--level` | Filter by severity | `--level warn` |
|
||
| `--since` | Show logs from a time window | `--since 5m` |
|
||
|
||
OpenShell Terminal combines sandbox status and live logs in a single real-time dashboard:
|
||
|
||
```shell
|
||
openshell term
|
||
```
|
||
|
||
Use the terminal to spot blocked connections marked `action=deny` and inference-related proxy activity. If a connection is blocked unexpectedly, add the host to your network policy. Refer to [Policies](/sandboxes/policies) for the workflow.
|
||
|
||
The dashboard has three panels stacked vertically: Gateways, Providers (or Global Settings), and Sandboxes. Navigate within a panel with `Up`/`Down` or `j`/`k`. At a list boundary the cursor overflows into the adjacent panel, skipping empty panels. Use `Tab`/`Shift+Tab` to cycle panels directly. Press `h`/`l` or `Left`/`Right` in the middle panel to switch between the Providers and Global Settings tabs.
|
||
|
||
## Port Forwarding
|
||
|
||
Forward a local port to a running sandbox to access services inside it, such as a web server or database:
|
||
|
||
```shell
|
||
openshell forward start 8000 my-sandbox
|
||
openshell forward start 8000 my-sandbox -d # run in background
|
||
```
|
||
|
||
OpenShell prints the local URL only after the forward listener is reachable. Background forwards must be tracked locally so `openshell forward list` and `openshell forward stop` can manage them.
|
||
|
||
List and stop active forwards:
|
||
|
||
```shell
|
||
openshell forward list
|
||
openshell forward stop 8000 my-sandbox
|
||
```
|
||
|
||
<Tip>
|
||
You can also forward a port at creation time with `--forward`:
|
||
|
||
```shell
|
||
openshell sandbox create --forward 8000 -- claude
|
||
```
|
||
|
||
</Tip>
|
||
|
||
## SSH Config
|
||
|
||
Generate an SSH config entry for a sandbox so tools like VS Code Remote-SSH can connect directly:
|
||
|
||
```shell
|
||
openshell sandbox ssh-config my-sandbox
|
||
```
|
||
|
||
Append the output to `~/.ssh/config` or use `--editor` on `sandbox create`/`sandbox connect` for automatic setup.
|
||
|
||
## Transfer Files
|
||
|
||
Upload files from your host into the sandbox:
|
||
|
||
```shell
|
||
openshell sandbox upload my-sandbox ./src /sandbox/src
|
||
```
|
||
|
||
When the local path is a named directory, OpenShell preserves that basename at the destination, matching `scp -r` and `cp -r`. The example above creates `/sandbox/src/src`.
|
||
|
||
OpenShell preserves symlinks during upload. A symlink arrives in the sandbox as a symlink with the same target path instead of an expanded copy of the target file or directory. Dangling symlinks are also preserved.
|
||
|
||
Download files from the sandbox to your host:
|
||
|
||
```shell
|
||
openshell sandbox download my-sandbox /sandbox/output ./local
|
||
```
|
||
|
||
When the sandbox-side source is a single file, the destination follows `cp`-style placement: if the destination already exists as a directory or ends with `/`, the file lands inside it as `<dest>/<basename>`; otherwise the file is written at the exact destination path.
|
||
|
||
The CLI only allows sandbox-side sources that resolve inside the writable workspace (`/sandbox`). Paths that escape lexically (`/etc/passwd`, `/sandbox/../etc/passwd`) and paths that escape through a symlink (`/sandbox/etc-link` pointing at `/etc`) are both refused before any data is transferred.
|
||
|
||
<Note>
|
||
You can also upload files at creation time with the `--upload` flag on
|
||
`openshell sandbox create`. Pass `--upload` multiple times to upload
|
||
several paths in a single command:
|
||
|
||
```shell
|
||
openshell sandbox create --upload ./src:/workspace/src --upload ./config:/workspace/config -- claude
|
||
```
|
||
|
||
</Note>
|
||
|
||
By default, uploads inside a Git repository respect `.gitignore` rules so that
|
||
build artifacts, dependency caches, and other ignored files are not transferred.
|
||
If `.gitignore` filtering excludes every file in the upload path, the CLI falls
|
||
back to an unfiltered upload and prints a warning. Pass `--no-git-ignore` to
|
||
opt into unfiltered uploads explicitly, upload a path outside the Git work
|
||
tree, or force-add the intended files if they should remain Git-aware.
|
||
|
||
## Delete Sandboxes
|
||
|
||
Deleting a sandbox stops all processes, releases resources, and purges injected credentials.
|
||
|
||
```shell
|
||
openshell sandbox delete my-sandbox
|
||
```
|
||
|
||
## Sandbox Lifecycle
|
||
|
||
Every sandbox moves through a defined set of phases:
|
||
|
||
| Phase | Description |
|
||
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| Provisioning | The runtime is setting up the sandbox environment, injecting credentials, and applying your policy. |
|
||
| Ready | The sandbox is running. The agent process is active and all isolation layers are enforced. You can connect, sync files, and view logs. |
|
||
| Error | Something went wrong during provisioning or execution. Check logs with `openshell logs` for details. |
|
||
| Deleting | The sandbox is being torn down. The system releases resources and purges credentials. |
|
||
|
||
## Sandbox Compute Drivers
|
||
|
||
The gateway's configured compute driver determines how OpenShell creates each sandbox. The CLI workflow stays the same across drivers: you create, connect to, inspect, and delete sandboxes through the gateway API.
|
||
|
||
For Docker, Podman, MicroVM, and Kubernetes behavior, refer to [Sandbox Compute Drivers](/reference/sandbox-compute-drivers).
|
||
|
||
## Next Steps
|
||
|
||
- To follow a complete end-to-end example, refer to the [GitHub Sandbox](/get-started/tutorials/github-sandbox) tutorial.
|
||
- To supply API keys or tokens, refer to [Manage Providers](/sandboxes/manage-providers).
|
||
- To control what the agent can access, refer to [Policies](/sandboxes/policies).
|
||
- To use the default runtime image, refer to [Base Sandbox Container](#base-sandbox-container).
|