mcpField
O
openshell-cli

openshell-cli

github.com/nvidia云与 DevOps20.6k577 次安装今天更新
代码仓库

关于 openshell-cli

openshell-cli 是指导 Agent 使用 openshell 命令行管理沙箱与平台资源的技能,适用于需要编排 OpenShell 工作流的用户。内容涵盖网关、沙箱、Provider、配置文件和策略生命周期,并建议以 CLI 内置帮助为准。

主要功能

  1. 01管理网关与沙箱
  2. 02创建和维护 Provider
  3. 03检查与导入配置文件
  4. 04编排凭据及策略流程
  5. 05通过内置帮助查找命令

适用场景

  1. 01连接网关并启动沙箱
  2. 02为沙箱配置 Provider 凭据
  3. 03检查或导入 Provider 配置文件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/nvidia/openshell --skill openshell-cli

安装后在 Claude Code 中输入/openshell-cli确认已加载。

详细介绍

OpenShell CLI

指导 Agent 使用 openshell CLI 管理沙盒和平台——从基本操作到高级多步骤工作流。

概述

OpenShell CLI(openshell)是管理沙盒、提供方、策略、设置、暴露的服务和网关注册的主要接口。网关服务的生命周期由软件包、systemd 或 Helm 在 CLI 之外处理。本技能将指导 Agent 编排 CLI 命令,以完成常见和复杂的工作流。

配套技能:要创建或修改沙盒策略 YAML 内容(网络规则、L7 检查、访问预设),请使用 generate-sandbox-policy 技能。本技能介绍策略生命周期的 CLI 命令;generate-sandbox-policy 则介绍策略内容的编写。

自学:CLI 内置了全面的帮助信息。遇到本技能未涵盖的命令或选项时,请沿着帮助树逐级查看:

openshell --help                    # Top-level commands
openshell <group> --help            # Subcommands in a group
openshell <group> <cmd> --help      # Flags for a specific command

这是首选的备用方案,可随时使用——CLI 的帮助输出具有权威性,且始终保持最新。

前置条件

  • openshell 已加入 PATH。若尚未安装,请参阅发布的安装指南。
  • 可访问由 Docker、Podman、Kubernetes 或实验性 VM 驱动程序支持的 OpenShell 网关
  • 仅在使用 BYOC 本地构建或 Docker 支持的网关时,才需要运行 Docker
  • 对于 Kubernetes 部署:可访问目标集群的 kubectl 和 Helm

权威参考资料

以 openshell --help 和嵌套的 --help 输出为准,了解已安装 CLI 版本的信息。使用发布的文档了解产品概念和受支持的工作流:


工作流 1:开始使用

当用户已有网关端点,并希望首次启动沙盒时,请使用此工作流。

步骤 1:注册网关
openshell gateway add http://127.0.0.1:8080 --local --name local

仅当用于可信的本地端口转发或受保护的私有路径时,才使用 http:// 端点。对于位于经过身份验证的反向代理之后的网关,请使用 openshell gateway add https://gateway.example.com 注册其 HTTPS 端点。

步骤 2:验证网关
openshell status
openshell whoami

确认网关可访问、身份验证有效或无需身份验证,并且 输出中显示了版本号。Status: Connected 仅能证明公共健康检查 端点可访问;运行受保护的命令前,请单独检查 Authentication 行。 openshell whoami 会报告经网关验证的身份,包括管理员用于授予 工作区成员资格的主体。自动化时可添加 --output json。

步骤 3:创建沙箱

启动沙箱最简单的方法:

openshell sandbox create

这会创建一个沙箱,其规范主进程为 /bin/bash -l,并将你的终端连接到该保留进程。添加 --detach,即可在沙箱就绪后返回,而不连接到该进程。

即使 stdin 或 stdout 不是终端,显式指定的末尾命令也会在前台运行。CLI 会流式传输其 stdout 和 stderr,并在输出排空后报告命令的退出状态。如果输出传送失败,即使命令本身已成功退出,CLI 也会报告失败;重试可能产生副作用的操作前,请检查沙箱状态。退出代码为 0 时,保留的沙箱状态为 Completed;非零时,状态为 Error,并显示 MainProcessFailed。使用 --no-keep 可在输出排空后删除这两种结果,或使用 --detach 运行长时间运行的服务。当网关应在没有主机连接的情况下运行服务,并在服务退出后删除其沙箱时,可组合使用 --detach --no-keep。

指定 --name 时,请使用可移植的 DNS-1123 标签:最多 63 个小写字母、数字或 - 字符,且必须以字母或数字开头和结尾。Kubernetes 驱动程序会拒绝大写字母、下划线、点号以及其他无法转换为 Kubernetes 资源标签的名称。

提供方连接需显式指定。使用 --provider 命名每个提供方;末尾命令不会选择或连接提供方。如果指定的提供方不存在,但有可用的同 ID 配置文件,CLI 可以根据本地凭据创建该提供方:

openshell sandbox create --from registry.example.com/your-org/claude-agent:latest --provider claude-code -- claude
openshell sandbox create --from registry.example.com/your-org/codex-agent:latest --provider codex -- codex

如果缺少凭据,Agent 会提示用户交互式地提供。

步骤 4:退出并清理

使用 exit 退出沙箱 shell,或按 Ctrl-D 分离,然后:

openshell sandbox delete <name>

工作流 2:提供方管理

提供方为沙箱提供凭据和特定于提供方的配置。提供方配置文件只能导入:网关只提供操作员导入的内容,而新网关的目录为空。切勿依赖硬编码的类型列表或 gh、claude 等旧别名——--type 会与配置文件 ID 精确匹配。发现所选网关上可用的配置文件:

openshell profile list
openshell profile list --type provider --output json
使用本地凭据创建提供方
openshell provider create --name my-github --type github --from-existing

