Connect to an interactive terminal session on a computer via WebSocket. This provides a full PTY (pseudo-terminal) interface, enabling real-time bidirectional communication with the computer’s shell.
Connection URL
wss://{computer_id}.orgo.dev/terminal?token={password}
Authentication
The terminal WebSocket requires the computer’s password as the token query parameter. This is the same password used for VNC connections. Retrieve it from the Get VNC Password endpoint before connecting.
Connections without a valid token are rejected with close code 4401.
Query Parameters
Number of columns for the terminal.
Number of rows for the terminal.
Message Protocol
All messages are JSON-encoded. The WebSocket uses a simple request/response protocol with the following message types.
Client → Server Messages
Resize the terminal dimensions. {
"type" : "resize" ,
"cols" : 120 ,
"rows" : 40
}
Send a heartbeat ping to keep the connection alive.
Server → Client Messages
Terminal output data. {
"type" : "output" ,
"data" : "user@computer:~$ "
}
The terminal output. May contain ANSI escape codes for colors and formatting.
Error message from the server. {
"type" : "error" ,
"message" : "Connection failed"
}
Human-readable error description.
The shell process has exited. {
"type" : "exit" ,
"code" : 0
}
Exit code of the shell process.
Response to a ping message.
Examples
JavaScript
Python
TypeScript
const computerId = 'orgo-a3bb189e-8bf9-3888-9912-ace4e6543002' ;
const apiKey = process . env . ORGO_API_KEY ;
// Step 1: Get the computer password
const res = await fetch (
`https://www.orgo.ai/api/computers/ ${ computerId } /vnc-password` ,
{ headers: { 'Authorization' : `Bearer ${ apiKey } ` } }
);
const { password } = await res . json ();
// Step 2: Connect with password as token
const ws = new WebSocket (
`wss:// ${ computerId } .orgo.dev/terminal?token= ${ password } &cols=80&rows=24`
);
ws . onopen = () => {
console . log ( 'Connected to terminal' );
};
ws . onmessage = ( event ) => {
const message = JSON . parse ( event . data );
switch ( message . type ) {
case 'output' :
// Append to your terminal display
terminal . write ( message . data );
break ;
case 'error' :
console . error ( 'Terminal error:' , message . message );
break ;
case 'exit' :
console . log ( 'Shell exited with code:' , message . code );
break ;
}
};
// Send a command
function sendCommand ( command ) {
ws . send ( JSON . stringify ({
type: 'input' ,
data: command + ' \r ' // \r for Enter key
}));
}
// Resize terminal
function resizeTerminal ( cols , rows ) {
ws . send ( JSON . stringify ({
type: 'resize' ,
cols ,
rows
}));
}
// Example: Run a command
sendCommand ( 'echo "Hello, World!"' );
Integration with xterm.js
For browser-based terminal UIs, we recommend using xterm.js :
import { Terminal } from '@xterm/xterm' ;
import { FitAddon } from '@xterm/addon-fit' ;
import '@xterm/xterm/css/xterm.css' ;
// Initialize xterm.js
const terminal = new Terminal ({
cursorBlink: true ,
fontFamily: 'monospace' ,
fontSize: 14 ,
});
const fitAddon = new FitAddon ();
terminal . loadAddon ( fitAddon );
terminal . open ( document . getElementById ( 'terminal' ));
fitAddon . fit ();
// Step 1: Get the computer password
const computerId = 'orgo-a3bb189e-8bf9-3888-9912-ace4e6543002' ;
const res = await fetch (
`https://www.orgo.ai/api/computers/ ${ computerId } /vnc-password` ,
{ headers: { 'Authorization' : `Bearer ${ apiKey } ` } }
);
const { password } = await res . json ();
// Step 2: Connect with password as token
const ws = new WebSocket (
`wss:// ${ computerId } .orgo.dev/terminal?token= ${ password } &cols= ${ terminal . cols } &rows= ${ terminal . rows } `
);
// Handle output from server
ws . onmessage = ( event ) => {
const message = JSON . parse ( event . data );
if ( message . type === 'output' ) {
terminal . write ( message . data );
}
};
// Send user input to server
terminal . onData (( data ) => {
ws . send ( JSON . stringify ({ type: 'input' , data }));
});
// Handle terminal resize
window . addEventListener ( 'resize' , () => {
fitAddon . fit ();
ws . send ( JSON . stringify ({
type: 'resize' ,
cols: terminal . cols ,
rows: terminal . rows
}));
});
Best Practices
Heartbeat Send periodic ping messages (every 30 seconds) to keep the connection alive and detect disconnections early.
Reconnection Implement automatic reconnection with exponential backoff. Start with 2 seconds and increase up to 30 seconds.
Resize Events Send resize messages whenever the terminal container size changes to ensure proper text wrapping.
ANSI Support The terminal output may contain ANSI escape codes. Use a library like xterm.js that handles these automatically.
The terminal WebSocket provides direct shell access. For running individual commands programmatically, consider using the Execute Bash endpoint instead.