Terminal
The terminal endpoints let you create interactive PTY sessions inside the workspace VM. Terminal I/O is multiplexed over a single WebSocket connection.
Requires the internal server to be enabled. Up to 10 concurrent terminal sessions per workspace.
Overview
1. Create a terminal session → get session ID
2. Open WebSocket at /ws → bidirectional I/O
3. Send stdin as binary → [id_byte][data]
4. Receive stdout as binary → [id_byte][data]
5. Resize / close via JSON messages or RESTCreate session
Create a new terminal session with an interactive PTY.
const rt = await client.workspaces.runtime('ws_a1b2c3d4');
const term = await rt.terminal.create({
shell: '/bin/bash',
cols: 120,
rows: 40,
});
console.log(term.id); // "1"
console.log(term.cols); // 120
console.log(term.rows); // 40POST https://workspace.oblien.com/terminals
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
{
"cmd": ["/bin/bash"],
"cols": 120,
"rows": 40
}curl -X POST "https://workspace.oblien.com/terminals" \
-H "Authorization: Bearer $GATEWAY_JWT" \
-H "Content-Type: application/json" \
-d '{"cmd":["/bin/bash"],"cols":120,"rows":40}'Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
cmd | string[] | No | Command to run (e.g. ["/bin/bash"]). Falls back to default shell |
command | string[] | No | Alias for cmd |
cols | integer | No | Terminal width in columns |
rows | integer | No | Terminal height in rows |
scrollback_size | integer | No | Retained bytes: default 65,536, maximum 262,144; SDK option scrollbackSize |
Response
{
"success": true,
"id": "1",
"cols": 120,
"rows": 40,
"command": ["/bin/bash"]
}HTTP status: 201 Created
Manage terminal history
Terminal history is a bounded buffer in the workspace's memory. Clearing it keeps the terminal and its shell running; it does not erase shell command-history files or application logs.
PATCH https://workspace.oblien.com/terminals/1/scrollback
Authorization: Bearer <runtime-token>
Content-Type: application/json
{"scrollback_size": 32768}Use DELETE /terminals/1/scrollback to clear retained output, and GET /terminals/1/scrollback to read it. Zero resets the limit to 64 KiB; the maximum is 256 KiB. Changes apply to that terminal session. These endpoints follow the selected runtime target.
In the dashboard terminal header, Terminal history controls the retained buffer and browser scrollback separately. The browser defaults to 2,000 rows. A viewer that cannot keep up disconnects instead of accumulating output indefinitely; the shell continues running.
SDK releases containing these controls provide rt.terminal.configureScrollback(id, bytes) and rt.terminal.clearScrollback(id).
List sessions
List all active terminal sessions.
const sessions = await rt.terminal.list();
for (const term of sessions) {
console.log(`${term.id}: ${term.command.join(' ')} (alive: ${term.alive})`);
}GET https://workspace.oblien.com/terminals
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl "https://workspace.oblien.com/terminals" \
-H "Authorization: Bearer $GATEWAY_JWT"Response
{
"success": true,
"terminals": [
{
"id": "1",
"command": ["/bin/bash"],
"cols": 120,
"rows": 40,
"alive": true,
"exit_code": 0,
"created_at": "2025-01-15T10:30:00Z"
}
]
}Close session
Close a terminal session and kill its process.
await rt.terminal.close('1');DELETE https://workspace.oblien.com/terminals/1
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl -X DELETE "https://workspace.oblien.com/terminals/1" \
-H "Authorization: Bearer $GATEWAY_JWT"Response
{
"success": true,
"terminal_id": "1"
}Get scrollback
Retrieve the scrollback buffer for a terminal session. Useful for restoring terminal state after reconnection.
const scrollback = await rt.terminal.scrollback('1');
console.log(scrollback.size); // bytes in buffer
console.log(scrollback.alive); // session still running
console.log(scrollback.scrollback); // base64-encoded dataGET https://workspace.oblien.com/terminals/1/scrollback
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl "https://workspace.oblien.com/terminals/1/scrollback" \
-H "Authorization: Bearer $GATEWAY_JWT"Response
{
"success": true,
"scrollback": "dXNlckBzYW5kYm94Oi9hcHAkIA==",
"size": 2048,
"alive": true,
"exit_code": 0
}| Field | Description |
|---|---|
scrollback | Base64-encoded terminal output (64 KiB ring buffer) |
size | Size of the scrollback data in bytes |
alive | Whether the session is still running |
exit_code | Process exit code (0 if still alive) |
WebSocket
Terminal I/O flows over a single multiplexed WebSocket connection at /ws. Multiple terminal sessions share the same connection.
Connect
// Create a terminal session
const term = await rt.terminal.create({ shell: '/bin/bash' });
// Open a RuntimeWebSocket for bidirectional I/O
const ws = rt.ws();
ws.onTerminalOutput((id, data) => {
process.stdout.write(data);
});
ws.onClose(() => console.log('WebSocket closed'));
await ws.connect();
ws.writeTerminalInput(term.id, 'ls -la\n');
ws.resizeTerminal(term.id, 160, 50);WebSocket: wss://workspace.oblien.com/ws
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...const ws = new WebSocket('wss://workspace.oblien.com/ws', {
headers: { Authorization: `Bearer ${gatewayJwt}` },
});
ws.binaryType = 'arraybuffer';
ws.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) {
// Binary: terminal output
const bytes = new Uint8Array(event.data);
const terminalId = bytes[0];
const data = bytes.slice(1);
console.log(`Terminal ${terminalId}:`, new TextDecoder().decode(data));
} else {
// Text: control messages (exit, etc.)
const msg = JSON.parse(event.data);
console.log('Control:', msg);
}
};Protocol
Binary frames
| Direction | Format | Description |
|---|---|---|
| Client → Server | [id_byte][stdin_data] | Send input to terminal |
| Server → Client | [id_byte][stdout_data] | Receive output from terminal |
The first byte is the terminal ID byte (mapped from the session ID). The remaining bytes are raw terminal data.
Text frames
Resize a terminal:
{
"channel": "terminal",
"type": "resize",
"id": "1",
"cols": 160,
"rows": 50
}Terminal exit notification (server → client):
{
"channel": "terminal",
"type": "exit",
"id": "1",
"code": 0
}On connect
When a WebSocket connection is established, the server automatically sends:
- Scrollback data - binary frames with buffered output for each active session
- Exit notifications - text frames for any sessions that have already exited
This allows clients to restore terminal state after reconnection without explicit scrollback requests.
Error responses
| Status | Meaning |
|---|---|
400 | Missing terminal ID |
401 | Missing or invalid token |
404 | Terminal session not found |
405 | Method not allowed |
500 | Failed to create PTY session |