Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion .agents/skills/openshell-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ Key flags:
- `--gpu [COUNT]`: Request the driver's default GPU selection or a specific GPU count
- `--cpu`, `--memory`: Set per-sandbox compute sizing. Docker/Podman apply limits; Kubernetes applies matching requests and limits.
- `--driver-config-json`: Pass experimental driver-specific sandbox configuration
- `--template NAME`: Create from a named sandbox workload template. Conflicts with inline workload flags such as `--from`, `--gpu`, `--cpu`, `--memory`, `--env`, and `--driver-config-json`.
- `--label KEY=VALUE`: Add labels for later selection (repeatable)
- `--env KEY=VALUE`: Set non-secret sandbox environment variables (repeatable); use `--provider` for credentials
- `--approval-mode manual|auto`: Control handling of agent-authored policy proposals; `manual` is the default
Expand All @@ -237,6 +238,44 @@ Key flags:
- `--forward [BIND_ADDRESS:]PORT`: Forward a local port and keep the sandbox alive
- `--editor vscode|cursor`: Open a remote editor after creation and keep the sandbox alive

Create from a reusable workload template when several sandboxes should share
image, environment, sizing, or driver-specific configuration:

```bash
openshell sandbox template create gpu-kata \
--image ghcr.io/nvidia/openshell-community/sandboxes/python:latest \
--cpu 2 \
--memory 4Gi \
--gpu 1 \
--driver-config-json '{"kubernetes":{"pod":{"node_selector":{"pool":"gpu"}}}}'

openshell sandbox create --name my-sandbox --template gpu-kata --provider my-github -- claude
```

Direct `sandbox create --driver-config-json` remains valid for one-off
creates. Put driver config on a template only when it should be reused.

### Manage sandbox workload templates

```bash
openshell sandbox template create gpu-kata \
--image ghcr.io/nvidia/openshell-community/sandboxes/python:latest \
--cpu 2 \
--memory 4Gi \
--gpu 1 \
--label team=runtime \
--env FEATURE_FLAG=on
openshell sandbox template list
openshell sandbox template list --all-workspaces --output json
openshell sandbox template get gpu-kata
openshell sandbox template delete gpu-kata
```

Template `--image` accepts an OCI image reference. If omitted, the gateway
applies its default sandbox image when creating a sandbox from the template.
Create-time policy, providers, labels, uploads, forwarding, editor launch, and
the initial command stay on `sandbox create`.

### List and inspect sandboxes

```bash
Expand Down Expand Up @@ -714,7 +753,7 @@ The CLI help is always authoritative. If the help output contradicts this skill,

```bash
$ openshell sandbox --help
# Shows: create, get, list, stop, start, delete, exec, connect, upload, download, ssh-config, provider
# Shows: create, get, list, stop, start, delete, exec, connect, upload, download, ssh-config, provider, template

$ openshell sandbox upload --help
# Shows: positional arguments (name, path, dest), usage examples
Expand All @@ -735,6 +774,8 @@ $ openshell sandbox upload --help
| Create sandbox with tool | `openshell sandbox create -- claude` |
| Create sandbox with GPUs | `openshell sandbox create --gpu 1` |
| Create with custom policy | `openshell sandbox create --policy ./p.yaml` |
| Create from template | `openshell sandbox create --template gpu-kata` |
| Create workload template | `openshell sandbox template create gpu-kata --image python:3.12` |
| Connect to sandbox | `openshell sandbox connect <name>` |
| Stop sandbox compute | `openshell sandbox stop [name]` |
| Start sandbox compute | `openshell sandbox start [name]` |
Expand Down
64 changes: 60 additions & 4 deletions .agents/skills/openshell-cli/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,15 @@ openshell
│ ├── upload <name> <path> [dest]
│ ├── download <name> <path> [dest]
│ ├── ssh-config [name]
│ └── provider
│ ├── list [name]
│ ├── attach <name> <provider>
│ └── detach <name> <provider>
│ ├── provider
│ │ ├── list [name]
│ │ ├── attach <name> <provider>
│ │ └── detach <name> <provider>
│ └── template
│ ├── create <name> [opts]
│ ├── get <name>
│ ├── list [opts]
│ └── delete <name>...
├── forward
│ ├── start <port> [name] [-d]
│ ├── stop <port> [name]
Expand Down Expand Up @@ -216,6 +221,7 @@ Create a sandbox through the selected gateway, wait for readiness, then connect,
| `--cpu <QUANTITY>` | CPU limit (for example: `500m`, `1`, `2.5`) |
| `--memory <QUANTITY>` | Memory limit (for example: `512Mi`, `4Gi`, `8G`) |
| `--driver-config-json <JSON>` | Experimental driver-keyed configuration object |
| `--template <NAME>` | Create from a named sandbox workload template |
| `--provider <NAME>` | Provider to attach (repeatable) |
| `--policy <PATH>` | Custom policy YAML; overrides the built-in default and `OPENSHELL_SANDBOX_POLICY` |
| `--forward <[BIND:]PORT>` | Start a local port forward and keep the sandbox alive |
Expand All @@ -229,6 +235,56 @@ Create a sandbox through the selected gateway, wait for readiness, then connect,
| `--no-git-ignore` | Disable `.gitignore` filtering for `--upload` |
| `[-- COMMAND...]` | Initial command (defaults to an interactive shell) |