--from-existing 标志会从本地状态发现凭据(例如,gh auth 令牌、Claude 配置文件)。

使用显式凭据创建提供方
openshell provider create --name my-openai --type openai \
  --credential OPENAI_API_KEY

单独使用 KEY 会从同名环境变量读取值,避免将密钥写入 shell 历史记录。仅当用户明确接受此类暴露时,才使用 KEY=VALUE。

其他凭据来源包括:适用于兼容配置文件的 --from-gcloud-adc,以及在网关或沙箱运行时解析所需凭据时使用的 --runtime-credentials。

静态提供方凭据仅适用于提供方配置文件声明的主机、端口和路径。当存在占位符但请求收到 credential_endpoint_mismatch 时,可使用 profile export 检查该范围。没有配置文件的静态提供方会默认拒绝请求,因为网关无法构造绑定。

当经过检查的请求收到 request_authority_mismatch 时,请比较其 HTTP authority 与 CONNECT 隧道端点。主机和有效端口必须匹配。对于连接到 api.example.com:8443 的隧道,请发送 Host: api.example.com:8443;Host: api.example.com 未包含非默认端口,因此会被拒绝。绝对形式的请求目标也必须使用相同的 authority。

除非启用了网关全局策略,否则基于配置文件的提供方始终会应用策略。静态凭据端点绑定仍会独立强制执行。

为提供方添加标签并进行筛选

创建提供方时,可通过可重复使用的 --label KEY=VALUE 标志添加标签。所有凭据来源均支持标签。列表筛选器要求每个以逗号分隔的键值对都匹配,并在分页前应用。

openshell provider create --name public-pypi --type pypi --label env=dev --label team=ml
openshell provider list --label-selector env=dev,team=ml
openshell provider list --all-workspaces --label-selector team=ml --output json
openshell provider get public-pypi

在本示例中,使用导入的配置文件(例如 pypi)。get 会显示标签; 结构化列表输出也包含标签。--all-workspaces 需要 Platform Admin 访问权限。传递下一个 --page-token 时,请保留筛选器和工作区范围。创建提供方后,无法更改或移除标签。

检查和管理提供方配置文件
openshell profile describe github
openshell profile export github --output yaml
openshell profile lint --file ./my-profile.yaml
openshell profile import --file ./my-profile.yaml
openshell profile lint --url https://example.com/profiles/my-profile.yaml
openshell profile import --url https://example.com/profiles/my-profile.yaml

--url 接受一个 HTTP 或 HTTPS YAML 或 JSON 配置文件。导入前,请检查其端点和 二进制授权。URL 路径必须以 .yaml、.yml 或 .json 结尾;下载大小上限为 1 MiB,超时时间为 15 秒。

创建提供方前,使用 profile describe 检查定义中的凭据元数据、端点、TLS 处理方式、MCP 访问设置、规则数量、二进制文件、来源和范围。在依赖显示的 L7 规则之前,请检查是否设置了 tls: skip,以及是否启用了未经检查凭据的选项。列表和描述命令支持表格、JSON 和 YAML 输出;使用结构化输出获取完整规则定义,使用 --workspace 指定工作区目录,或使用 --global 指定平台范围。准备可编辑的定义时,使用 profile export;使用 profile update <id> --file <file>,通过当前资源版本替换现有自定义配置文件;使用 profile delete <id>... 删除自定义配置文件。提供方实例仍通过 provider 管理。

现有脚本可继续使用 provider list-profiles 和 provider profile export/import/update/lint/delete。 这些命令共用顶层处理程序,并保留其参数、输出选项以及工作区/全局标志。编写新命令时,优先使用 profile。

列出、检查、更新、删除

使用 openshell sandbox provider status --help 以及 attach、detach 和 update 的帮助信息,查找已安装版本的等待选项。如果后续步骤依赖提供方变更生效,请添加 --wait。不添加此选项时,命令成功仅表示网关已保存变更。保存返回的 receipt_id,以便稍后检查同一项变更,并检查每个选定沙盒的结果。凭据刷新状态确认 OpenShell 已获取凭据;提供方状态确认沙盒已应用凭据、激活策略,并为新进程更新环境。如果状态为 superseded,请说明后续变更已取代此请求,并单独检查该变更。

如果 attach、detach 或 update 报告 CONFIG_OPERATION_STORAGE_UNCERTAIN,请说明变更可能已保存,但可能无法获取其就绪回执。不要盲目重试该变更操作。检查提供方和沙盒状态,并核实已保存的变更,然后再决定是否执行其他变更操作;此错误既不能证明操作已回滚,也不能证明已就绪。

openshell provider list
openshell provider list --output json
openshell provider get my-github
openshell provider update my-github --from-existing
openshell provider delete my-github

provider update 不接受 --type。它会更新现有提供方的凭据、配置或凭据有效期。

如果外部更新程序的工作负载必须保留原始环境引用,请使用设置了 stable_placeholder: true 的凭据配置,并确保网关和 supervisor 支持该模式。CLI 会在导入或更新此可选设置之前检查网关是否支持。默认值仍为 false,从而保留现有的按修订版本限定的行为和普通的旧版网关运行方式。保留 supervisor 签发的值;切勿自行生成占位符。supervisor 安装仅值更新后,保留的引用只会在其有效的主机、端口和路径绑定范围内解析为当前凭据。凭据替换、过期、绑定变更或已激活的分离操作,都会阻止旧授权继续解析。降级网关前,请移除此可选设置并激活该变更。有关生命周期约定及其与网关管理的刷新和 token_grant 的区别,请参阅提供方配置文档。

配置凭据刷新

仅当提供商配置文件和网关支持可刷新的凭据时,才使用刷新命令:

openshell provider refresh status my-provider
openshell provider refresh configure my-provider \
  --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-provider --credential-key ACCESS_TOKEN

