User Story
As an OpenShell user launching a network service in a sandbox, I want to expose that service as part of sandbox creation, so that clients can connect without a separate post-create command or local SSH port-forwarding process.
Problem Statement
openshell sandbox create cannot currently declare a service endpoint. Users must wait for the sandbox to become ready and then run a separate service-exposure operation, or use local port forwarding. SDK callers likewise cannot express service exposure in their sandbox create request.
This makes service-oriented workloads harder to automate and creates a race between sandbox readiness and endpoint registration. It also complicates examples such as launching a Codex app server in an OpenShell sandbox and connecting a local Codex client to it.
Impact / Why This Matters
The current multi-step workflow requires extra lifecycle coordination, additional error handling, and knowledge of a second API. Local port forwarding also depends on a long-running client-side process and is not suitable when the gateway's routed service endpoint is the desired access path.
A create-time exposure declaration makes service workloads reproducible across the CLI and SDKs, eliminates avoidable orchestration, and gives users one stable endpoint workflow.
Proposed Design
Allow users to request one or more sandbox service exposures during sandbox creation.
The CLI should support an unnamed exposure with a workflow such as:
openshell sandbox create \
--name codex-app-server \
--expose 4500 \
-- codex app-server --listen ws://0.0.0.0:4500
After the sandbox reaches Ready, the CLI should print the routed service URL. Requesting an exposure should keep the sandbox alive after its main command starts and should be incompatible with options that require immediate sandbox cleanup.
The public sandbox create API and the Rust, Python, TypeScript, and Go SDK create options should accept service exposure declarations containing a target port and an optional service name. Named exposures should use the same naming and routing behavior as the existing service-exposure command.
The routed service boundary should preserve the existing behavior of consuming gateway authentication and not forwarding the gateway Authorization header to the sandbox application. Application-level authentication should use a distinct credential mechanism.
Add an example under examples/ that runs the Codex app server inside an OpenShell sandbox and shows how a local Codex client connects through the exposed WebSocket URL.
Acceptance Criteria
Alternatives Considered
Continue requiring openshell sandbox service expose after creation. This preserves the existing API but forces every caller to coordinate readiness and perform a second mutation.
Use openshell sandbox create --forward exclusively. Port forwarding remains useful for local-only access, but it requires a persistent client-side forwarding process and does not provide a gateway-routed service endpoint.
Forward the gateway Authorization header to the workload. This would conflate gateway authentication with application authentication and disclose a gateway credential to sandbox code, so the service router should continue stripping it.
Agent Investigation
The existing gateway service router already supports named and unnamed ServiceEndpoint records and WebSocket upgrades. The create path can reuse the same exposure validation and endpoint persistence behavior. The maintained SDK surfaces are Rust, Python, TypeScript, and Go.
User Story
As an OpenShell user launching a network service in a sandbox, I want to expose that service as part of sandbox creation, so that clients can connect without a separate post-create command or local SSH port-forwarding process.
Problem Statement
openshell sandbox createcannot currently declare a service endpoint. Users must wait for the sandbox to become ready and then run a separate service-exposure operation, or use local port forwarding. SDK callers likewise cannot express service exposure in their sandbox create request.This makes service-oriented workloads harder to automate and creates a race between sandbox readiness and endpoint registration. It also complicates examples such as launching a Codex app server in an OpenShell sandbox and connecting a local Codex client to it.
Impact / Why This Matters
The current multi-step workflow requires extra lifecycle coordination, additional error handling, and knowledge of a second API. Local port forwarding also depends on a long-running client-side process and is not suitable when the gateway's routed service endpoint is the desired access path.
A create-time exposure declaration makes service workloads reproducible across the CLI and SDKs, eliminates avoidable orchestration, and gives users one stable endpoint workflow.
Proposed Design
Allow users to request one or more sandbox service exposures during sandbox creation.
The CLI should support an unnamed exposure with a workflow such as:
After the sandbox reaches
Ready, the CLI should print the routed service URL. Requesting an exposure should keep the sandbox alive after its main command starts and should be incompatible with options that require immediate sandbox cleanup.The public sandbox create API and the Rust, Python, TypeScript, and Go SDK create options should accept service exposure declarations containing a target port and an optional service name. Named exposures should use the same naming and routing behavior as the existing service-exposure command.
The routed service boundary should preserve the existing behavior of consuming gateway authentication and not forwarding the gateway
Authorizationheader to the sandbox application. Application-level authentication should use a distinct credential mechanism.Add an example under
examples/that runs the Codex app server inside an OpenShell sandbox and shows how a local Codex client connects through the exposed WebSocket URL.Acceptance Criteria
openshell sandbox create --expose <PORT>requests an unnamed routed service endpoint as part of sandbox creation.Ready.examples/workflow launches a Codex app server in a sandbox and connects a local Codex client through the routed WebSocket endpoint.Alternatives Considered
Continue requiring
openshell sandbox service exposeafter creation. This preserves the existing API but forces every caller to coordinate readiness and perform a second mutation.Use
openshell sandbox create --forwardexclusively. Port forwarding remains useful for local-only access, but it requires a persistent client-side forwarding process and does not provide a gateway-routed service endpoint.Forward the gateway
Authorizationheader to the workload. This would conflate gateway authentication with application authentication and disclose a gateway credential to sandbox code, so the service router should continue stripping it.Agent Investigation
The existing gateway service router already supports named and unnamed
ServiceEndpointrecords and WebSocket upgrades. The create path can reuse the same exposure validation and endpoint persistence behavior. The maintained SDK surfaces are Rust, Python, TypeScript, and Go.