`--template` uses the named template workload, so it conflicts with inline
workload flags: `--from`, `--gpu`, `--cpu`, `--memory`, `--env`, and
`--driver-config-json`. Direct `sandbox create --driver-config-json` remains
valid when `--template` is not set.

### `openshell sandbox template create NAME [OPTIONS]`

Create a reusable sandbox workload template. Templates hold image,
environment, resource, startup, and driver-specific configuration for later
`sandbox create --template NAME` calls.

| Flag | Description |
|------|-------------|
| `--image <IMAGE>` | OCI image reference; when omitted, the gateway default image is applied at sandbox create time |
| `--env <KEY=VALUE>` | Set a non-secret template workload environment variable (repeatable) |
| `--cpu <QUANTITY>` | CPU limit for sandboxes created from the template |
| `--memory <QUANTITY>` | Memory limit for sandboxes created from the template |
| `--gpu [COUNT]` | Request the driver's default GPU selection or a specific GPU count for sandboxes created from the template |
| `--driver-config-json <JSON>` | Experimental driver-keyed configuration object owned by the template |
| `--ready-within <DURATION>` | Target startup readiness duration, for example `30s`, `5m`, or `1h` |
| `--max-burst <COUNT>` | Maximum startup burst associated with this template |
| `--label <KEY=VALUE>` | Attach a template label (repeatable) |
| `--annotation <KEY=VALUE>` | Attach a template annotation (repeatable) |
| `--output table|yaml|json` | Output format |

### `openshell sandbox template get NAME`

Show a sandbox workload template.

| Flag | Description |
|------|-------------|
| `--output table|yaml|json` | Output format |

### `openshell sandbox template list`

List sandbox workload templates.

| Flag | Default | Description |
|------|---------|-------------|
| `--limit <N>` | 100 | Maximum templates |
| `--offset <N>` | 0 | Pagination offset |
| `--names` | false | Print only template names |
| `--all-workspaces` | false | List templates across all workspaces; requires platform-admin permissions |
| `--output table|yaml|json` | `table` | Output format |

### `openshell sandbox template delete NAME...`

Delete one or more sandbox workload templates by name. Existing sandboxes
created from a template are not deleted.

### `openshell sandbox get [name]`

Show sandbox details and the active policy. Metadata identifies sandbox or global policy source and the corresponding revision. The name defaults to the last-used sandbox.
Expand Down
10 changes: 10 additions & 0 deletions architecture/compute-runtimes.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,16 @@ template resource limits. Docker and Podman apply them as runtime limits.
Kubernetes mirrors each limit into the matching request. VM accepts the fields
but currently ignores them.

Reusable sandbox workload templates are resolved before the compute-driver
boundary. Drivers do not receive a separate template resource; the gateway
lowers the selected `SandboxWorkloadTemplate` into the existing sandbox spec
and validates that spec before calling `ValidateSandboxCreate` or
`CreateSandbox`. Template CPU and memory become the same typed resource limits
described above. Template GPU settings become `ResourceRequirements`, preserving
the driver's default GPU assignment when the count is omitted. Template
`driver_config` remains a driver-keyed envelope until the compute layer selects
the active driver block and forwards only that block to the driver.