对于机密刷新材料,优先使用 --secret-material-env KEY[=ENVVAR]。--material KEY=VALUE 用于非机密材料;--secret-material-key 会将提供的材料键标记为机密。

网关通过其活动凭据驱动程序存储机密刷新材料。 选择 Vault 后,刷新令牌、客户端密钥和私钥会与可注入的提供商凭据一同存储在 Vault 中;刷新状态仅包含不透明句柄。凭据后端读取或写入失败时,刷新会以 失败关闭的方式处理,而不会回退到内联存储。在 OpenShell 0.1.0 之前,网关 不会迁移旧版内联刷新材料,也不会在凭据后端之间移动机密。升级后请重新配置 受影响的授权;在更改后端之前,请确保原后端仍可用,并在此期间移除或重新配置 凭据。不要让混合版本的网关使用同一批刷新记录。

网关管理的刷新凭据使用身份稳定的工作负载句柄。常规自动刷新和 provider refresh rotate 会更新该句柄关联的访问令牌,因此长时间运行的 进程无需重启。从按修订版本划分的占位符升级时,必须重启正在运行的进程一次。 之后调用 provider refresh configure 是明确的重新授权边界:它会撤销先前的 句柄,持有该句柄的进程将以失败关闭的方式处理,直至重启。

配置了网关管理的刷新后,provider update --credential 无法替换或删除刷新 拥有的主要凭据或任何共同签发的输出。要恢复手动管理这些密钥,请使用 provider refresh rotate、重新配置刷新,或先删除刷新。其他不相关的提供商 字段仍可更新。

OAuth 刷新失败时,请查看 provider refresh status 输出中的 RECOVERY 和 FAILURE_CODE 列;不要根据 HTTP 状态推断补救措施,也不要解析 LAST_ERROR。retry 表示工作线程会再次尝试;reauthorize 表示用户必须获取 新的 OAuth 授权,并运行 provider refresh configure;fix_configuration 表示操作员必须修复 OAuth 客户端、作用域或管理员策略;investigate 可能表示 发行方响应无法识别,或签发过程被中断且结果不确定。网关会暂停 reauthorize 记录,直到手动轮换或重新配置。它会每小时重试 fix_configuration 记录,以便外部修复配置后能够恢复,同时避免令牌端点流量 激增。现有访问凭据仅在其记录的到期时间之前可用。

refresh_in_progress 和 refresh_committing 可能表示操作仍在进行。将其视为 失败之前,请检查网关运行状况和刷新状态;并发刷新请求会等待当前签发操作完成。 如果网关中断后遗留了其中任一标记,且轮换报告先前的签发结果不确定,网关将 不会自动重用该授权。请调查发行方状态,然后使用有效授权运行 provider refresh configure。如果先前的刷新令牌可能已被使用,请先获取新的 OAuth 授权。不要直接清除标记,也不要反复轮换;重新配置会撤销旧的工作负载 句柄,因此请重启持有这些句柄的进程。


工作流 3:沙盒生命周期

使用选项创建
openshell sandbox create \
  --name my-sandbox \
  --provider my-github \
  --provider my-claude \
  --policy ./my-policy.yaml \
  --label team=agents \
  -- claude

关键标志:

  • --provider:附加已配置的凭据提供方,用于 API 密钥、令牌和其他机密(可重复指定)
  • --policy:自定义策略 YAML(否则使用内置默认值或 OPENSHELL_SANDBOX_POLICY 环境变量)
  • --gpu [COUNT]:请求驱动程序的默认 GPU 选择,或指定 GPU 数量
  • --cpu、--memory:设置每个沙箱的计算资源规格。Docker/Podman 会应用限制;Kubernetes 会应用相应的请求和限制。
  • --driver-config-json:传入实验性的驱动程序专属沙箱配置
  • --template NAME:基于具名沙箱工作负载模板创建。与 --from、--gpu、--cpu、--memory、--env、--env-from 和 --driver-config-json 等内联工作负载标志冲突。
  • --label KEY=VALUE:添加标签以供后续选择(可重复指定)
  • --annotation KEY=VALUE:添加非机密元数据,例如文件路径(可重复指定)
  • --env KEY=VALUE:设置非机密沙箱环境变量(可重复指定);凭据请使用 --provider
  • --env-from KEY[=ENVVAR]:从 CLI 进程环境中读取沙箱环境变量值,不将其值放入参数中;如需避免工作负载接触凭据,请使用 --provider
  • --tty:为规范主进程分配一个保留的 PTY
  • --restart-policy never|on-failure|always:选择由网关管理的主进程重启行为;默认值为 never
  • --approval-mode manual|auto:控制对由 Agent 编写的策略提案的处理方式;默认值为 manual
  • --upload <PATH>[:<DEST>]:将本地文件上传到容器工作目录或指定目标路径
  • --no-git-ignore:禁用上传时的 .gitignore 过滤
  • --no-keep:主进程输出和退出结果排空后删除沙箱
  • --detach:启动规范主进程,但不附加到该进程
  • --forward [BIND_ADDRESS:]PORT:转发本地端口并保持沙箱运行
  • --editor vscode|cursor:创建后打开远程编辑器并保持沙箱运行

如果驱动程序在创建验证期间拒绝前台附加,请使用 --detach。

--detach 不会增加附加宽限期。规范进程退出后, 系统会立即报告其终止阶段。前台创建会声明一个预期的主进程 SSH 附加;该连接自然关闭后,清理工作才会完成。使用 --detach --no-keep 时,网关负责管理分离进程的生命周期,并在 终止报告完成后删除临时沙箱。

不要将 --upload 与末尾的主命令一起使用。 上传目前会在规范进程启动后完成;请创建临时沙箱并使用 sandbox exec,或将文件构建到镜像中。

当多个沙箱需要共享镜像、环境、资源规格或驱动程序专属配置时, 请基于可复用的工作负载模板创建:

openshell sandbox template create gpu-kata \
  --image registry.example.com/agents/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

默认情况下,驱动程序配置处于禁用状态。以下模板示例和一次性 sandbox create --driver-config-json 示例都要求管理员为所选驱动程序设置 allow_driver_config = true。这不会免除资源准入要求:外部附加 需要在实际资源上设置由管理员控制的批准标签,而不是沙箱标签。GPU 设备附加 暂时不需要标签;公开的 --gpu 标志无需启用驱动程序配置。更改准入设置前, 请参阅已发布的网关配置参考;不要建议通过禁用准入来绕过 拒绝。只有在需要复用驱动程序配置时,才将其放入模板中。

管理沙箱工作负载模板
openshell sandbox template create gpu-kata \
  --image registry.example.com/agents/python:latest \
  --cpu 2 \
  --memory 4Gi \
  --gpu 1 \
  --label team=runtime \
  --env FEATURE_FLAG=on
openshell sandbox template list
openshell sandbox template list --label-selector team=runtime
openshell sandbox template list --all-workspaces --output json
openshell sandbox template get gpu-kata
openshell sandbox template delete gpu-kata

模板的 --image 接受 OCI 镜像引用。如果省略,网关会在根据模板创建沙箱时 应用默认沙箱镜像。创建时的策略、提供方、标签、上传、端口转发、 编辑器启动和初始命令仍通过 sandbox create 设置。

列出并检查沙盒
openshell sandbox list
openshell sandbox list --selector team=agents --output json
openshell sandbox get my-sandbox

大多数可选沙盒名称的命令都会使用上次使用的沙盒。在自动化中,请传入明确的名称。

连接到正在运行的沙盒
openshell sandbox connect my-sandbox
openshell sandbox connect my-sandbox --editor vscode

连接到沙盒中现有的规范主进程。断开连接不会终止该进程;重新连接时会指向同一个进程实例,并重放最近的输出。如果已建立的 SSH 传输中断(例如,笔记本电脑休眠后又唤醒),CLI 会在最长 60 秒内重试暂时性故障,并重新连接到同一个进程。要启动新的 shell,请使用 sandbox exec --tty -- /bin/bash -l。按 Ctrl-D 或 Ctrl-P,然后按 Ctrl-Q,即可断开连接而不终止主进程。OpenSSH 的 ~. 转义序列看起来像传输中断,因此会启动自动恢复;重新连接后,按 Ctrl-D 或 Ctrl-P,然后按 Ctrl-Q 退出,或者在两次重试之间按 Ctrl-C 取消恢复。当你拥有 stdin 时,Ctrl-C 会中断前台进程。在只读连接中,按 Ctrl-C 或 Ctrl-D 会退出查看器,并让主进程和其他连接继续运行。使用以下配置设置 VS Code Remote-SSH:

openshell sandbox ssh-config my-sandbox >> ~/.ssh/config

如果可写连接发现另一个连接正占用 stdin,就会报告 attached read-only; retry input after the owner disconnects。自动恢复可能在重新连接时遇到这种情况,因为监督程序尚未关闭失效的连接。监督程序会在连接最后一次收到字节 60 秒后关闭该连接;如果中继缓冲了数据,关闭时间可能晚于网络中断后的 60 秒。旧连接的所有者断开连接或超时后,再发送你接下来想输入的内容。如果 stdin 空闲,连接会打印 input enabled 并将该输入转发给进程,因此不要按 Enter 试探,也不要发送 y 之类的提示回答。如果没有任何输出,说明旧连接仍占用 stdin。在连接处于只读状态时发送的输入不会到达进程,因此之后需要重新发送。按 Ctrl-C、Ctrl-D,以及按 Ctrl-P 后再按 Ctrl-Q,仍会退出只读连接,而不会启用输入;如果需要用 Ctrl-C 中断进程,请先启用输入。恢复过程不会从正常运行的所有者手中接管 stdin,显式设为只读的连接也会始终保持只读。

如果 connect 报告 canonical main process already finished,请使用 sandbox get 检查结果。处于 Completed 或 Error 状态的待处理前台连接仍可获取保留的输出;是否可连接并不只由阶段状态决定。在 on-failure 策略下,主进程以非零状态退出,或在 always 策略下主进程以任何状态退出,都会使沙盒在退避等待和资源替换期间进入 Starting 状态。新的监督程序会话变为 Ready 后,连接和执行命令会恢复。显式执行 sandbox stop 会取消待处理的重启。

上传和下载文件
# Upload local files to the sandbox working directory
openshell sandbox upload my-sandbox ./src

# Download a path relative to the sandbox working directory
openshell sandbox download my-sandbox output ./local-output

上传使用有界流式传输,并会等待沙盒消耗输入;4 MiB 的进程输入预算并非上传总大小上限。请同时升级 CLI 和沙盒使用的 supervisor 运行时。较旧的 supervisor 会在发送文件数据之前拒绝上传协议。失败或取消的上传可能会在目标位置留下不完整的文件;重试前请检查目标位置,或删除残留文件。

默认情况下,在 Git 工作树中上传会遵循 .gitignore,如果 Git 筛选失败或未选中任何文件,则会停止。确认位于 Git 工作树之外的源文件会在不进行筛选的情况下上传,并会警告未应用 .gitignore 规则。必须能够使用 Git,才能判断是否适用筛选;损坏或无法访问的仓库会导致上传停止。如需明确进行未筛选上传,请添加 --no-git-ignore。sandbox create --upload 也适用此规则。

sandbox create --upload 会在配置资源前于本地检查每个上传项;如果有任何上传项被拒绝,则不会创建沙盒。如果配置资源后传输失败,沙盒仍会运行,且此前的上传可能已完成。请针对该沙盒重试 sandbox upload,或使用 sandbox delete 将其删除。

