From f5f7b6683e5eb6087668a6e58b974e8cbf6c91fd Mon Sep 17 00:00:00 2001 From: Piotr Mlocek Date: Fri, 17 Jul 2026 14:32:36 -0700 Subject: [PATCH 1/3] docs(agents): refresh CLI and debugging skills Signed-off-by: Piotr Mlocek --- .agents/skills/debug-inference/SKILL.md | 76 +++- .../skills/debug-openshell-cluster/SKILL.md | 60 ++- .agents/skills/openshell-cli/SKILL.md | 303 ++++++--------- .../openshell-cli/advanced-workflows.md | 215 ++++++++++ .agents/skills/openshell-cli/cli-reference.md | 366 ++++++++++++++---- .agents/skills/sync-agent-infra/SKILL.md | 6 +- AGENTS.md | 24 ++ 7 files changed, 743 insertions(+), 307 deletions(-) create mode 100644 .agents/skills/openshell-cli/advanced-workflows.md diff --git a/.agents/skills/debug-inference/SKILL.md b/.agents/skills/debug-inference/SKILL.md index 6770da5987..4b73143f9b 100644 --- a/.agents/skills/debug-inference/SKILL.md +++ b/.agents/skills/debug-inference/SKILL.md @@ -1,6 +1,6 @@ --- name: debug-inference -description: Debug why inference.local or external inference setup is failing. Use when the user cannot reach a local model server, has provider base URL issues, sees inference verification failures, hits protocol mismatches, or needs to diagnose inference on local vs remote gateways. Trigger keywords - debug inference, inference.local, local inference, ollama, vllm, sglang, trtllm, NIM, inference failing, model server unreachable, failed to verify inference endpoint, host.openshell.internal. +description: Debug why inference.local, supervisor-only system inference, or direct external inference is failing. Use when the user cannot reach a local model server, has provider base URL issues, sees inference verification failures, hits protocol mismatches, or needs to diagnose inference on local vs remote gateways. Trigger keywords - debug inference, inference.local, system inference, sandbox-system, local inference, ollama, vllm, sglang, trtllm, NIM, inference failing, model server unreachable, failed to verify inference endpoint, host.openshell.internal. --- # Debug Inference @@ -11,13 +11,17 @@ Use `openshell` CLI commands to inspect the active gateway, provider records, ma ## Overview -OpenShell supports two different inference paths. Diagnose the correct one first. +OpenShell supports three inference paths. Diagnose the correct one first. 1. **Managed inference** through `https://inference.local` - Configured by `openshell inference set` - Shared by every sandbox on the active gateway - Credentials and model are injected by OpenShell -2. **Direct external inference** to hosts like `api.openai.com` +2. **System inference** for platform functions such as the agent harness + - Configured by `openshell inference set --system` + - Uses the `sandbox-system` route + - Consumed in-process by the sandbox supervisor and not exposed to sandbox user code through `inference.local` +3. **Direct external inference** to hosts like `api.openai.com` - Controlled by `network_policies` - Requires the application to call the external host directly - Requires provider attachment and network access to be configured separately @@ -38,10 +42,13 @@ Use these commands first: # Which gateway is active, and can the CLI reach it? openshell status -# Show managed inference config for inference.local +# Show both the user-facing and system inference routes openshell inference get -# Inspect the provider record referenced by inference.local +# Show only the supervisor-only system route +openshell inference get --system + +# Inspect the provider record referenced by the relevant route openshell provider get # Inspect gateway topology details when remote/local confusion is suspected @@ -59,9 +66,9 @@ When the user asks to debug inference, run diagnostics automatically in this ord Establish these facts first: -1. Is the application calling `https://inference.local` or a direct external host? +1. Is sandbox code calling `https://inference.local`, is a platform function using system inference, or is the application calling a direct external host? 2. Which gateway is active, and is it local, remote, or cloud? -3. Which provider and model are configured for managed inference? +3. Which provider, model, and timeout are configured for the relevant route? 4. Is the upstream local to the gateway host, or somewhere else? ### Step 0: Check the Active Gateway @@ -83,23 +90,31 @@ Common mistake: - **Laptop-local model + remote gateway**: `host.openshell.internal` points to the remote gateway host, not your laptop. A laptop-local Ollama or vLLM server will not be reachable without a tunnel or shared reachable network path. -### Step 1: Check Whether Managed Inference Is Configured +### Step 1: Check Whether the Relevant Route Is Configured Run: ```bash openshell inference get +openshell inference get --system ``` Interpretation: -- **`Not configured`**: `inference.local` has no backend yet. Fix by configuring it: +- `openshell inference get` shows both **Gateway inference** (`inference.local`) and **System inference** (`sandbox-system`). `--system` isolates the system route. +- **Gateway inference is `Not configured`**: `inference.local` has no backend. Configure it without `--system`: ```bash openshell inference set --provider --model ``` -- **Provider and model shown**: Continue to provider inspection. +- **System inference is `Not configured`**: platform functions have no system backend. Configure it separately: + + ```bash + openshell inference set --system --provider --model + ``` + +- **Provider, model, and timeout shown**: Continue to provider inspection for the relevant route. ### Step 2: Inspect the Provider Record @@ -111,10 +126,13 @@ openshell provider get Check: -- Provider type matches the client API shape +- Provider type matches the client API shape and is supported for managed inference - `openai` for OpenAI-compatible engines such as Ollama, vLLM, SGLang, TRT-LLM, and many NIM deployments - `anthropic` for Anthropic Messages API - `nvidia` for NVIDIA-hosted OpenAI-compatible endpoints + - `deepinfra` for DeepInfra's OpenAI-compatible endpoint + - `google-vertex-ai` for Vertex AI; Claude models use Anthropic Messages and other models use OpenAI Chat Completions + - `aws-bedrock` only through a configured Bedrock-compatible bridge today - Required credential key exists - `*_BASE_URL` override is correct when using a self-hosted endpoint @@ -123,9 +141,11 @@ Fix examples: ```bash openshell provider create --name ollama --type openai --credential OPENAI_API_KEY=empty --config OPENAI_BASE_URL=http://host.openshell.internal:11434/v1 -openshell provider update ollama --type openai --credential OPENAI_API_KEY=empty --config OPENAI_BASE_URL=http://host.openshell.internal:11434/v1 +openshell provider update ollama --credential OPENAI_API_KEY=empty --config OPENAI_BASE_URL=http://host.openshell.internal:11434/v1 ``` +`provider update` preserves the provider type and does not accept `--type`. Prefer bare credential keys, such as `--credential OPENAI_API_KEY`, when reading a real secret from the CLI environment. + ### Step 3: Check Local Host Reachability For host-backed local inference, confirm the upstream server: @@ -142,21 +162,25 @@ Common mistakes: ### Step 4: Check Request Shape -Managed inference only works for `https://inference.local` and supported inference API paths. +User-facing managed inference only works for `https://inference.local` and supported inference API paths. Supported patterns include: - `POST /v1/chat/completions` - `POST /v1/completions` - `POST /v1/responses` +- `POST /v1/embeddings` - `POST /v1/messages` - `GET /v1/models` +- `GET /v1/models/*` +- `POST /model/{modelId}/invoke` for bridge-fronted `aws-bedrock` Common mistakes: - **Wrong scheme**: `http://inference.local` instead of `https://inference.local` - **Unsupported path**: request does not match a known inference API - **Protocol mismatch**: Anthropic client against an `openai` provider, or vice versa +- **Provider-specific mismatch**: Vertex Claude requests must use `/v1/messages`; other Vertex models currently use `/v1/chat/completions`; Bedrock uses its model-in-path invoke shape Fix guidance: @@ -166,6 +190,8 @@ Fix guidance: ### Step 5: Probe from a Sandbox +This probe validates the user-facing `inference.local` route. It does not exercise supervisor-only system inference. + Run a minimal request from inside a sandbox: ```bash @@ -179,21 +205,28 @@ Interpretation: - **`no compatible route`**: provider type and client API shape do not match - **Connection refused / upstream unavailable / verification failures**: base URL, bind address, topology, or credentials are wrong +For system inference failures, inspect the platform function and sandbox supervisor/network logs after confirming `openshell inference get --system`. User code cannot call the `sandbox-system` route directly. + ### Step 6: Reapply or Repair the Managed Route -After fixing the provider, repoint `inference.local`: +After fixing the provider, use `update` for a partial change or `set` to replace the route: ```bash openshell inference set --provider --model +openshell inference update --provider +openshell inference update --model +openshell inference update --timeout 120 ``` +Add `--system` to target the system route. Without it, these commands target `inference.local`. A timeout of `0` uses the 60-second default; increase it for models with long reasoning or idle streaming phases. + If the endpoint is intentionally offline and you only want to save the config: ```bash openshell inference set --provider --model --no-verify ``` -Inference updates are hot-reloaded to all sandboxes on the active gateway within about 5 seconds by default. +Use `--no-verify` only when the endpoint is intentionally offline or the provider protocol cannot be verified, such as the current bridge-fronted Bedrock flow. Inference updates are hot-reloaded to running sandboxes within about 5 seconds by default. ### Step 7: Diagnose Direct External Inference @@ -203,9 +236,11 @@ Check instead: 1. The application is configured to call the external hostname directly 2. A provider with the needed credentials exists -3. The sandbox is launched with that provider attached +3. The sandbox has that provider attached (`openshell sandbox provider list [name]`) 4. `network_policies` allow that host, port, and HTTP rules +Attach or detach a provider on an existing sandbox with `openshell sandbox provider attach ` and `openshell sandbox provider detach `. + Use the `generate-sandbox-policy` skill when the user needs help authoring policy YAML. ## Fix: Local Host Inference Timeouts (Firewall) @@ -305,11 +340,13 @@ Both commands should return the upstream model list. | Symptom | Likely cause | Fix | |---------|--------------|-----| | `openshell inference get` shows `Not configured` | No managed inference route configured | `openshell inference set --provider --model ` | +| System inference is `Not configured` | Platform-only route has no backend | `openshell inference set --system --provider --model ` | | `failed to verify inference endpoint` | Bad base URL, wrong credentials, wrong provider type, or upstream not reachable | Fix provider config, then rerun `openshell inference set`; use `--no-verify` only when the endpoint is intentionally offline | | Base URL uses `127.0.0.1` | Loopback points at the wrong runtime | Use `host.openshell.internal` or another gateway-reachable host | | Local engine works only when gateway is local | Gateway moved to remote host | Run the engine on the gateway host, add a tunnel, or use direct external access | | `connection not allowed by policy` on `inference.local` | Unsupported path or method | Use a supported inference API path | -| `no compatible route` | Provider type does not match request shape | Switch provider type or change the client API | +| `no compatible route` | Provider type does not match request shape | Create or select a provider of the matching type, or change the client API | +| `inference.local` works but an agent-harness/platform call fails | User route is configured but `sandbox-system` is missing or wrong | `openshell inference get --system`; configure or update with `--system`; inspect supervisor logs | | Direct call to external host is denied | Missing policy or provider attachment | Update `network_policies` and launch sandbox with the right provider | | SDK fails on empty auth token | Client requires a non-empty API key even though OpenShell injects the real one | Use any placeholder token such as `test` | | Upstream timeout from container to host-local backend | Host firewall or network config blocks container-to-host traffic | Allow the Docker bridge subnet to reach the inference port on the host gateway IP (see firewall fix section above) | @@ -328,6 +365,9 @@ openshell gateway info echo "=== Managed Inference ===" openshell inference get +echo "=== System Inference Only ===" +openshell inference get --system + echo "=== Providers ===" openshell provider list @@ -340,7 +380,7 @@ openshell sandbox create -- curl https://inference.local/v1/chat/completions --j When you report back, state: -1. Which inference path is failing (`inference.local` vs direct external) +1. Which inference path is failing (`inference.local`, system inference, or direct external) 2. Whether gateway topology is part of the problem 3. The most likely root cause 4. The exact fix commands the user should run diff --git a/.agents/skills/debug-openshell-cluster/SKILL.md b/.agents/skills/debug-openshell-cluster/SKILL.md index 82ce9650cd..c721dfb091 100644 --- a/.agents/skills/debug-openshell-cluster/SKILL.md +++ b/.agents/skills/debug-openshell-cluster/SKILL.md @@ -1,11 +1,11 @@ --- name: debug-openshell-cluster -description: Debug why an OpenShell gateway deployment is unhealthy, unreachable, or unable to create sandboxes. Use when the user has a gateway health failure, Docker/Podman runtime issue, Helm install failure, Kubernetes scheduling issue, TLS secret issue, VM driver issue, or sandbox startup problem. Trigger keywords - debug gateway, gateway failing, deployment failing, helm install failing, cluster health, gateway health, gateway not starting, health check failed, sandbox pending, docker driver, podman driver, vm driver. +description: Debug why an OpenShell gateway deployment is unhealthy, unreachable, or unable to create sandboxes. Use when the user has a gateway health failure, Docker/Podman runtime issue, Helm install failure, Kubernetes scheduling issue, TLS or auth issue, interceptor startup failure, external compute-driver socket issue, VM driver issue, or sandbox startup problem. Trigger keywords - debug gateway, gateway failing, deployment failing, helm install failing, cluster health, gateway health, gateway not starting, health check failed, sandbox pending, docker driver, podman driver, kubernetes driver, external driver, compute driver socket, gateway interceptor, vm driver. --- # Debug OpenShell Gateway Deployment -Diagnose a gateway and its selected compute platform. Do not assume OpenShell provisions Kubernetes or runs a k3s container. OpenShell targets a reachable gateway endpoint backed by Docker, Podman, Kubernetes, or the experimental VM driver. +Diagnose a gateway and its selected compute platform. Do not assume OpenShell provisions Kubernetes or runs a k3s container. OpenShell targets a reachable gateway endpoint backed by Docker, Podman, Kubernetes, the experimental VM driver, or an operator-managed out-of-tree compute driver. Use `openshell` first to identify the active endpoint. Then use the platform tools that match the gateway's compute driver: `docker`, `podman`, `kubectl`/`helm`, or VM driver logs. @@ -15,7 +15,7 @@ The target deployment flow is: 1. Operator starts or deploys the gateway with system packages, systemd, Helm, or a development task. The CLI does not start, stop, or destroy gateway services. 2. Operator configures the compute driver. -3. Operator provides TLS and SSH relay material for the deployment mode. +3. Operator provides the CLI and supervisor authentication material required by the deployment mode: edge or OIDC user auth, optional CLI mTLS, and gateway-minted sandbox JWTs. 4. The CLI registers a reachable gateway endpoint with `openshell gateway add`. 5. The gateway creates sandboxes through the selected compute driver. @@ -25,7 +25,7 @@ For local evaluation only, TLS may be disabled and the gateway can be reached th - The `openshell` CLI must be available for endpoint checks. - Know the active gateway name and endpoint, or be able to inspect local gateway metadata. -- Know the compute platform: Docker, Podman, Kubernetes, or VM. +- Know the compute platform: Docker, Podman, Kubernetes, VM, or an out-of-tree driver. - For Kubernetes: `kubectl` must target the cluster that hosts OpenShell and Helm version 3 or later must be available. - For Docker or Podman: the runtime socket must be reachable from the gateway host. @@ -36,15 +36,24 @@ Run diagnostics in order and stop once the root cause is clear. ### Step 1: Check CLI Reachability ```bash +openshell gateway list --output json openshell gateway info openshell status ``` +For a one-off endpoint check that bypasses stored gateway selection and metadata: + +```bash +openshell --gateway-endpoint status +``` + Common findings: - `No active gateway`: register one with `openshell gateway add `. - Connection refused: gateway process is not running, service exposure is wrong, or a port-forward/proxy is not active. -- TLS/certificate errors: CLI mTLS bundle does not match the gateway CA, or the gateway is running with unexpected TLS settings. +- TLS/certificate errors: the endpoint scheme or trust chain is wrong, a local mTLS bundle does not match the gateway CA, or TLS termination does not match the gateway listener. +- `Unauthenticated` from an edge or OIDC gateway: refresh stored credentials with `openshell gateway login [name]`, then retry. Use `gateway logout` only when intentionally clearing local credentials. +- A direct development endpoint with a private or self-signed certificate can be isolated with `--gateway-endpoint --gateway-insecure`; do not persist or recommend insecure verification for shared gateways. ### Step 2: Identify the Compute Platform @@ -56,8 +65,35 @@ Use gateway metadata, deployment values, or the user's setup notes to identify t | Podman | Podman socket, rootless networking, sandbox containers, image pulls. | | Kubernetes | Helm release, gateway workload, service, secrets, sandbox pods, events. | | VM | VM driver logs, rootfs availability, host virtualization support. | +| Extension | External driver process, Unix socket ownership/mode, configured driver name, capability handshake, gateway logs. | + +### Step 3: Check Gateway Startup Dependencies + +Before debugging the compute platform, inspect gateway logs for failures in dependencies initialized before the listener becomes ready. + +For out-of-tree compute drivers, confirm the custom driver name and socket agree across CLI flags or `gateway.toml`, and that the operator-owned driver is running before the gateway starts: + +```bash +rg -n 'compute_drivers|socket_path' /etc/openshell/gateway.toml +stat /run/openshell/.sock +journalctl -u --no-pager --lines=200 +journalctl -u openshell-gateway --no-pager --lines=200 +``` + +The custom driver name must not be a reserved built-in name (`docker`, `podman`, `kubernetes`, or `vm`). The socket must be accessible only to the intended gateway identity. Check gateway logs for connection errors, `GetCapabilities` failures, or an unexpected advertised driver name. The gateway does not create or supervise out-of-tree driver processes or sockets. + +For configured gateway interceptors, inspect `[[openshell.gateway.interceptors]]`, their Unix or network endpoints, and gateway startup logs: + +```bash +rg -n 'interceptors|provider_profile_sources|grpc_endpoint|binding_policy|failure_policy' /etc/openshell/gateway.toml +stat /run/openshell/interceptors/.sock +journalctl -u --no-pager --lines=200 +journalctl -u openshell-gateway --no-pager --lines=200 +``` + +The gateway calls each interceptor's `Describe` RPC and validates its manifest at startup. Check for unreachable endpoints, invalid RPC/phase bindings, strict `allowlist` or `exact` mismatches, and `post_commit` bindings that resolve to `fail_closed`. If `provider_profile_sources` names an interceptor, that interceptor must advertise provider-profile capability and return a valid, duplicate-free catalog. A selected interceptor-only source is authoritative; include `builtin` or `user` sources explicitly when composition is intended. -### Step 3: Check Docker-Backed Gateways +### Step 4: Check Docker-Backed Gateways ```bash docker info @@ -110,7 +146,7 @@ For source checkout development, restart the local gateway with: mise run gateway:docker ``` -### Step 4: Check Podman-Backed Gateways +### Step 5: Check Podman-Backed Gateways ```bash podman info @@ -126,7 +162,7 @@ Common findings: - Sandbox image missing or pull denied: verify image reference and registry credentials. - Supervisor cannot call back: check callback endpoint and gateway logs. -### Step 5: Check Kubernetes Helm Gateways +### Step 6: Check Kubernetes Helm Gateways ```bash helm -n openshell status openshell @@ -319,7 +355,7 @@ kubectl -n logs -c openshell-supervisor-networ kubectl -n logs -c agent --tail=200 ``` -### Step 6: Check VM-Backed Gateways +### Step 7: Check VM-Backed Gateways Use the VM driver logs and host diagnostics available in the user's environment. Verify: @@ -346,6 +382,10 @@ openshell logs | Kubernetes gateway pod pending | PVC unbound, taint, selector, or insufficient resources | `kubectl -n openshell describe pod ` | | Kubernetes gateway pod crash loops | Missing secret, bad DB URL, bad TLS config | `kubectl -n openshell logs deployment/openshell -c openshell-gateway` or `kubectl -n openshell logs statefulset/openshell -c openshell-gateway` | | CLI TLS error | Local mTLS bundle does not match server cert/CA | Check `~/.config/openshell/gateways//mtls/` | +| Edge or OIDC gateway returns `Unauthenticated` | Stored login expired, audience/scopes mismatch, or gateway auth configuration changed | `openshell gateway info`, `openshell gateway login `, gateway auth logs | +| Gateway fails before serving health after enabling an interceptor | Interceptor endpoint unavailable or manifest/binding validation failed | Gateway and interceptor logs; interceptor socket; `binding_policy`, phases, and failure policy | +| Provider profiles disappear after enabling an interceptor catalog | `provider_profile_sources` selected only an authoritative interceptor or returned invalid/duplicate IDs | Inspect source list and interceptor `Describe`/catalog logs; include `builtin` and `user` when intended | +| Custom compute driver is unavailable | Driver process/socket missing, inaccessible, or configured with a reserved/mismatched name | Socket ownership/mode, driver service logs, gateway `GetCapabilities` logs | | Image pull failure | Gateway or sandbox image cannot be pulled | Runtime events and image pull credentials | | `K8s namespace not ready` with `envoy-gateway-openshell.yaml: the server could not find the requested resource` | Optional Gateway API manifest was applied without Envoy Gateway CRDs, or k3s Helm controller startup exceeded the namespace wait | Apply `deploy/kube/manifests/envoy-gateway-openshell.yaml` manually only after Envoy Gateway is installed and `grpcRoute` is enabled | | HTTPS ingress (`grpcRoute.gateway.listener.protocol=HTTPS`) connection resets or TLS handshake hangs | Envoy terminates TLS but the gateway pod still expects TLS, so the plaintext backend hop fails | Set `server.disableTls=true` so Envoy forwards plaintext to the pod; verify the listener `certificateRefs` Secret exists in the release namespace and `openshell status` over `https://` | @@ -359,7 +399,7 @@ When handing results back to the user, include: - Compute platform and driver. - Gateway process or workload status. - Recent gateway log summary. -- Missing or malformed TLS or SSH relay material. +- Missing or malformed TLS, OIDC/mTLS, or sandbox JWT material. - Service exposure status. - Sandbox workload status. - The exact command that failed and the shortest fix. diff --git a/.agents/skills/openshell-cli/SKILL.md b/.agents/skills/openshell-cli/SKILL.md index a559058917..25a117be35 100644 --- a/.agents/skills/openshell-cli/SKILL.md +++ b/.agents/skills/openshell-cli/SKILL.md @@ -1,6 +1,6 @@ --- name: openshell-cli -description: Guide agents through using the OpenShell CLI (openshell) for sandbox management, gateway registration, provider configuration, policy iteration, BYOC workflows, and inference routing. Covers basic through advanced multi-step workflows. Trigger keywords - openshell, sandbox create, sandbox connect, logs, provider create, policy set, policy get, image push, forward, port forward, BYOC, bring your own container, use openshell, run openshell, CLI usage, manage sandbox, manage provider, gateway add, gateway select. +description: Guide agents through using the OpenShell CLI (openshell) for sandbox management, gateway registration, provider configuration and refresh, policy iteration, settings, service exposure, BYOC workflows, and inference routing. Covers basic through advanced multi-step workflows. Trigger keywords - openshell, sandbox create, sandbox exec, sandbox connect, logs, provider create, provider profile, provider refresh, policy set, policy get, settings, service expose, forward, port forward, BYOC, bring your own container, inference, use openshell, run openshell, CLI usage, manage sandbox, manage provider, gateway add, gateway select. --- # OpenShell CLI @@ -9,7 +9,7 @@ Guide agents through using the `openshell` CLI for sandbox and platform manageme ## Overview -The OpenShell CLI (`openshell`) is the primary interface for managing sandboxes, providers, policies, inference routes, and gateway registrations. Gateway service lifecycle is handled outside the CLI by packages, systemd, Helm, or development tasks. This skill teaches agents how to orchestrate CLI commands for common and complex workflows. +The OpenShell CLI (`openshell`) is the primary interface for managing sandboxes, providers, policies, settings, exposed services, inference routes, and gateway registrations. Gateway service lifecycle is handled outside the CLI by packages, systemd, Helm, or development tasks. This skill teaches agents how to orchestrate CLI commands for common and complex workflows. **Companion skill**: For creating or modifying sandbox policy YAML content (network rules, L7 inspection, access presets), use the `generate-sandbox-policy` skill. This skill covers the CLI *commands* for the policy lifecycle; `generate-sandbox-policy` covers policy *content authoring*. @@ -32,7 +32,7 @@ This is your primary fallback. Use it freely -- the CLI's help output is authori ## Command Reference -See [cli-reference.md](cli-reference.md) for the full command tree with all flags and options. Use it as a quick-reference to avoid round-tripping through `--help` for common commands. +See [cli-reference.md](cli-reference.md) for the current command tree and commonly used flags. Use it as a quick-reference, then confirm uncommon or security-sensitive options with `--help`. --- @@ -87,9 +87,12 @@ openshell sandbox delete ## Workflow 2: Provider Management -Providers supply credentials to sandboxes (API keys, tokens, etc.). Manage them before creating sandboxes that need them. +Providers supply credentials and provider-specific configuration to sandboxes. Provider types come from built-in and custom profiles; do not rely on a hard-coded type list. Discover the profiles available on the selected gateway: -Supported types: `claude`, `opencode`, `codex`, `generic`, `nvidia`, `gitlab`, `github`, `outlook`. +```bash +openshell provider list-profiles +openshell provider list-profiles --output json +``` ### Create a provider from local credentials @@ -103,25 +106,57 @@ The `--from-existing` flag discovers credentials from local state (e.g., `gh aut ```bash openshell provider create --name my-api --type generic \ - --credential API_KEY=sk-abc123 \ + --credential API_KEY \ --config base_url=https://api.example.com ``` -Bare `KEY` (without `=VALUE`) reads the value from the environment variable of that name: +Bare `KEY` reads the value from the environment variable of that name and avoids placing the secret in shell history. Use `KEY=VALUE` only when the user explicitly accepts that exposure. + +Other credential sources are `--from-gcloud-adc` for compatible profiles and `--runtime-credentials` when the gateway or sandbox resolves the required credentials at runtime. + +Profile-backed provider policy and composition are controlled by the gateway-global `providers_v2_enabled` setting: + +```bash +openshell settings get --global +openshell settings set --global --key providers_v2_enabled --value true +``` + +### Inspect and manage provider profiles ```bash -openshell provider create --name my-api --type generic --credential API_KEY +openshell provider profile export github --output yaml +openshell provider profile lint --file ./my-profile.yaml +openshell provider profile import --file ./my-profile.yaml ``` ### List, inspect, update, delete ```bash openshell provider list +openshell provider list --output json openshell provider get my-github -openshell provider update my-github --type github --from-existing +openshell provider update my-github --from-existing openshell provider delete my-github ``` +`provider update` does not take `--type`. It updates credentials, config, or credential expiry on the existing provider. + +### Configure credential refresh + +Use refresh commands only when the provider profile and gateway support refreshable credentials: + +```bash +openshell provider refresh status my-outlook +openshell provider refresh configure my-outlook \ + --credential-key MS_GRAPH_ACCESS_TOKEN \ + --strategy oauth2-refresh-token \ + --secret-material-env REFRESH_TOKEN=MS_GRAPH_REFRESH_TOKEN \ + --credential-expires-at 2026-07-16T00:00:00Z +openshell provider refresh rotate my-outlook --credential-key MS_GRAPH_ACCESS_TOKEN +``` + +Prefer `--secret-material-env KEY[=ENVVAR]` for secret refresh material. `--material KEY=VALUE` is for non-secret material; `--secret-material-key` marks supplied material keys as secret. + --- ## Workflow 3: Sandbox Lifecycle @@ -134,29 +169,41 @@ openshell sandbox create \ --provider my-github \ --provider my-claude \ --policy ./my-policy.yaml \ - --upload .:/sandbox \ + --upload .:/workspace \ + --label team=agents \ -- claude ``` Key flags: - `--provider`: Attach one or more providers (repeatable) - `--policy`: Custom policy YAML (otherwise uses built-in default or `OPENSHELL_SANDBOX_POLICY` env var) +- `--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. -- `--upload [:]`: Upload local files into the sandbox (default dest: `/sandbox`) +- `--driver-config-json`: Pass experimental driver-specific sandbox configuration +- `--label KEY=VALUE`: Add labels for later selection (repeatable) +- `--env KEY=VALUE`: Inject sandbox environment variables (repeatable) +- `--approval-mode manual|auto`: Control handling of agent-authored policy proposals; `manual` is the default +- `--upload [:]`: Upload local files into the container working directory or an explicit destination +- `--no-git-ignore`: Disable `.gitignore` filtering for uploads - `--no-keep`: Delete the sandbox after the initial command or shell exits -- `--forward `: Forward a local port and keep the sandbox alive +- `--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 ### List and inspect sandboxes ```bash openshell sandbox list +openshell sandbox list --selector team=agents --output json openshell sandbox get my-sandbox ``` +Most commands with an optional sandbox name use the last-used sandbox. Pass an explicit name in automation. + ### Connect to a running sandbox ```bash openshell sandbox connect my-sandbox +openshell sandbox connect my-sandbox --editor vscode ``` Opens an interactive SSH shell. To configure VS Code Remote-SSH: @@ -175,6 +222,25 @@ openshell sandbox upload my-sandbox ./src /sandbox/src openshell sandbox download my-sandbox /sandbox/output ./local-output ``` +Uploads honor `.gitignore` by default. Add `--no-git-ignore` only when ignored files are intentionally in scope. + +### Execute a non-interactive command + +```bash +openshell sandbox exec --name my-sandbox --workdir /workspace -- ls -la +openshell sandbox exec --name my-sandbox --env MODE=test -- cargo test +``` + +`sandbox exec` streams output and exits with the remote command's exit code. Use `sandbox connect` for an interactive shell. + +### Change attached providers + +```bash +openshell sandbox provider list my-sandbox +openshell sandbox provider attach my-sandbox my-github +openshell sandbox provider detach my-sandbox my-github +``` + ### View logs ```bash @@ -196,6 +262,7 @@ openshell logs my-sandbox --since 5m ```bash openshell sandbox delete my-sandbox openshell sandbox delete sandbox-1 sandbox-2 sandbox-3 # Multiple at once +openshell sandbox delete --all ``` --- @@ -256,13 +323,13 @@ Look for log lines with `action: deny` -- these indicate blocked network request openshell policy get dev --full > current-policy.yaml ``` -The `--full` flag outputs valid YAML that can be directly re-submitted. This is the round-trip format. +The `--full` flag includes the effective policy, including provider-composed entries. Use `--base` instead when the editable base policy is needed without provider-composed entries. Before resubmitting a `--full` result, review composed entries and prefer incremental updates or the base policy when appropriate. ### Step 4: Modify the policy Edit `current-policy.yaml` to allow the blocked actions. **For policy content authoring, delegate to the `generate-sandbox-policy` skill.** That skill handles: - Network endpoint rule structure -- L4 vs L7 policy decisions +- L4 vs REST, WebSocket, JSON-RPC, MCP, and SQL L7 policy decisions - Access presets (`read-only`, `read-write`, `full`) - TLS termination configuration - Enforcement modes (`audit` vs `enforce`) @@ -307,200 +374,37 @@ Fetch a specific historical revision: openshell policy get dev --rev 3 --full ``` ---- - -## Workflow 5: BYOC (Bring Your Own Container) - -Build a custom container image and run it as a sandbox. - -### Step 1: Create a sandbox from a Dockerfile - -```bash -openshell sandbox create --from ./Dockerfile --name my-app -``` - -The `--from` flag accepts a Dockerfile path, a directory containing a Dockerfile, a full image reference (e.g. `myregistry.com/img:tag`), or a community sandbox name (e.g. `openclaw`). - -When given a Dockerfile or directory, the image is built locally via Docker and delivered through the selected compute driver. Docker and Podman-backed gateways can use local images directly. Kubernetes gateways usually need the image available to the cluster through a registry or driver-supported image push path. - -When `--from` is specified, the CLI: -- Clears default `run_as_user`/`run_as_group` (custom images may not have the `sandbox` user) -- Uses a supervisor bootstrap pattern (init container copies the sandbox supervisor into a shared volume) - -### Step 2: Forward ports (if the container runs a service) +Gateway-global policy commands use `--global` and require confirmation unless `--yes` is supplied: ```bash -# Foreground (blocks) -openshell forward start 8080 my-app - -# Background (returns immediately) -openshell forward start 8080 my-app -d +openshell policy get --global --full +openshell policy set --global --policy ./global-policy.yaml +openshell policy list --global +openshell policy delete --global ``` -The service is now reachable at `localhost:8080`. - -### Step 3: Manage port forwards +Avoid `--yes` during interactive work. A global policy locks policy control for all sandboxes on the gateway. -```bash -# List active forwards -openshell forward list +### Review agent-authored rule proposals -# Stop a forward -openshell forward stop 8080 my-app -``` - -### Step 4: Iterate - -To update the container: +Sandboxes created with `--approval-mode manual` place every proposal in the review inbox. `auto` approves only proposals with an empty prover delta; findings still require review. ```bash -openshell sandbox delete my-app -openshell sandbox create --from ./Dockerfile --name my-app --forward 8080 +openshell rule get dev --status pending +openshell rule approve dev --chunk-id +openshell rule reject dev --chunk-id --reason "too broad" +openshell rule history dev ``` -### Shortcut: Create with port forward in one command - -```bash -openshell sandbox create --from ./Dockerfile --forward 8080 -- ./start-server.sh -``` - -The `--forward` flag starts a background port forward before the command runs, so the service is reachable immediately. - -### Limitations - -- Distroless / `FROM scratch` images are not supported (the supervisor needs glibc, `/proc`, and a shell) -- Missing `iproute2` or required capabilities blocks startup in proxy mode +Review the proposed scope and prover findings before approval. Treat `rule approve-all --include-security-flagged` as a high-risk bulk action. --- -## Workflow 6: Agent-Assisted Sandbox Session - -This workflow supports a human working in a sandbox while an agent monitors activity and refines the policy in parallel. - -### Step 1: Create sandbox with providers and keep alive - -```bash -openshell sandbox create \ - --name work-session \ - --provider github \ - --provider claude \ - --policy ./dev-policy.yaml \ - # sandbox create keeps the sandbox alive by default -``` - -### Step 2: User connects in a separate shell - -Tell the user to run: - -```bash -openshell sandbox connect work-session -``` - -Or for VS Code: - -```bash -openshell sandbox ssh-config work-session >> ~/.ssh/config -# Then connect via VS Code Remote-SSH to the host "work-session" -``` - -### Step 3: Agent monitors logs - -While the user works, monitor the sandbox logs: - -```bash -openshell logs work-session --tail --source sandbox --level warn -``` - -Watch for `deny` actions that indicate the user's work is being blocked by policy. - -### Step 4: Agent refines policy - -When denied actions are observed: - -1. Prefer incremental updates for additive network changes: - `openshell policy update work-session --add-endpoint api.github.com:443:read-only:rest:enforce --binary /usr/bin/gh --wait` - `openshell policy update work-session --add-allow 'api.github.com:443:POST:/repos/*/issues' --wait` -2. Use full YAML replacement when the change is broad or touches non-network fields: - `openshell policy get work-session --full > policy.yaml` - Modify the policy to allow the blocked actions (use `generate-sandbox-policy` skill for content) - `openshell policy set work-session --policy policy.yaml --wait` -3. Verify: `openshell policy list work-session` - -The user does not need to disconnect -- policy updates are hot-reloaded within ~30 seconds (or immediately when using `--wait`, which polls for confirmation). - -### Step 5: Clean up when done - -```bash -openshell sandbox delete work-session -``` - ---- - -## Workflow 7: Gateway Inference - -Configure the gateway's managed inference route for `inference.local`. - -### Set gateway inference - -First ensure the provider record exists: - -```bash -openshell provider list -``` - -Then point gateway inference at that provider and model: - -```bash -openshell inference set \ - --provider nvidia \ - --model nvidia/nemotron-3-nano-30b-a3b -``` - -This updates the gateway-managed `inference.local` route. There is no per-route create/list/update/delete workflow for sandbox inference. - -### Inspect current inference config - -```bash -openshell inference get -``` - -### How sandboxes use it - -- Agents send HTTPS requests to `inference.local`. -- The sandbox intercepts those requests locally and routes them through the gateway inference config. -- Sandbox policy is separate from gateway inference configuration. - ---- - -## Workflow 8: Gateway Management - -### List and switch gateways - -```bash -openshell gateway select # See all gateways (no args shows list) -openshell gateway select production # Switch active gateway -openshell status # Verify connectivity -``` - -### Registration - -```bash -openshell gateway add http://127.0.0.1:8080 --local --name local -openshell gateway add https://gateway.example.com --name production -openshell gateway remove local # Remove local registration -``` - -### Platform-specific deployment inspection - -```bash -# Inspect a Kubernetes Helm release and gateway pod -helm -n openshell status openshell -kubectl -n openshell get deployment,statefulset,pods,svc -kubectl -n openshell logs deployment/openshell -c openshell-gateway --tail=100 -kubectl -n openshell logs statefulset/openshell -c openshell-gateway --tail=100 -``` +## Advanced Workflows -For Docker, Podman, and VM-backed gateways, inspect the gateway process or container logs and the selected runtime directly. +Read [advanced-workflows.md](advanced-workflows.md) when the task involves BYOC, +agent-assisted policy iteration, gateway inference, gateway registration or +authentication, settings, or service exposure. Load only the relevant workflow. --- @@ -518,7 +422,7 @@ The CLI help is always authoritative. If the help output contradicts this skill, ```bash $ openshell sandbox --help -# Shows: create, get, list, delete, connect, upload, download, ssh-config, image +# Shows: create, get, list, delete, exec, connect, upload, download, ssh-config, provider $ openshell sandbox upload --help # Shows: positional arguments (name, path, dest), usage examples @@ -533,21 +437,30 @@ $ openshell sandbox upload --help | Register local port-forwarded gateway | `openshell gateway add http://127.0.0.1:8080 --local --name local` | | Check gateway health | `openshell status` | | List/switch gateways | `openshell gateway select [name]` | +| Connect directly to a gateway | `openshell --gateway-endpoint status` | | Create sandbox (interactive) | `openshell sandbox create` | | 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` | | Connect to sandbox | `openshell sandbox connect ` | +| Execute in sandbox | `openshell sandbox exec --name -- ` | | Stream live logs | `openshell logs --tail` | | Incremental policy update | `openshell policy update --add-endpoint host:443:read-only:rest:enforce --binary /usr/bin/curl --wait` | | Pull current policy | `openshell policy get --full > p.yaml` | | Push updated policy | `openshell policy set --policy p.yaml --wait` | | Policy revision history | `openshell policy list ` | +| View global policy | `openshell policy get --global --full` | +| Review proposed rules | `openshell rule get --status pending` | | Create sandbox from Dockerfile | `openshell sandbox create --from ./Dockerfile` | | Forward a port | `openshell forward start -d` | +| Expose an HTTP service | `openshell service expose [service]` | | Upload files to sandbox | `openshell sandbox upload ` | | Download files from sandbox | `openshell sandbox download ` | | Create provider | `openshell provider create --name N --type T --from-existing` | | List providers | `openshell provider list` | +| Discover provider profiles | `openshell provider list-profiles` | +| List attached providers | `openshell sandbox provider list ` | +| View settings | `openshell settings get [name]` | | Configure gateway inference | `openshell inference set --provider P --model M` | | View gateway inference | `openshell inference get` | | Delete sandbox | `openshell sandbox delete ` | diff --git a/.agents/skills/openshell-cli/advanced-workflows.md b/.agents/skills/openshell-cli/advanced-workflows.md new file mode 100644 index 0000000000..a04b89992a --- /dev/null +++ b/.agents/skills/openshell-cli/advanced-workflows.md @@ -0,0 +1,215 @@ +# OpenShell CLI Advanced Workflows + +Use this reference with [SKILL.md](SKILL.md). Load only the workflow relevant to +the current task. + +## Contents + +- [BYOC](#byoc-bring-your-own-container) +- [Agent-assisted sandbox session](#agent-assisted-sandbox-session) +- [Gateway inference](#gateway-inference) +- [Gateway management](#gateway-management) +- [Settings management](#settings-management) +- [Service access](#service-access) + +## BYOC (Bring Your Own Container) + +Build a custom container image and run it as a sandbox. + +### Create a sandbox from a Dockerfile + +```bash +openshell sandbox create --from ./Dockerfile --name my-app +``` + +The `--from` flag accepts a Dockerfile path, a directory containing a Dockerfile, +a full image reference such as `myregistry.com/img:tag`, or a community sandbox +name such as `ollama`. + +Local Dockerfile and directory builds require a local gateway because the CLI +builds through the local Docker daemon. Use a registry image reference for remote +gateways. Bare community names resolve under +`ghcr.io/nvidia/openshell-community/sandboxes` unless +`OPENSHELL_COMMUNITY_REGISTRY` overrides the prefix. + +### Forward ports + +```bash +# Foreground (blocks) +openshell forward start 8080 my-app + +# Background (returns immediately) +openshell forward start 8080 my-app -d +``` + +The service is now reachable at `localhost:8080`. + +Manage or iterate on the sandbox: + +```bash +openshell forward list +openshell forward stop 8080 my-app +openshell sandbox delete my-app +openshell sandbox create --from ./Dockerfile --name my-app --forward 8080 +``` + +Create and forward in one command: + +```bash +openshell sandbox create --from ./Dockerfile --forward 8080 -- ./start-server.sh +``` + +The `--forward` flag starts a background port forward before the command runs. + +## Agent-Assisted Sandbox Session + +Support a human working in a sandbox while an agent monitors activity and refines +the policy in parallel. + +Create the sandbox and keep it alive: + +```bash +openshell sandbox create \ + --name work-session \ + --provider github \ + --provider claude \ + --policy ./dev-policy.yaml +``` + +Tell the user to connect in another shell: + +```bash +openshell sandbox connect work-session +openshell sandbox connect work-session --editor vscode +``` + +Monitor denied activity: + +```bash +openshell logs work-session --tail --source sandbox --level warn +``` + +When denied actions appear: + +1. Prefer incremental updates for additive network changes: + `openshell policy update work-session --add-endpoint api.github.com:443:read-only:rest:enforce --binary /usr/bin/gh --wait` + `openshell policy update work-session --add-allow 'api.github.com:443:POST:/repos/*/issues' --wait` +2. Use full YAML replacement for broad changes or non-network fields: + `openshell policy get work-session --full > policy.yaml` + Modify the policy with the `generate-sandbox-policy` skill. + `openshell policy set work-session --policy policy.yaml --wait` +3. Verify with `openshell policy list work-session`. + +The user does not need to disconnect. Policy updates are hot-reloaded; `--wait` +blocks until the sandbox confirms the revision or the timeout expires. Delete the +sandbox when the session ends: + +```bash +openshell sandbox delete work-session +``` + +## Gateway Inference + +Configure the gateway's user-facing `inference.local` route or the system +inference route used by platform functions. + +Ensure the provider exists, then set the route: + +```bash +openshell provider list +openshell inference set \ + --provider nvidia \ + --model nvidia/nemotron-3-nano-30b-a3b +``` + +This updates the gateway-managed `inference.local` route. Endpoint verification +runs before the route is saved. Use `--no-verify` only when verification is +intentionally impossible, and use `--timeout SECONDS` to configure the request +timeout. Add `--system` to `set` or `update` for the platform-only system route. + +Inspect both configurations: + +```bash +openshell inference get +openshell inference get --system +``` + +Agents send HTTPS requests to `inference.local`; the sandbox intercepts them and +routes them through the gateway inference config. Sandbox policy remains separate +from gateway inference configuration. + +## Gateway Management + +List, switch, and verify gateways: + +```bash +openshell gateway select +openshell gateway list --output json +openshell gateway select production +openshell gateway info --name production +openshell status +``` + +Register or remove gateways: + +```bash +openshell gateway add http://127.0.0.1:8080 --local --name local +openshell gateway add https://gateway.example.com --name production +openshell gateway remove local +``` + +`https://` registrations default to edge authentication. Use `gateway login` and +`gateway logout` to refresh or clear stored authentication. For an OIDC gateway, +supply `--oidc-issuer` and, when needed, `--oidc-client-id`, `--oidc-audience`, and +`--oidc-scopes`. For remote mTLS gateways, use `--remote USER@HOST` or an `ssh://` +endpoint. + +For one-off automation, `--gateway-endpoint URL` connects directly without stored +metadata. Limit `--gateway-insecure` to explicitly trusted development endpoints. + +Inspect a Kubernetes deployment: + +```bash +helm -n openshell status openshell +kubectl -n openshell get deployment,statefulset,pods,svc +kubectl -n openshell logs deployment/openshell -c openshell-gateway --tail=100 +kubectl -n openshell logs statefulset/openshell -c openshell-gateway --tail=100 +``` + +For Docker, Podman, and VM-backed gateways, inspect the gateway process or +container logs and the selected runtime directly. + +## Settings Management + +Manage sandbox-scoped or gateway-global settings: + +```bash +openshell settings get work-session +openshell settings set work-session --key ocsf_json_enabled --value true +openshell settings delete work-session --key ocsf_json_enabled + +openshell settings get --global --json +openshell settings set --global --key providers_v2_enabled --value true +``` + +Global mutations prompt for confirmation. Use `--yes` only in reviewed automation. + +## Service Access + +Use `forward` for local access and `service` for a gateway-managed HTTP endpoint: + +```bash +# SSH-based same-port forwarding; optional bind address is accepted. +openshell forward start 127.0.0.1:8080 my-app -d + +# gRPC relay to a loopback TCP service, with an optional dynamic local port. +openshell forward service my-app --target-port 8000 --local 127.0.0.1:0 + +# Expose and manage an HTTP service through the gateway. +openshell service expose my-app 8080 web +openshell service list my-app +openshell service get my-app web +openshell service delete my-app web +``` + +Prefer loopback binds unless the user explicitly needs LAN-visible local access. diff --git a/.agents/skills/openshell-cli/cli-reference.md b/.agents/skills/openshell-cli/cli-reference.md index 7998502326..4266d5a185 100644 --- a/.agents/skills/openshell-cli/cli-reference.md +++ b/.agents/skills/openshell-cli/cli-reference.md @@ -4,19 +4,40 @@ Quick-reference for the `openshell` command-line interface. For workflow guidanc > **Self-teaching**: If a command or flag is not listed here, use `openshell --help` to discover it. The CLI has comprehensive built-in help at every level. +## Contents + +- [Global options](#global-options) +- [Environment variables](#environment-variables) +- [Complete command tree](#complete-command-tree) +- [Gateway commands](#gateway-commands) +- [Doctor and status commands](#doctor-commands) +- [Sandbox commands](#sandbox-commands) +- [Port forwarding and service commands](#port-forwarding-commands) +- [Logs](#logs-command) +- [Policy and settings commands](#policy-commands) +- [Provider commands](#provider-commands) +- [Inference commands](#inference-commands) +- [Other commands](#other-commands) + ## Global Options | Flag | Description | |------|-------------| | `-v`, `--verbose` | Increase verbosity (`-v` = info, `-vv` = debug, `-vvv` = trace) | | `-g`, `--gateway ` | Gateway to operate on. Also settable via `OPENSHELL_GATEWAY` env var. Falls back to active gateway in `~/.config/openshell/active_gateway`. | +| `--gateway-endpoint ` | Connect directly to a gateway endpoint without looking up stored metadata. Also settable via `OPENSHELL_GATEWAY_ENDPOINT`. | +| `--gateway-insecure` | Skip TLS certificate verification. Also settable via `OPENSHELL_GATEWAY_INSECURE`; use only for trusted development endpoints. | ## Environment Variables | Variable | Description | |----------|-------------| | `OPENSHELL_GATEWAY` | Override active gateway name (same as `--gateway`) | +| `OPENSHELL_GATEWAY_ENDPOINT` | Connect directly to a gateway endpoint (same as `--gateway-endpoint`) | +| `OPENSHELL_GATEWAY_INSECURE` | Skip TLS verification when set (same as `--gateway-insecure`) | | `OPENSHELL_SANDBOX_POLICY` | Path to default sandbox policy YAML (fallback when `--policy` is not provided) | +| `OPENSHELL_COMMUNITY_REGISTRY` | Override the community sandbox image registry prefix used by `sandbox create --from ` | +| `OPENSHELL_THEME` | TUI theme: `auto`, `dark`, or `light` | --- @@ -39,29 +60,64 @@ openshell │ └── get ├── sandbox │ ├── create [opts] [-- CMD...] -│ ├── get +│ ├── get [name] │ ├── list [opts] -│ ├── delete ... -│ ├── connect +│ ├── delete [name]... [--all] +│ ├── exec [--name ] [opts] -- CMD... +│ ├── connect [name] [--editor ] │ ├── upload [dest] │ ├── download [dest] -│ ├── ssh-config -│ └── image -│ └── push [opts] +│ ├── ssh-config [name] +│ └── provider +│ ├── list [name] +│ ├── attach +│ └── detach ├── forward -│ ├── start [-d] -│ ├── stop -│ └── list -├── logs [opts] +│ ├── start [name] [-d] +│ ├── stop [name] +│ ├── list +│ └── service [name] --target-port [opts] +├── service +│ ├── expose [service] +│ ├── list [sandbox] +│ ├── get [service] +│ └── delete [service] +├── logs [name] [opts] ├── policy -│ ├── set --policy [--wait] -│ ├── get [--full] -│ └── list +│ ├── set [name] --policy [--global] [--wait] +│ ├── update [name] [opts] +│ ├── get [name] [--full|--base] [--global] +│ ├── list [name] [--global] +│ ├── delete --global +│ └── prove --policy --credentials [opts] +├── settings +│ ├── get [name] [--global] +│ ├── set [name] --key --value [--global] +│ └── delete [name] --key [--global] +├── rule (advanced; hidden from top-level help) +│ ├── get [name] [--status ] +│ ├── approve [name] --chunk-id +│ ├── reject [name] --chunk-id [--reason ] +│ ├── approve-all [name] [--include-security-flagged] +│ ├── clear [name] +│ └── history [name] ├── provider │ ├── create --name --type [opts] +│ ├── refresh +│ │ ├── status [opts] +│ │ ├── configure [opts] +│ │ ├── rotate --credential-key +│ │ └── delete --credential-key │ ├── get │ ├── list [opts] -│ ├── update --type [opts] +│ ├── list-profiles [opts] +│ ├── profile +│ │ ├── export [opts] +│ │ ├── import (--file |--from ) +│ │ ├── update --file +│ │ ├── lint (--file |--from ) +│ │ └── delete +│ ├── update [opts] │ └── delete ... ├── doctor │ └── check @@ -81,13 +137,20 @@ Register an existing gateway endpoint. | Flag | Description | |------|-------------| | `--name ` | Gateway name | -| `--local` | Register a local endpoint, commonly a trusted port-forward | -| `--remote ` | Register a remote gateway associated with an SSH destination | +| `--local` | Register a local mTLS gateway; with HTTP, store a local plaintext registration | +| `--remote ` | Register a remote mTLS gateway over SSH; with HTTP, store a remote plaintext registration | +| `--oidc-issuer ` | Register an OIDC-authenticated gateway | +| `--oidc-client-id ` | OIDC client ID (default: `openshell-cli`; requires `--oidc-issuer`) | +| `--oidc-audience ` | OIDC API audience (requires `--oidc-issuer`) | +| `--oidc-scopes ` | Space-separated OAuth2 scopes (requires `--oidc-issuer`) | Examples: - `openshell gateway add http://127.0.0.1:8080 --local --name local` - `openshell gateway add https://gateway.example.com --name production` +- `openshell gateway add ssh://user@gateway.example.com:8080 --name remote` + +An `http://` endpoint is direct plaintext. A plain `https://` endpoint uses edge authentication. `--local` and `--remote` select mTLS registration modes when used with HTTPS; required certificates must already exist. An `ssh://` endpoint is shorthand for a remote gateway. ### `openshell gateway remove [name]` @@ -95,7 +158,11 @@ Remove a local gateway registration. This removes CLI metadata and stored auth t ### `openshell gateway login [name]` -Refresh browser-based authentication for a gateway behind an edge proxy. +Refresh browser-based authentication for an edge-authenticated or OIDC gateway. + +### `openshell gateway logout [name]` + +Clear locally stored OIDC or edge credentials for a gateway. ### `openshell gateway info` @@ -107,7 +174,11 @@ Show gateway details: endpoint, auth mode, and remote host metadata when present ### `openshell gateway select [name]` -Set the active gateway. Writes to `~/.config/openshell/active_gateway`. When called without arguments, lists all registered gateways with the active one marked with `*`. +Set the active gateway. Writes to `~/.config/openshell/active_gateway`. Without a name, opens an interactive chooser on a TTY or lists gateways in non-interactive mode. + +### `openshell gateway list` + +List registered gateways and mark the active one. `--output table|yaml|json` selects the format. --- @@ -133,103 +204,138 @@ Show server connectivity and version for the active gateway. ### `openshell sandbox create [OPTIONS] [-- COMMAND...]` -Create a sandbox through the active gateway, wait for readiness, then connect or execute the trailing command. +Create a sandbox through the selected gateway, wait for readiness, then connect, open an editor, or execute the trailing command. | Flag | Description | |------|-------------| | `--name ` | Sandbox name (auto-generated if omitted) | -| `--from ` | Sandbox source: community name, Dockerfile path, directory, or image reference (BYOC) | -| `--upload [:]` | Upload local files into sandbox (default dest: `/sandbox`) | -| `--no-keep` | Delete sandbox after the initial command or shell exits | +| `--from ` | Community name, Dockerfile path, directory, or image reference (BYOC) | +| `--no-keep` | Delete the sandbox after the initial command or shell exits | +| `--editor vscode|cursor` | Launch a remote editor and keep the sandbox alive | +| `--gpu [COUNT]` | Request the driver's default GPU selection or a specific count | +| `--cpu ` | CPU limit (for example: `500m`, `1`, `2.5`) | +| `--memory ` | Memory limit (for example: `512Mi`, `4Gi`, `8G`) | +| `--driver-config-json ` | Experimental driver-keyed configuration object | | `--provider ` | Provider to attach (repeatable) | -| `--policy ` | Path to custom policy YAML | -| `--cpu ` | CPU amount for the sandbox (for example: `500m`, `1`, `2.5`) | -| `--memory ` | Memory amount for the sandbox (for example: `512Mi`, `4Gi`, `8G`) | -| `--forward ` | Forward local port to sandbox (keeps the sandbox alive) | -| `--tty` | Force pseudo-terminal allocation | -| `--no-tty` | Disable pseudo-terminal allocation | -| `--auto-providers` | Auto-create missing providers from local credentials (skips interactive prompt) | -| `--no-auto-providers` | Never auto-create providers; skip missing providers silently | -| `[-- COMMAND...]` | Command to execute (defaults to interactive shell) | - -### `openshell sandbox get ` - -Show sandbox details (id, name, namespace, phase) and the **active** policy from the gateway (same source whether policy is sandbox-scoped or global). Metadata includes **Policy source** (`sandbox` or `global`) and **Revision** (global policy row when source is global, otherwise sandbox policy row). +| `--policy ` | 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 | +| `--tty`, `--no-tty` | Force or disable pseudo-terminal allocation | +| `--auto-providers` | Auto-create missing providers from local credentials | +| `--no-auto-providers` | Never auto-create providers; error if a required provider is missing | +| `--label ` | Attach a label (repeatable) | +| `--env ` | Inject an environment variable (repeatable) | +| `--approval-mode manual|auto` | Handle agent-authored policy proposals; default: `manual` | +| `--upload [:]` | Upload local files to the working directory or an explicit destination (repeatable) | +| `--no-git-ignore` | Disable `.gitignore` filtering for `--upload` | +| `[-- COMMAND...]` | Initial command (defaults to an interactive shell) | + +### `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. | Flag | Description | |------|-------------| -| `--policy-only` | Print only the active policy YAML to stdout (same policy as above; use for scripts and piping) | +| `--policy-only` | Print only the active policy YAML to stdout | ### `openshell sandbox list` -List sandboxes in a table. - | Flag | Default | Description | |------|---------|-------------| -| `--limit ` | 100 | Max sandboxes to return | +| `--limit ` | 100 | Maximum sandboxes | | `--offset ` | 0 | Pagination offset | | `--ids` | false | Print only sandbox IDs | | `--names` | false | Print only sandbox names | +| `--selector ` | none | Filter by `key1=value1,key2=value2` | +| `--output table|yaml|json` | `table` | Output format | -### `openshell sandbox delete ...` +### `openshell sandbox delete [NAME]...` -Delete one or more sandboxes by name. Stops any background port forwards. +Delete one or more named sandboxes, or use `--all`. Deletion stops background port forwards. -### `openshell sandbox connect ` +### `openshell sandbox exec [OPTIONS] -- COMMAND...` -Open an interactive SSH shell to a sandbox. +Execute a command through the gRPC exec endpoint, stream its output, and exit with the remote command's exit code. -### `openshell sandbox upload [dest]` +| Flag | Default | Description | +|------|---------|-------------| +| `-n`, `--name ` | last-used | Sandbox name | +| `--workdir ` | none | Working directory in the sandbox | +| `--timeout ` | 0 | Command timeout; `0` disables it | +| `--tty`, `--no-tty` | auto | Force or disable a pseudo-terminal | +| `--env ` | none | Command environment variable (repeatable) | + +### `openshell sandbox connect [name]` -Upload local files to a sandbox using tar-over-SSH. +Open an interactive SSH shell. The name defaults to the last-used sandbox. `--editor vscode|cursor` launches a supported remote editor instead. -| Argument | Default | Description | -|----------|---------|-------------| -| `` | -- | Sandbox name (required) | -| `` | -- | Local path to upload (required) | -| `[dest]` | `/sandbox` | Destination path in sandbox | +### `openshell sandbox upload [dest]` + +Upload files using tar-over-SSH. The destination defaults to the container working directory. `.gitignore` filtering is enabled unless `--no-git-ignore` is passed. ### `openshell sandbox download [dest]` -Download files from a sandbox using tar-over-SSH. +Download files using tar-over-SSH. The local destination defaults to `.`. + +### `openshell sandbox ssh-config [name]` + +Print an SSH config `Host` block. The name defaults to the last-used sandbox. -| Argument | Default | Description | -|----------|---------|-------------| -| `` | -- | Sandbox name (required) | -| `` | -- | Sandbox path to download (required) | -| `[dest]` | `.` | Local destination path | +### `openshell sandbox provider` -### `openshell sandbox ssh-config ` +Manage providers on an existing sandbox: -Print an SSH config `Host` block for a sandbox. Useful for VS Code Remote-SSH. +- `openshell sandbox provider list [name]` +- `openshell sandbox provider attach ` +- `openshell sandbox provider detach ` --- ## Port Forwarding Commands -### `openshell forward start ` +### `openshell forward start [name]` Start forwarding a local port to a sandbox. | Flag | Description | |------|-------------| -| `` | Port number (used as both local and remote) | -| `` | Sandbox name | +| `` | `[bind_address:]port`; the port is used locally and remotely | +| `[name]` | Sandbox name (defaults to last-used) | | `-d`, `--background` | Run in background | -### `openshell forward stop ` +### `openshell forward stop [name]` -Stop a background port forward. +Stop a background port forward. When the sandbox name is omitted, it is inferred from active forwards. ### `openshell forward list` List all active port forwards (sandbox, port, PID, status). +### `openshell forward service [name] --target-port ` + +Forward a local TCP port to a loopback service inside a sandbox over the gRPC relay. + +| Flag | Default | Description | +|------|---------|-------------| +| `--target-port ` | required | Service port inside the sandbox | +| `--target-host ` | `127.0.0.1` | Loopback service host | +| `--local <[BIND:]PORT>` | target port | Local bind; port `0` requests dynamic assignment | + +--- + +## Service Commands + +Gateway-managed HTTP service endpoints: + +- `openshell service expose [service]` +- `openshell service list [sandbox] [--limit N] [--offset N]` +- `openshell service get [service]` +- `openshell service delete [service]` + --- ## Logs Command -### `openshell logs ` +### `openshell logs [name]` View sandbox logs. Supports one-shot and streaming. @@ -241,20 +347,22 @@ View sandbox logs. Supports one-shot and streaming. | `--source ` | `all` | Filter: `gateway`, `sandbox`, or `all` (repeatable) | | `--level ` | none | Minimum level: `error`, `warn`, `info`, `debug`, `trace` | +The sandbox name defaults to the last-used sandbox. + --- ## Policy Commands -### `openshell policy update ` +### `openshell policy update [name]` Incrementally merge live network policy changes into the current sandbox policy. Multiple flags in one invocation are applied as one atomic batch and create at most one new revision. | Flag | Default | Description | |------|---------|-------------| -| `--add-endpoint ` | repeatable | `host:port[:access[:protocol[:enforcement]]]`. Adds or merges an endpoint. `access`: `read-only`, `read-write`, `full`. `protocol`: `rest`, `sql`. `enforcement`: `enforce`, `audit`. | +| `--add-endpoint ` | repeatable | `host:port[:access[:protocol[:enforcement[:options]]]]`. Adds or merges an endpoint. | | `--remove-endpoint ` | repeatable | `host:port`. Removes the endpoint or just the requested port from a multi-port endpoint. | -| `--add-allow ` | repeatable | `host:port:METHOD:path_glob`. Adds REST allow rules to an existing `protocol: rest` endpoint. | -| `--add-deny ` | repeatable | `host:port:METHOD:path_glob`. Adds REST deny rules to an existing `protocol: rest` endpoint that already has an allow base. | +| `--add-allow ` | repeatable | `host:port:METHOD:path_glob`. Adds REST or WebSocket allow rules. | +| `--add-deny ` | repeatable | `host:port:METHOD:path_glob`. Adds REST or WebSocket deny rules. | | `--remove-rule ` | repeatable | Deletes a named network rule. | | `--binary ` | repeatable | Adds binaries to each `--add-endpoint` rule. Valid only with `--add-endpoint`. | | `--rule-name ` | none | Overrides the generated rule name. Valid only when exactly one `--add-endpoint` is provided. | @@ -264,44 +372,92 @@ Incrementally merge live network policy changes into the current sandbox policy. Notes: -- `--add-allow` and `--add-deny` currently operate only on `protocol: rest` endpoints. +- The sandbox name defaults to the last-used sandbox. +- `--add-allow` and `--add-deny` operate on REST and WebSocket endpoints. Use full YAML for JSON-RPC, MCP, SQL, or other policy structure. - `--wait` cannot be combined with `--dry-run`. - Use `policy set` when replacing the full policy or changing static sections. -### `openshell policy set --policy ` +### `openshell policy set [name] --policy ` Replace the full policy on a live sandbox. Only the dynamic `network_policies` field can be changed at runtime. | Flag | Default | Description | |------|---------|-------------| | `--policy ` | -- | Path to policy YAML (required) | +| `--global` | false | Apply as the gateway-global policy | +| `--yes` | false | Skip confirmation for a global update | | `--wait` | false | Wait for sandbox to confirm policy is loaded | | `--timeout ` | 60 | Timeout for `--wait` | Exit codes with `--wait`: 0 = loaded, 1 = failed, 124 = timeout. -### `openshell policy get ` +### `openshell policy get [name]` -Show current active policy for a sandbox. +Show the current effective sandbox policy or stored global policy. | Flag | Default | Description | |------|---------|-------------| -| `--rev ` | 0 (latest) | Show a specific revision | -| `--full` | false | Print the full policy as YAML (round-trips with `--policy` input) | +| `--rev ` | 0 | Show a stored revision; `0` shows the current effective policy | +| `--full` | false | Include the effective policy payload and provider-composed entries | +| `--base` | false | Include the base policy payload without provider-composed entries | +| `--output table|json` | `table` | Output format | +| `--global` | false | Show the global policy revision | -### `openshell policy list ` +### `openshell policy list [name]` List policy revision history (version, hash, status, created, error). | Flag | Default | Description | |------|---------|-------------| | `--limit ` | 20 | Max revisions to return | +| `--global` | false | List global policy revisions | + +### `openshell policy delete --global` + +Delete the global policy lock and restore sandbox-level policy control. `--yes` skips confirmation. + +### `openshell policy prove` + +Prove policy properties or find counterexamples. + +| Flag | Description | +|------|-------------| +| `--policy ` | Policy YAML (required) | +| `--credentials ` | Credential descriptor YAML (required) | +| `--registry ` | Capability registry directory (defaults to bundled) | +| `--accepted-risks ` | Accepted-risks YAML | +| `--compact` | One-line-per-finding output | + +### `openshell rule` (advanced) + +Review agent-authored network rule proposals. This command group is intentionally hidden from top-level help but is part of the policy-advisor workflow. + +- `openshell rule get [name] [--status pending|approved|rejected]` +- `openshell rule approve [name] --chunk-id ` +- `openshell rule reject [name] --chunk-id [--reason ]` +- `openshell rule approve-all [name] [--include-security-flagged]` +- `openshell rule clear [name]` +- `openshell rule history [name]` + +Sandbox names default to the last-used sandbox. Bulk approval of security-flagged proposals requires explicit `--include-security-flagged`. + +--- + +## Settings Commands + +Settings support sandbox and gateway-global scopes: + +- `openshell settings get [name] [--global] [--json]` +- `openshell settings set [name] --key --value [--global] [--yes]` +- `openshell settings delete [name] --key [--global] [--yes]` + +Sandbox names default to the last-used sandbox. Global mutations prompt unless `--yes` is passed. --- ## Provider Commands -Supported provider types: `claude`, `opencode`, `codex`, `generic`, `nvidia`, `gitlab`, `github`, `outlook`. +Provider types are defined by built-in and custom provider profiles. Use `openshell provider list-profiles` to discover the selected gateway's current inventory. ### `openshell provider create --name --type ` @@ -311,10 +467,14 @@ Create a provider configuration. |------|-------------| | `--name ` | Provider name (required) | | `--type ` | Provider type (required) | -| `--from-existing` | Load credentials from local state (mutually exclusive with `--credential`) | +| `--from-existing` | Load credentials and config from local state | | `--credential KEY[=VALUE]` | Credential pair. Bare `KEY` reads from env var. Repeatable. | +| `--from-gcloud-adc` | Load a compatible credential from gcloud Application Default Credentials | +| `--runtime-credentials` | Resolve required credentials at runtime in the gateway or sandbox | | `--config KEY=VALUE` | Config key/value pair. Repeatable. | +Exactly one credential source is required. Credential-source flags conflict with one another. + ### `openshell provider get ` Show provider details (id, name, type, credential keys, config keys). @@ -328,40 +488,80 @@ List providers in a table. | `--limit ` | 100 | Max providers | | `--offset ` | 0 | Pagination offset | | `--names` | false | Print only names | +| `--output table|yaml|json` | `table` | Output format | -### `openshell provider update --type ` +### `openshell provider update ` -Update an existing provider. Same flags as `create`. +Update an existing provider without changing its type. + +| Flag | Description | +|------|-------------| +| `--from-existing` | Rediscover local credentials and config | +| `--credential KEY[=VALUE]` | Update a credential (repeatable) | +| `--config KEY=VALUE` | Update config (repeatable) | +| `--credential-expires-at KEY=TIMESTAMP` | Set or clear credential expiry; accepts epoch milliseconds or RFC3339, and `0` clears | ### `openshell provider delete ...` Delete one or more providers by name. +### Provider profiles + +- `openshell provider list-profiles [--output table|yaml|json]` +- `openshell provider profile export [--output table|yaml|json]` +- `openshell provider profile import (--file |--from )` +- `openshell provider profile update --file ` +- `openshell provider profile lint (--file |--from )` +- `openshell provider profile delete ` + +### Provider credential refresh + +- `openshell provider refresh status [--credential-key ]` +- `openshell provider refresh rotate --credential-key ` +- `openshell provider refresh delete --credential-key ` + +`provider refresh configure ` accepts: + +| Flag | Description | +|------|-------------| +| `--credential-key ` | Injectable credential key (required) | +| `--strategy ` | `oauth2-refresh-token`, `oauth2-client-credentials`, or `google-service-account-jwt` | +| `--material KEY=VALUE` | Non-secret refresh material (repeatable) | +| `--secret-material-env KEY[=ENVVAR]` | Secret refresh material read from the CLI environment (repeatable) | +| `--secret-material-key KEY` | Mark a supplied material key secret (repeatable) | +| `--credential-expires-at TIMESTAMP` | Current credential expiry in epoch milliseconds or RFC3339 | + --- ## Inference Commands ### `openshell inference set` -Configure the managed gateway inference route used by `inference.local`. Both flags are required. +Configure the gateway's user-facing `inference.local` route or the platform-only system route. Provider and model are required. | Flag | Default | Description | |------|---------|-------------| | `--provider ` | -- | Provider record name (required) | | `--model ` | -- | Model identifier to use for generation requests (required) | +| `--system` | false | Configure the system inference route | +| `--no-verify` | false | Skip endpoint verification before saving | +| `--timeout ` | 0 | Request timeout; `0` uses the 60-second default | ### `openshell inference update` -Partially update the gateway inference configuration. Fetches the current config and applies only the provided overrides. At least one flag is required. +Partially update the selected inference route. | Flag | Default | Description | |------|---------|-------------| | `--provider ` | unchanged | Provider record name | | `--model ` | unchanged | Model identifier | +| `--system` | false | Target the system inference route | +| `--no-verify` | false | Skip endpoint verification before saving | +| `--timeout ` | unchanged | Request timeout; `0` uses the 60-second default | ### `openshell inference get` -Show the current gateway inference configuration. +Show both inference routes. `--system` shows only the system route. --- @@ -369,7 +569,7 @@ Show the current gateway inference configuration. ### `openshell term` -Launch the OpenShell interactive TUI. +Launch the OpenShell interactive TUI. `--theme auto|dark|light` overrides `OPENSHELL_THEME`. ### `openshell completions ` diff --git a/.agents/skills/sync-agent-infra/SKILL.md b/.agents/skills/sync-agent-infra/SKILL.md index 2c87dd4182..03dca7c834 100644 --- a/.agents/skills/sync-agent-infra/SKILL.md +++ b/.agents/skills/sync-agent-infra/SKILL.md @@ -9,7 +9,7 @@ Detect and fix drift across the agent-first infrastructure files. These files re | File | What it tracks | |------|---------------| -| `AGENTS.md` | Project identity, workflow chains, architecture overview, issue/PR conventions | +| `AGENTS.md` | Project identity, workflow chains, architecture overview, issue/PR conventions, skill maintenance map | | `CONTRIBUTING.md` | Skills table, workflow chains, "When to Open an Issue" guidance, skill references | | `README.md` | "Built With Agents" section, "Explore with your agent" skill references | | `.github/ISSUE_TEMPLATE/bug_report.yml` | Skill name references in diagnostic guidance | @@ -25,6 +25,7 @@ Detect and fix drift across the agent-first infrastructure files. These files re - After adding, removing, or renaming a skill in `.agents/skills/` - After adding, removing, or renaming a crate in `crates/` - After changing workflow chain relationships between skills +- After changing which product or development areas a skill covers - After modifying issue or PR templates - Before opening a PR that touches any of the above @@ -77,6 +78,7 @@ For each file in the table above, check for the following inconsistencies: 1. **Architecture overview** — Every crate in `crates/` must appear in the architecture table. The `python/`, `proto/`, `deploy/`, `.agents/` rows must also be present. 2. **Workflow chains** — Verify each skill named in a chain exists in `.agents/skills/`. 3. **Issue/PR conventions** — Verify referenced skills (`create-github-issue`, `create-github-pr`, `build-from-issue`) exist. +4. **Skill maintenance map** — Verify each named skill exists and the mapped change areas still match the skill descriptions and current repository boundaries. ### `README.md` @@ -125,6 +127,7 @@ If any inconsistencies are found, report them in a structured format: ### Cross-References - : references non-existent skill - : references non-existent label