Docs/Sandbox protocolv1.0.0-rc.1

UDIOT Sandbox RPC Protocol

Added: v0.16.0 Client: RemoteWorkspaceFS from @tagna/udiot/sandbox

This protocol is the wire contract between RemoteWorkspaceFS and a sandbox worker. UDIOT provides the client. Hosted products provide the worker and the isolation boundary.

Endpoints

Method Path Purpose
POST /rpc Execute one workspace operation
GET /stream/:id Optional NDJSON stream for runCommand().onChunk output

RPC Request

{
  "id": "uuid",
  "method": "writeFile",
  "params": {
    "path": "src/example.ts",
    "content": "export const ok = true;\n",
    "encoding": "utf8"
  }
}

The client sends Authorization: Bearer <token> when authToken is configured.

RPC Response

Successful calls return:

{
  "id": "uuid",
  "result": {}
}

Failed calls return:

{
  "id": "uuid",
  "error": {
    "message": "path escapes workspace root",
    "code": "PATH_TRAVERSAL"
  }
}

The client throws an Error with the returned message.

Methods

Method Params Result
readFile { path } UTF-8 string
readBytes { path } Base64 string
writeFile { path, content, encoding } void
applyDiff { diff } void
listFiles { glob } string[]
deleteFile { path, force } void
runCommand { id, command, args, cwd, env, shell, timeoutMs } RunCommandResult
startServer { command, args, cwd, env, port, readyPattern, readyTimeoutMs } { id, pid?, url? }
stopServer { id } void
getPreviewUrl { id } URL string
snapshot {} Base64 tarball or implementation-defined snapshot bytes
dispose { purge } void

Command Output Stream

If callers pass onChunk to runCommand(), the client opens GET /stream/:id while the RPC request is active. The worker may emit one JSON object per line:

{"stream":"stdout","data":"running tests\n"}
{"stream":"stderr","data":"warning: slow test\n"}

The stream is optional. runCommand() must still return final stdout, stderr, exitCode, and durationMs in the RPC response.

Safety Requirements

Workers should reject path traversal, enforce workspace-root confinement, bound command duration, avoid shell evaluation unless explicitly allowed, and terminate child processes during dispose({ purge: true }).

From the canonical UDIOT public documentation.Try it in the playground ↗