上传会保留符号链接,包括悬空符号链接,而不会跟随链接访问目标。符号链接源会跳过 Git 筛选,以便将链接本身打包存档。

省略上传目标时,CLI 会查找远程工作目录。上传具名目录时,会将其合并到同名的现有目录中,覆盖匹配的条目,但不会删除无关条目。下载路径可以是相对于该工作目录的路径,也可以是该目录内的绝对路径。

执行非交互式命令
openshell sandbox exec my-sandbox --workdir /workspace -- ls -la
openshell sandbox exec --name my-sandbox --env MODE=test -- cargo test

沙盒必须是位置参数名称或 --name,不能同时使用两者;省略时会使用上次使用的沙盒。必须使用 --,其后的所有内容都会作为远程命令,因此请将 --tty 等选项放在它之前。

sandbox exec 会启动一个独立的同级进程,并流式传输输出。标准输出和标准错误流排空后,如果输出传送成功,则会返回远程命令的退出代码。如果输出传送失败,则会返回退出代码 74,即使命令已成功退出也是如此。命令退出后,如果某个后代进程在超过 30 秒的时间内仍保持继承的输出管道打开,就会触发此失败。重试有副作用的工作之前,请先确认命令是否已运行。请使用 sandbox connect 连接到规范的主进程。 --env 仅用于非机密值。请通过提供程序将凭据附加到沙盒,而不要将 API 密钥、令牌或其他机密传递给 sandbox exec。

更改已附加的提供程序
openshell sandbox provider list my-sandbox
openshell sandbox provider list my-sandbox --output json
openshell sandbox provider attach my-sandbox my-github --wait --timeout 30
openshell sandbox provider status my-sandbox my-github --output json
openshell sandbox provider detach my-sandbox my-github --wait --timeout 30

结构化的附加信息输出包含提供程序名称、类型,以及已排序的凭据和配置键名称。它绝不会包含凭据、句柄或配置值。

查看日志
# Recent logs
openshell logs my-sandbox

# Stream live logs
openshell logs my-sandbox --tail

# Filter by source and level
openshell logs my-sandbox --tail --source sandbox --level warn

# Logs from the last 5 minutes
openshell logs my-sandbox --since 5m
删除沙盒
openshell sandbox delete my-sandbox
openshell sandbox delete sandbox-1 sandbox-2 sandbox-3   # Multiple at once
openshell sandbox delete --all

deletion accepted 表示清理仍在进行中。请检查沙盒,直至其消失,再确认删除已完成。已不存在的沙盒也会视为成功;工作区缺失和授权失败仍会报错。如果其他进程可能已重新创建同名沙盒,请勿盲目按名称重试。

停止和启动沙箱

使用 stop 可停止计算,同时保留沙箱及其持久化工作区:

openshell sandbox stop [name]
openshell sandbox start [name]

这两个命令默认针对最近使用的沙箱。Stop 会停止后台转发,并等待状态变为 Stopped;start 会等待状态变为 Ready。沙箱处于停止或已完成状态时,无法连接、执行命令、传输文件、进行转发或访问已公开的服务。启动保留的 Completed 或 Error/MainProcessFailed 沙箱时,会启动一个全新的规范主实例,并使前一个运行时代的 SSH 会话失效。删除才会移除保留状态。

沙箱的 SSH 主机身份在 stop/start 和运行时重启后保持不变。API 客户端可以从沙箱资源或 SSH 会话响应中读取其公钥指纹,并将其绑定到沙箱 ID。即使使用相同名称重新创建已删除的沙箱,也会生成不同的身份。有关验证行为和发行版兼容性,请参阅沙箱 SSH 文档。

如果在支持重启已停止沙箱的后端上遇到基础设施 Error,请修复报告的原因,运行 sandbox stop 并等待其成功,然后运行 sandbox start。这会保留沙箱和持久化工作区,但无法恢复已删除的资源或存储。如果发生配置超时,请等待清理完成,然后直接运行 sandbox start。

暂停和恢复沙箱

在计算驱动程序和隔离后端支持此功能的网关上,suspend 会冻结处于 Ready 状态的沙箱,并保留其内存状态:

openshell sandbox suspend [name]
openshell sandbox resume [name]

Suspend 会等待状态变为 Suspended,然后停止后台转发。如果 suspend 被拒绝,转发会继续运行。Resume 会在新的运行时代中恢复状态,并等待状态变为 Ready。不支持此功能的网关会以 FAILED_PRECONDITION 拒绝 suspend。如果无法恢复保留的状态,resume 会失败;如需明确进行全新启动,请使用 sandbox start。对已暂停的沙箱运行 sandbox start、sandbox stop 和 sandbox delete 会丢弃保留的内存状态。


工作流 4:策略迭代循环

这是最重要的多步骤工作流。它建立了紧密的反馈循环,可根据观察到的活动不断完善沙箱策略。

核心概念:策略包含静态字段(激活后不可更改:filesystem_policy、landlock、process)和两个动态字段:network_policies 与 network_middlewares。如果所选计算驱动程序支持实时策略更新,则无需重新创建沙箱即可更新这两个动态字段。不使用标准 supervisor 的驱动程序会通过沙箱配置 API 获取修订版本,并报告是否已加载这些版本。

如果启动时报告 ConfigurationInvalid,请检查 openshell sandbox get, 并通过网关修复完整的策略或提供程序集合。沙箱首次激活时,工作负载尚未启动, 因此在这次初始修复期间也可以替换静态字段。此前已激活的沙箱在等待重启准入或 重启准入被拒绝期间,会保留静态字段限制。 在网关的 300 秒修复窗口到期之前,验证成功即可原地完成启动。已存储配置的有效变更 及其首次加载失败会重置此窗口;重复失败不会重置。发生 ProvisioningTimedOut 后,请检查保留的记录和清理状态,修复配置,并在清理完成后 显式运行一次 sandbox start。CLI 等待超时与此网关期限是分开的。请遵循已发布的 策略修复指南, 并通过已安装的 CLI 帮助确认当前的替换/分离语法。