Docker and Podman also accept per-sandbox driver-config mounts for existing
runtime-managed named volumes and tmpfs mounts. Podman additionally accepts
image mounts through its image-volume API. User-supplied bind and volume mounts
Expand Down
44 changes: 27 additions & 17 deletions architecture/gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,23 +317,33 @@ default WAL journal mode), which mirror the same sensitive contents.

Persisted state includes sandboxes, providers, provider credential refresh
state, SSH sessions, policy revisions, settings, inference configuration, and
deployment records. Provider refresh state is stored as a separate object
scoped to the provider instance through `objects.scope`. Its non-secret
configuration remains inline, while refresh tokens, client secrets, private
keys, and other secret source material are stored through the active credential
driver and represented by opaque handles. The provider record keeps only the
current injectable credential handles and optional per-credential expiry
timestamps. A refresh normally mints one credential, but a strategy may
co-mint several (AWS STS mints the access key, secret key, and session token in
one call); the refresh state pins the resolved set of env keys it owns so
collision checks reserve all of them before the first mint. Provider records
keep inline credential values only for legacy records created before credential
driver storage. New provider and refresh-material writes keep driver-owned
credential handles. When no external credential driver is configured, gateways
use server-owned encrypted database credential storage for defense in depth.
Multi-replica deployments can use that default with a shared database and
shared key-encryption key, or opt into an external backend such as Vault or
Kubernetes Secrets.
deployment records, and reusable sandbox workload templates. Provider refresh
state is stored as a separate object scoped to the provider instance through
`objects.scope`. Its non-secret configuration remains inline, while refresh
tokens, client secrets, private keys, and other secret source material are
stored through the active credential driver and represented by opaque handles.
The provider record keeps only the current injectable credential handles and
optional per-credential expiry timestamps. A refresh normally mints one
credential, but a strategy may co-mint several (AWS STS mints the access key,
secret key, and session token in one call); the refresh state pins the resolved
set of env keys it owns so collision checks reserve all of them before the
first mint. Provider records keep inline credential values only for legacy
records created before credential driver storage. New provider and
refresh-material writes keep driver-owned credential handles. When no external
credential driver is configured, gateways use server-owned encrypted database
credential storage for defense in depth. Multi-replica deployments can use that
default with a shared database and shared key-encryption key, or opt into an
external backend such as Vault or Kubernetes Secrets.

Sandbox workload templates are workspace-scoped gateway resources. Workspace
admins create and delete them; workspace users can read and list them. A
template owns reusable workload intent: image, environment, CPU and memory
limits, GPU request, driver-specific config, and service-level hints. A sandbox
created from a template resolves that resource once and persists an ordinary
`SandboxSpec` snapshot. The create request still owns per-sandbox governance:
name, labels, annotations, provider attachments, and policy. The sandbox stores
template provenance as the template name and resource version used for the
snapshot, so later template edits or deletes do not mutate existing sandboxes.

Credential handles remain bound to the driver that created them. Before the
0.1.0 compatibility boundary, gateways do not migrate inline refresh material
Expand Down
9 changes: 9 additions & 0 deletions architecture/sandbox-limits.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ New limits should follow these rules:
query parameters, or external free-form diagnostics.
- Test time bounds with simulated time and test shared budgets under saturation.

## Gateway Sandbox Resources

Gateway-owned sandbox resources also carry admission limits before they can
produce supervisor work. Reusable workload templates are capped at 1000 per
workspace. Template payloads reuse sandbox spec validation for environment
entry count and size, image and resource field sizes, driver-config serialized
size, and GPU count. Template names use the same DNS-style resource-name rules
as other named gateway resources.

## Middleware

Middleware limits are process-wide per sandbox. Registry replacement preserves
Expand Down
6 changes: 6 additions & 0 deletions architecture/sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ own DNS view, e.g. DoH tunneled via CONNECT, is a possible future
enhancement and out of scope.) The workload child's proxy variables are
unaffected — they are always rewritten to point at the local policy proxy.

Template environment is treated like user-provided sandbox environment. It can
shape the workload child, but it cannot override driver-controlled identity,
gateway callback, TLS, relay socket, proxy, provider, or supervisor coordination
variables. Drivers and the supervisor rewrite those reserved values after image
and template environment are considered.

The configuration is fail-closed: a setting that is present but invalid — an
empty value, an unsupported or malformed proxy URL, an unreadable auth file,
a malformed credential, or an auth file or `NO_PROXY` list set while no proxy
Expand Down
Loading
Loading