nodus.sandbox
View MarkdownSandbox: an isolated long-running container driven by exec, files and tunnels (resources.md §3.5, ADR-044).
Sandbox.create(name=...) is create-by-name: an identical create reconnects to (and wakes) the existing Sandbox,
a different spec is AlreadyExists with a diff. The image defaults to nodus/agent-tools client-side.
Spec fields the API does not serve yet (volumes, ports, init, service, egress allow-lists) raise
errors.Unsupported before anything is sent, because the API rejects an unknown field outright. secrets is sent
when set, and a server that does not take it yet answers Unsupported as well.
class Init(git: str | None = None, ref: str | None = None, path: str | None = None, project: str | Path | None = None, setup: str | None = None) -> NoneOne-time setup: clone git (or upload the local project directory), then run setup as Process setup.
Init.git
Section titled “Init.git”Type: str | None
Init.path
Section titled “Init.path”Type: str | None
Init.project
Section titled “Init.project”Type: str | Path | None
Init.ref
Section titled “Init.ref”Type: str | None
Init.setup
Section titled “Init.setup”Type: str | None
Sandbox
Section titled “Sandbox”class Sandbox(obj: Obj) -> NoneSandbox.create
Section titled “Sandbox.create”create(*command: str, name: str | None = None, image: Any = None, cpu: Any = None, memory: Any = None, gpu: Any = None, disk: Any = None, timeout: Any = None, idle_timeout: Any = None, on_idle: str = 'stop', secrets: list[Any] | None = None, volumes: Mapping[str, Any] | None = None, env: dict[str, str] | None = None, workdir: str | None = None, network: _spec.Egress | None = None, ports: list[int] | None = None, init: Init | None = None, service: Service | None = None, max_cost: Any = None, labels: dict[str, str] | None = None, idempotency_key: str | None = None, project: str | None = None) -> _SandboxCreate (or reconnect to, by name) a Sandbox; returns without waiting for it to start.
Sandbox.exec
Section titled “Sandbox.exec”exec(*command: str, pty: bool = False, stdin: bool = False, env: dict[str, str] | None = None, workdir: str | None = None, timeout: Any = None) -> _ProcessStart a recorded Process; a single string with spaces runs under /bin/sh -c. Wakes a stopped Sandbox.
Sandbox.files
Section titled “Sandbox.files”Type: _Files
Sandbox.from_id
Section titled “Sandbox.from_id”from_id(object_id: str, project: str | None = None) -> _SandboxSandbox.from_name
Section titled “Sandbox.from_name”from_name(name: str, project: str | None = None) -> _SandboxReconnect by name; a Sandbox the user stopped is started again.
Sandbox.list
Section titled “Sandbox.list”list(labels: Mapping[str, str] | None = None, project: str | None = None) -> list[_Sandbox]Sandbox.logs
Section titled “Sandbox.logs”logs(follow: bool = False) -> AsyncIterator[str]Sandbox.name
Section titled “Sandbox.name”Type: str
Sandbox.object_id
Section titled “Sandbox.object_id”Type: str | None
Sandbox.open
Section titled “Sandbox.open”open(path: str, mode: str = 'r') -> _FileSandbox.refresh_secrets
Section titled “Sandbox.refresh_secrets”refresh_secrets() -> NoneSandbox.snapshot_filesystem
Section titled “Sandbox.snapshot_filesystem”snapshot_filesystem(name: str | None = None) -> AnyBuild an Image from this Sandbox’s filesystem (Beta); use it as image= for new Sandboxes.
Sandbox.start
Section titled “Sandbox.start”start() -> NoneSandbox.status
Section titled “Sandbox.status”status() -> ViewThe Sandbox’s status (phase, activity, endpoints, stop reason, cost).
Sandbox.stop
Section titled “Sandbox.stop”stop() -> NoneSandbox.terminate
Section titled “Sandbox.terminate”terminate() -> NoneSandbox.tunnels
Section titled “Sandbox.tunnels”Type: _Tunnels
Sandbox.wait
Section titled “Sandbox.wait”wait() -> int | NoneWait for the main command to exit and return its exit code (None when the Sandbox stopped without one).
Service
Section titled “Service”class Service(command: str | list[str], port: int, health_path: str | None = None) -> NoneA supervised main service: restarted on exit, health-checked on health_path.
Service.command
Section titled “Service.command”Type: str | list[str]
Service.health_path
Section titled “Service.health_path”Type: str | None
Service.port
Section titled “Service.port”Type: int
Tunnel
Section titled “Tunnel”class Tunnel(port: int, url: str, public: bool = False) -> NoneTunnel.port
Section titled “Tunnel.port”Type: int
Tunnel.public
Section titled “Tunnel.public”Type: bool
Tunnel.url
Section titled “Tunnel.url”Type: str
Tunnels
Section titled “Tunnels”class Tunnels(sb: _Sandbox) -> Nonesb.tunnels.open(port) adds an ingress port and returns its URL; sb.tunnels() lists them.
Tunnels.open
Section titled “Tunnels.open”open(port: int, public: bool = False) -> Tunnel