未指定 protocol 的端点会保留显式代理行为。显式设置 protocol: tcp 表示请求使用策略 DNS 和透明 TCP,目前要求使用 Docker 或 Podman 运行时;不支持的运行时会在启动 工作负载前拒绝该策略,而不会仅激活网络契约的一部分。

Create sandbox with initial policy
        │
        ▼
   Monitor logs ◄──────────────────┐
        │                          │
        ▼                          │
  Observe denied actions           │
        │                          │
        ▼                          │
  Pull current policy              │
        │                          │
        ▼                          │
  Modify policy YAML               │
  (use generate-sandbox-policy)    │
        │                          │
        ▼                          │
  Push updated policy              │
        │                          │
        ▼                          │
  Verify reload succeeded ─────────┘
步骤 1:使用初始策略创建沙箱
openshell sandbox create --name dev --from registry.example.com/your-org/claude-agent:latest --policy ./initial-policy.yaml -- claude

默认情况下,沙箱会持续运行,以便进行迭代。只有在希望沙箱在初始会话后自动删除时,才添加 --no-keep。

步骤 2:监控日志中的拒绝操作

在单独的终端中监控,或由 Agent 监控:

openshell logs dev --tail --source sandbox

查找 DENIED 日志行。NET:OPEN [MED] DENIED 表示连接被阻止,HTTP:<METHOD> [MED] DENIED 表示请求被阻止。策略事件是 INFO 级别的日志记录,因此不要添加 --level warn。日志包含:

  • 目标主机和端口(被阻止的对象)
  • 二进制文件路径(尝试连接的进程)
  • 拒绝原因(被阻止的原因)
步骤 3:提取当前策略
set -o pipefail
openshell policy get dev --base | sed '1,/^---$/d' > current-policy.yaml

--base 返回不含提供程序组合条目的可编辑策略;OpenShell 会单独组合已附加的提供程序规则。命令会打印修订详情、一行 ---,然后打印策略 YAML。sed 表达式只保留 YAML,因为 policy set 无法解析修订详情。--full 仅用于检查生效策略,不要将其作为 policy set 的输入。

第 4 步:修改策略

编辑 current-policy.yaml,允许被阻止的操作。**编写策略内容时,请委派给 generate-sandbox-policy 技能。**该技能负责处理:

  • 网络端点规则结构
  • L4 与 REST、WebSocket、JSON-RPC 和 MCP L7 策略决策
  • 访问预设(read-only、read-write、full)
  • TLS 终止配置
  • 强制执行模式(audit 与 enforce)
  • 二进制匹配模式
  • 有序的 network_middlewares、主机选择、HTTP 请求/响应和 WebSocket 绑定,以及 fail_open 或 fail_closed 行为

当所选计算驱动程序支持实时策略更新时,可在运行时修改 network_policies 和 network_middlewares。使用 --wait 验证活动运行时已加载该修订版本;不要仅凭网关接受更新就推断策略已生效。如果需要更改 filesystem_policy、landlock 或 process,则必须重新创建沙箱。openshell/regex 等内置中间件无需在网关注册。由操作员运行的中间件必须已在 [[openshell.supervisor.middleware]] 下注册;更改此静态注册需要重启网关。

如果实现声明了相应绑定,中间件可以检查 HTTP 请求、HTTP 响应或客户端 WebSocket 文本消息。内置的 openshell/regex 支持请求正文和客户端 WebSocket 文本消息。使用 generate-sandbox-policy 技能选择附加项和失败策略,并使用 debug-openshell-cluster 调查中间件故障。

第 5 步:推送更新后的策略
openshell policy set dev --policy current-policy.yaml --wait

网关会验证完整的有效候选策略(包括已附加的提供方配置文件策略),之后才会存储直接更新、增量合并、已批准的提案、提供方附加项,或影响已附加沙箱的配置文件更新。若遇到歧义错误,将返回 FAILED_PRECONDITION;被拒绝的候选策略不会创建策略修订版本,也不会部分更新受影响的沙箱。如果 credential_signing 未附加凭据边界覆盖该端点的 AWS 配置文件,或者显式绑定到了没有端点的 AWS 配置文件,也会采用相同的失败关闭响应。修正冲突的端点选择器或凭据来源后重新提交。

--wait 标志会阻塞,直到沙箱确认策略已加载(每秒轮询一次)。退出代码:

  • 0:策略已成功加载
  • 1:策略加载失败
  • 124:超时(默认 60 秒)
第 6 步:验证更新
openshell policy list dev

检查最新修订版本的状态是否为 loaded。如果状态为 failed,请查看错误列中的详细信息。

第 7 步:重复

返回第 2 步。继续监控日志并完善策略,直到允许所有必需操作,且不存在不必要的权限。

策略修订历史记录

查看所有修订版本,了解策略的演变过程:

openshell policy list dev --page-size 50
openshell policy list dev --output json

获取特定的历史修订版本:

openshell policy get dev --rev 3 --full

网关全局策略命令使用 --global,除非指定 --yes,否则需要确认:

openshell policy get --global --full
openshell policy set --global --policy ./global-policy.yaml
openshell policy list --global
openshell policy delete --global

交互操作时避免使用 --yes。全局策略会锁定网关上所有沙箱的策略控制。

审核 Agent 编写的规则提案

使用 --approval-mode manual 创建的沙箱会将每个提案放入审核收件箱。auto 只会批准有效策略候选方案中证明器差异为空的方案;发现的问题仍需审核。CLI 会将批准操作绑定到候选方案当前的审核令牌。如果实时策略、提供方或凭据输入发生变化,批准操作会将该区块保留为待处理状态,并刷新候选方案,因此需要重新审核。

