Command Execution

Run commands inside Sprites over WebSocket connections. The exec API is designed for both one-shot commands and long-running interactive sessions.

Sessions persist across disconnections—start a dev server or build, disconnect, and reconnect later to resume streaming output. The binary protocol efficiently multiplexes stdin, stdout, and stderr over a single connection.

Execute Command

WSS /v1/sprites/{name}/exec

Execute a command in the sprite environment via WebSocket. Commands continue running after disconnect; use max_run_after_disconnect to control timeout. Supports TTY and non-TTY modes.

Query Parameters

Pass these as query string parameters when connecting to the WebSocket.

cmd* string

Command to execute (can be repeated for command + args)

id string

Session ID to attach to an existing session

path string

Explicit path to executable (defaults to first cmd value or bash)

tty bool

Enable TTY mode (default: false)

stdin bool

Enable stdin. TTY default: true, non-TTY default: false

cols int

Initial terminal columns (default: 80)

rows int

Initial terminal rows (default: 24)

max_run_after_disconnect duration

Max time to run after disconnect. TTY default: 0 (forever), non-TTY default: 10s

env string

Environment variables in KEY=VALUE format (can be repeated). If set, replaces the default environment.

JSON Messages

ResizeMessage Client → Server
type* "resize"
cols* non_neg_integer

New column count

rows* non_neg_integer

New row count

SessionInfoMessage Server → Client
type* "session_info"
session_id* integer

Process PID

command* String

Command being executed

created* integer

Unix timestamp of session creation

cols* non_neg_integer

Terminal columns (TTY mode only)

rows* non_neg_integer

Terminal rows (TTY mode only)

is_owner* boolean

Whether this attachment owns the session

tty* boolean

Whether session is in TTY mode

ExitMessage Server → Client
type* "exit"
exit_code* integer

Process exit code

PortNotificationMessage Server → Client
type* "port_opened" | "port_closed"

Notification type

port* integer

Port number

address* String

Proxy URL for accessing the port

pid* integer

Process ID that opened/closed the port

Binary Protocol

In non-PTY mode, binary messages are prefixed with a stream identifier byte. In PTY mode, binary data is sent raw without prefixes.

Binary Frame Format (non-PTY):
Stream ID (1 byte) + Payload (N bytes)
Stream ID Name Direction Description
0 stdin client → server Standard input data
1 stdout server → client Standard output data
2 stderr server → client Standard error data
3 exit server → client Exit code (payload is exit code as byte)
4 stdin_eof client → server End of stdin stream

Response Codes

101

Switching Protocols - WebSocket connection established

400

Bad Request - Invalid WebSocket upgrade or missing parameters

404

Not Found - Resource not found

bash
websocat \
  "wss://api.sprites.dev/v1/sprites/{name}/exec?path=/bin/bash&tty=true" \
  -H "Authorization: Bearer $SPRITES_TOKEN"
Binary Streams
stdin (0x00 + data)
stdout (0x01 + data)
stderr (0x02 + data)
JSON Messages

Resize terminal (client → server):

{"type": "resize", "cols": 120, "rows": 40}

Port opened (server → client):

{"type": "port_opened", "port": 8080, "address": "0.0.0.0", "pid": 1234}

List Exec Sessions

GET /v1/sprites/{name}/exec

List active exec sessions.

Response

application/json

Response Codes

200

Success

404

Not Found - Resource not found

500

Internal Server Error

bash
curl -X GET \
  "https://api.sprites.dev/v1/sprites/{name}/exec" \
  -H "Authorization: Bearer $SPRITES_TOKEN"
200 Response
[
  {
    "bytes_per_second": 125.5,
    "command": "bash",
    "created": "2026-01-05T10:30:00Z",
    "id": 1847,
    "is_active": true,
    "last_activity": "2026-01-05T10:35:00Z",
    "tty": true,
    "workdir": "/home/sprite/myproject"
  },
  {
    "bytes_per_second": 0,
    "command": "python -m http.server 8000",
    "created": "2026-01-05T09:15:00Z",
    "id": 1923,
    "is_active": false,
    "last_activity": "2026-01-05T09:20:00Z",
    "tty": false,
    "workdir": "/home/sprite/webapp"
  }
]

Attach to Exec Session

WSS /v1/sprites/{name}/exec/{session_id}

Attach to an existing exec session via WebSocket.

JSON Messages

ResizeMessage Client → Server
type* "resize"
cols* non_neg_integer

New column count

rows* non_neg_integer

New row count

SessionInfoMessage Server → Client
type* "session_info"
session_id* integer

Process PID

command* String

Command being executed

created* integer

Unix timestamp of session creation

cols* non_neg_integer

Terminal columns (TTY mode only)

rows* non_neg_integer

Terminal rows (TTY mode only)

is_owner* boolean

Whether this attachment owns the session

tty* boolean

Whether session is in TTY mode

ExitMessage Server → Client
type* "exit"
exit_code* integer

Process exit code

Scrollback Buffer

When you attach to a session, the server immediately sends the session's scrollback buffer as stdout data. This allows you to see previous output that occurred while disconnected.

Response Codes

101

Switching Protocols - WebSocket connection established

400

Bad Request - Invalid WebSocket upgrade or missing parameters

404

Not Found - Resource not found

bash
websocat \
  "wss://api.sprites.dev/v1/sprites/{name}/exec/{session_id}" \
  -H "Authorization: Bearer $SPRITES_TOKEN"
Scrollback Buffer
On attach, the server sends the session's scrollback buffer as stdout data, allowing you to see previous output from the command.
JSON Messages

Resize terminal (client → server):

{"type": "resize", "cols": 120, "rows": 40}

Kill Exec Session

POST /v1/sprites/{name}/exec/{session_id}/kill

Kill an exec session by session ID. Returns streaming NDJSON with kill progress.

Query Parameters

signal string

Signal to send (default: SIGTERM)

timeout duration

Timeout waiting for process to exit (default: 10s)

Response

application/x-ndjson
ExecKillSignalEvent
type* "signal"
message* String

Status message

signal* String

Signal name (e.g., SIGTERM)

pid* integer

Target process ID

ExecKillTimeoutEvent
type* "timeout"
message* String

Status message

ExecKillExitedEvent
type* "exited"
message* String

Status message

ExecKillKilledEvent
type* "killed"
message* String

Status message

ExecKillErrorEvent
type* "error"
message* String

Error message

ExecKillCompleteEvent
type* "complete"
exit_code* integer

Process exit code

Response Codes

200

Success - Streaming NDJSON response

404

Not Found - Resource not found

500

Internal Server Error

bash
curl -X POST \
  "https://api.sprites.dev/v1/sprites/{name}/exec/{session_id}/kill" \
  -H "Authorization: Bearer $SPRITES_TOKEN"
200 Response
[
  {
    "message": "Signaling SIGTERM to process group 1847",
    "pid": 1847,
    "signal": "SIGTERM",
    "type": "signal"
  },
  {
    "message": "Process exited",
    "type": "exited"
  },
  {
    "exit_code": 0,
    "type": "complete"
  }
]