openshell rule get dev --status pending
openshell rule approve dev --chunk-id <chunk-id>
openshell rule reject dev --chunk-id <chunk-id> --reason "too broad"
openshell rule history dev

批准前,请审核提议的范围、候选方案哈希、证明器发现的问题和应用错误。将 rule approve-all --include-security-flagged 视为高风险批量操作。

在网关能够分析当前策略和提议策略之前,validation unavailable 会阻止批准。它并不表示已接受风险。


工作流 5:BYOC(自带容器)

构建自定义容器镜像,并将其作为沙箱运行。

从预构建镜像创建沙箱
docker build -t my-app:latest .
openshell sandbox create --from my-app:latest --name my-app

--from 标志接受明确的 OCI 镜像引用,例如 myregistry.com/img:tag。它不会展开目录别名。先使用与本地网关相同的容器引擎构建本地 Dockerfile,然后传入镜像标签。

对于 Docker 网关,使用 docker build -t my-app:latest。对于 Podman 网关,使用 podman build -t localhost/my-app:latest,并将 localhost/my-app:latest 传给 --from。对于远程网关,将镜像推送到网关可访问的注册表。

对于 Docker 和 Podman 网关,自定义镜像应声明一个非 root 的 OCI USER。未声明该值的镜像将以数字 UID 和 GID 1000 运行。每个显式设置的 process.run_as_user 或 process.run_as_group 策略 字段都会独立生效;未设置的字段则回退到镜像声明的值。 显式数字字段可以使用 1 到 4294967294 之间的任意 UID/GID;0 表示 root,4294967295 是无效身份哨兵值。 请提醒用户,较低的 ID 可能会继承匹配账户、镜像 文件、挂载卷或设备的权限。

转发端口
# Foreground (blocks)
openshell forward start 8080 my-app

# Background (returns immediately)
openshell forward start 8080 my-app -d

现在可以通过 localhost:8080 访问该服务。 CLI 端口转发不受用户 SSH 配置中的 SSH 多路复用和自动后台运行设置影响。只有后台转发会由 forward list 跟踪并由 forward stop 管理;前台转发会在命令退出时结束。

管理或迭代沙箱:

openshell forward list
openshell forward stop 8080 my-app
openshell sandbox delete my-app
openshell sandbox create --from my-app:latest --name my-app --forward 8080

自动化需要跟踪的转发元数据和经过验证的进程状态时,请使用结构化输出:

openshell forward list --output json

每条记录都包含 workspace、sandbox、bind_address、port、pid 和 alive。alive 布尔值会验证工作区范围内的沙箱和跟踪的进程身份;它不会探测转发的套接字。

在一条命令中创建并转发:

openshell sandbox create --from my-app:latest --forward 8080 -- ./start-server.sh

--forward 标志会在命令运行前启动后台端口转发。

工作流 6:Agent 辅助的沙箱会话

支持用户在沙箱中工作,同时由 Agent 并行监控活动并调整策略。

创建沙箱并使其保持运行:

openshell sandbox create \
  --name work-session \
  --provider github \
  --provider claude \
  --policy ./dev-policy.yaml

告知用户在另一个 Shell 中连接:

openshell sandbox connect work-session
openshell sandbox connect work-session --editor vscode

监控被拒绝的活动:

openshell logs work-session --tail --source sandbox

出现被拒绝的操作时:

  1. 对于新增网络配置,优先使用增量更新: 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 --rule-name allow_api_github_com_443 --binary /usr/bin/gh --add-allow 'api.github.com:443:POST:/repos/*/issues' --wait

    规则会授权其中列出的每个二进制文件访问其中列出的每个端点,因此,更新现有规则以添加二进制文件或端点时,必须声明该规则的完整二进制文件和端点范围。网关会拒绝授予某个二进制文件访问某个端点的权限、但更新中未要求此权限的操作,并在错误中指出仍缺少的二进制文件。若要仅授予某个二进制文件访问规则中部分端点的权限,请使用其专属的 --rule-name 提交范围较窄的授权;该授权会保留在自己的规则中,不会并入范围更广的规则。

    --add-allow 和 --add-deny 必须与 --rule-name 及完整的二进制文件范围一起使用,后者通过重复指定 --binary 或显式指定 --any-binary 来声明。操作中必须声明端点的每个端口,例如 api.example.com:443,8443:POST:/admin。使用 --endpoint-path 可在所选规则中区分端点;显式指定空路径表示选择未设置路径选择器的端点。网关会在持久化之前拒绝范围缺失或不匹配的操作。检查当前策略并确认预期受影响的范围;不要仅为避免被拒绝而自动从当前策略填充声明。

  2. 对于大范围网络变更,或 policy update 无法表达的设置,使用完整 YAML 替换,包括原本需要重新声明大量现有范围的任何变更。文件系统、Landlock 和进程变更仍需重新创建沙箱: openshell policy get work-session --base | sed '1,/^---$/d' > policy.yaml 使用 generate-sandbox-policy 技能修改策略。 openshell policy set work-session --policy policy.yaml --wait

  3. 使用 openshell policy list work-session 验证。

用户无需断开连接。策略更新会热重载;--wait 会阻塞,直到沙箱确认该修订或超时。会话结束后删除沙箱:

openshell sandbox delete work-session

工作流 7:使用已附加提供方进行推理

推理采用与其他需要凭据的服务相同的提供方附加工作流。导入或选择一个允许访问提供方原生端点的配置文件,创建提供方,并仅将其附加到需要它的沙箱:

openshell provider profile import -f ./inference-provider.yaml
openshell provider create --name model-provider --type <profile-id> --credential <KEY>
openshell sandbox provider attach work-session model-provider --wait --timeout 30
openshell sandbox exec work-session -- <client-command>

应用负责管理原生基础 URL、模型、请求格式和超时。提供方就绪后启动新进程,使其继承已安装的提供方环境。若发生端点、策略、凭据绑定或迁移故障,请使用 debug-inference 技能。

对于常规的静态提供方更新,请等待更新完成,然后启动新的客户端进程以获取新引用。不要声称就绪状态会更新现有进程的环境或重新指向其旧引用。确认分离后,会撤销保留的引用,并将其从后续进程的环境中移除。

工作流 8:网关管理

列出、切换和验证网关:

openshell gateway select
openshell gateway list --output json
openshell gateway select production
openshell gateway info --name production
openshell status

openshell gateway info 会报告计算驱动程序、凭据驱动程序、网关拦截器和监督器中间件的不可变启动快照。诊断扩展版本不匹配问题时,请参考每个条目的协议版本、实现版本、支持的功能和网关要求;实现版本不能标识底层的 Docker、Kubernetes 或凭据后端。

注册或移除网关:

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:// 注册默认使用边缘身份验证。使用 gateway login 和 gateway logout 刷新或清除已存储的身份验证信息。对于 OIDC 网关,请提供 --oidc-issuer,并在需要时提供 --oidc-client-id、--oidc-audience 和 --oidc-scopes。如果 OIDC 自动刷新失败,受保护的命令会在发送 RPC 前停止,并提示用户运行 openshell gateway login <name>;openshell status 仍会分别报告网关可访问性和身份验证状态。对于远程 mTLS 网关,请使用 --remote USER@HOST 或 ssh:// 端点。

对于一次性自动化,--gateway-endpoint URL 可直接连接,不使用已存储的元数据。仅对明确可信的开发端点使用 --gateway-insecure。

检查 Kubernetes 部署:

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

对于 Docker、Podman 和由虚拟机提供支持的网关,请直接检查网关进程或容器日志以及所选运行时。

工作流 9:设置管理

管理沙盒级或网关全局设置:

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 ocsf_json_enabled --value true

# OCSF schema version downgrade for SIEM compatibility (allowed: "1.1", "1.3")
openshell settings set --global --key ocsf_schema_version --value "1.1"

启用 ocsf_json_enabled 后,监督器的 stderr 中会在简写日志旁添加精简的 OCSF-JSON 记录;如果文件存储可用,也会将这些记录写入其 JSONL 文件。通过监督器的平台日志(docker logs、podman logs 或 kubectl logs)收集这些记录;openshell logs 仍用于查看简写日志。请在时间戳后匹配 OCSF-JSON 标记,并将其余部分解析为 JSON。有关传输和保留限制,请参阅已发布的 OCSF JSON 导出指南。

全局更改需要确认。仅在经过审查的自动化中使用 --yes。

policy_validation_failure_mode 是网关启动配置,并非可通过 openshell settings 修改的键。请在 gateway.toml 的 [openshell.gateway] 下设置该项,然后重启网关。安全优先的默认值为 fail_closed;retain_last_valid 则是在可用性方面作出的明确权衡。OCSF 配置事件会说明运行时验证失败后,是否仍在使用上一代配置。

工作流 10:服务访问

本地访问使用 forward,网关管理的 HTTP 端点使用 service:

# 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

# Create a sandbox with its unnamed HTTP or WebSocket service exposed.
openshell sandbox create \
  --name my-app \
  --from my-app:latest \
  --expose 8080 \
  --expose-authorization-mode bearer-passthrough \
  --detach \
  -- ./start-server.sh

# Expose and manage an HTTP service through the gateway.
openshell service expose my-app 8080 web \
  --authorization-mode bearer-passthrough
openshell service list my-app
openshell service list my-app --output json
openshell service get my-app web
openshell service delete my-app web

使用 openshell service list --all-workspaces 查看跨工作区的平台管理员视图。沙箱名称与 --all-workspaces 不能同时使用。

sandbox create --expose PORT 会在创建请求中注册未命名端点,并让沙箱保持运行。添加 --output json 可用于自动化;结果包含一个 service_urls 映射,其中空键对应未命名端点。创建后,使用 openshell service expose 添加或更新已命名端点。

默认情况下,已公开的服务会剥离 Authorization。只有当沙箱内的应用会对自己的客户端进行身份验证时,才选择 bearer-passthrough 模式。此模式接受没有 Authorization 标头,或恰好包含一个非空 Bearer 凭证的情况,并原样转发该值。在联系应用之前,它会拒绝重复、格式错误或非 Bearer 的授权信息。应用仍负责验证令牌,且原始令牌会传递到沙箱进程,因此切勿记录该令牌。服务路由会绕过控制平面 RPC 授权,但仍使用网关现有的监听器、域名路由和 TLS 配置,包括任何客户端证书要求。完整的安全约定请参阅已发布的沙箱服务文档。

除非用户明确需要可供局域网访问的本地服务,否则优先绑定到 loopback 地址。


通过 --help 自主学习

遇到本技能未涵盖的命令或选项时:

  1. 先了解概况:运行 openshell --help 查看所有命令组。
  2. 缩小范围:运行 openshell <group> --help 查看子命令(例如,openshell sandbox --help)。
  3. 查看详情:运行 openshell <group> <cmd> --help 查看标志和用法(例如,openshell sandbox create --help)。

CLI 帮助始终具有权威性。如果帮助输出与本技能冲突,请以帮助输出为准——CLI 可能已在编写本技能后更新。

示例:探索不熟悉的命令
$ openshell sandbox --help
# 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

配套技能

技能适用场景
generate-sandbox-policy创建或修改策略 YAML 内容(网络规则、L7 检查、访问预设、端点配置和网络中间件)
debug-openshell-cluster诊断网关部署、运行时或健康状态故障
debug-inference诊断附加的提供方推理、原生端点、基于主机的模型,以及从已弃用的托管端点迁移

评论

支持 Markdown