Skip to content
Hoody.com

This page documents the system monitoring endpoints exposed by the terminal container: aggregate resource statistics, process inventory, network port discovery, display state, daemon configuration, and the power management controls (reboot, shutdown, and process freeze or unfreeze). It also covers the optional client diagnostics beacon that the terminal client posts so the server can correlate render or connection issues with server-side state.

All endpoints below share the same base URL, since they are all served by the terminal container.

Unauthenticated health probe for the terminal container. Always responds with HTTP 200 and a JSON body when the service is up.

This endpoint takes no parameters.

Terminal window
curl -X GET 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/health'
{
"status": "ok",
"service": "hoody-terminal",
"built": "2026-04-14T10:00:00Z",
"started": "2026-04-14T10:01:00Z",
"memory": {
"rss": 52428800,
"heap": null
},
"fds": 47,
"pid": 1234,
"ip": "198.51.100.42",
"userAgent": "curl/8.0.0"
}

Returns aggregate CPU, memory, network interface, uptime, and disk statistics for the container.

This endpoint takes no parameters.

Terminal window
curl -X GET 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/resources'
{
"memory": {
"total_kb": 16777216,
"free_kb": 2097152,
"available_kb": 8388608,
"buffers_kb": 1468,
"cached_kb": 6291456,
"swap_total_kb": 4194304,
"swap_free_kb": 4194304,
"swap_cached_kb": 0,
"used_kb": 8388608,
"used_percent": 50
},
"cpu": {
"usage_percent": 15.5,
"load_1min": 1.2,
"load_5min": 0.9,
"load_15min": 0.7,
"user": 1044524,
"nice": 4657,
"system": 467452,
"idle": 33880505,
"iowait": 25169
},
"uptime": {
"uptime_seconds": 86400.5,
"idle_seconds": 675000.2
},
"network": [
{
"name": "eth0",
"rx_bytes": 1024000,
"rx_packets": 8000,
"rx_errors": 0,
"tx_bytes": 2048000,
"tx_packets": 9000,
"tx_errors": 0
}
],
"disk": [
{
"device": "nvme0n1",
"reads": 96886,
"writes": 77549,
"read_sectors": 4942803,
"write_sectors": 1625191
}
]
}

Lists every process running in the container with CPU, memory, and state information. Supports filtering by name or command line, sorting by common metrics, and limiting the number of results. cpu_percent is the process’s CPU time over its lifetime (above 100 on several cores); mem_percent is resident memory over total memory; vsize and rss are bytes; output_type is what the process’s stdout is (pty, pipe, null, file, other, or unknown when it cannot be read). total_processes equals process_count: both count the processes returned.

NameInTypeRequiredDescription
sortquerystringNoSort by field: cpu, memory, pid, name (default: pid)
limitqueryintegerNoMaximum number of processes to return (default: 1000)
filterquerystringNoKeep processes whose name or command line contains this text (case-sensitive)
Terminal window
curl -X GET 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/processes?sort=cpu&limit=20'
{
"process_count": 1,
"total_processes": 1,
"processes": [
{
"pid": 1,
"name": "systemd",
"cmdline": "/sbin/init",
"state": "S",
"ppid": 0,
"user": "root",
"threads": 1,
"cpu_percent": 0.07,
"mem_percent": 0.01,
"vsize": 25497600,
"rss": 11001856,
"priority": 20,
"nice": 0,
"output_type": "unknown"
}
]
}

Returns detailed information about a single process: the fields of the process list plus process group, session, controlling terminal, uid, CPU times and start time (clock ticks), the pty path (pty, only when the process has one) and its environment (env, only when readable).

NameInTypeRequiredDescription
pidpathintegerYesProcess ID
Terminal window
curl -X GET 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/processes/1234'
{
"pid": 1234,
"name": "bash",
"cmdline": "bash",
"state": "S",
"ppid": 1200,
"pgrp": 1234,
"session": 1234,
"tty_nr": 34816,
"user": "user",
"uid": 1000,
"threads": 1,
"priority": 20,
"nice": 0,
"cpu_percent": 0.2,
"mem_percent": 0.01,
"vsize": 9469952,
"rss": 5357568,
"utime": 12,
"stime": 4,
"starttime": 2268334,
"output_type": "pty",
"pty": "/dev/pts/0",
"env": {
"PATH": "/usr/bin",
"TERM": "xterm-256color"
}
}

Sends a Unix signal to one or more processes. Target by PID for a single process, or by name to signal every matching process. The string form of signal accepts the conventional names with or without the SIG prefix; the integer form accepts any value in [0, NSIG), including realtime signals SIGRTMIN..SIGRTMAX (typically 34..64 on Linux), which have no portable string names.

This endpoint takes no parameters.

FieldTypeRequiredDescription
pidintegerNoProcess ID to signal. Mutually exclusive with name.
namestringNoProcess name to signal. Signals every matching process. Mutually exclusive with pid.
signalstring or integerNoSignal to send. String form accepts SIGTERM, TERM, 15, etc. (with or without SIG prefix). Integer form accepts any value in [0, NSIG), including realtime signals SIGRTMIN..SIGRTMAX (typically 34..64 on Linux), which have no portable string names.
forcebooleanNoShorthand for SIGKILL (true) or SIGTERM (false). Overrides the signal parameter.
Terminal window
curl -X POST 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/process/signal' \
-H 'Content-Type: application/json' \
-d '{"pid": 1234, "signal": "SIGTERM"}'
{
"success": true,
"message": "Signal SIGTERM sent to PID 1234",
"affected_pids": [1234]
}

The freeze and unfreeze endpoints suspend and resume a process (or an entire process tree) by delivering SIGSTOP and SIGCONT. They are the recommended way to pause background workloads (builds, fine-tunes, AI inference) without losing in-memory state.

Both endpoints share the same request body. Exactly one of pid or name must be provided.

Suspends execution of one or more processes by delivering SIGSTOP. The kernel halts every thread of the target’s thread group until a matching SIGCONT arrives (see the unfreeze endpoint below).

This endpoint takes no parameters.

FieldTypeRequiredDescription
pidintegerNoProcess ID to freeze. Mutually exclusive with name. PIDs 1, 2, the server’s own PID, and the server’s parent PID are guarded and rejected with 403.
namestringNoProcess name (case-insensitive comm match; freezes every matching process). Mutually exclusive with pid. Linux truncates comm to 15 characters, so longer names silently match nothing.
include_descendantsbooleanNoWhen true, also freezes every descendant via a one-shot /proc PPID snapshot (bounded at 65535 PIDs). Default false. The parent is signalled before descendants to shrink the fork or escape race window, but the operation is best-effort, not atomic. With descendants, by-name dedupes overlapping subtrees so the same PID is not signalled twice.
Terminal window
curl -X POST 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/processes/freeze' \
-H 'Content-Type: application/json' \
-d '{"pid": 1234, "include_descendants": true}'
{
"success": true,
"operation": "freeze",
"signal": "SIGSTOP",
"affected_pids": [1234, 5678],
"skipped": [],
"frozen_count": 2,
"message": "Froze 2 process(es)"
}

Resumes execution of one or more previously stopped processes by delivering SIGCONT. The body schema is identical to freeze. Calling unfreeze on a process that is already running is harmless: SIGCONT is a no-op for processes that are not stopped.

This endpoint takes no parameters.

FieldTypeRequiredDescription
pidintegerNoProcess ID to unfreeze. Mutually exclusive with name. The guarded-PID set (1, 2, self, parent) is the same as for freeze; calling unfreeze on a guarded PID returns 403.
namestringNoProcess name (case-insensitive comm match). Mutually exclusive with pid. Linux truncates comm to 15 characters, so longer names silently match nothing.
include_descendantsbooleanNoAlso unfreeze every descendant via a /proc PPID snapshot (bounded at 65535 PIDs). Default false. By-name dedupes overlapping subtrees.
Terminal window
curl -X POST 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/processes/unfreeze' \
-H 'Content-Type: application/json' \
-d '{"pid": 1234, "include_descendants": true}'
{
"success": true,
"operation": "unfreeze",
"signal": "SIGCONT",
"affected_pids": [1234, 5678],
"skipped": [],
"unfrozen_count": 2,
"message": "Unfroze 2 process(es)"
}

Lists every listening TCP and UDP port on the container, with the owning PID, user, program, and command line. Use the query parameters to filter the result set; the endpoint does not paginate and returns the full matching set in one response.

NameInTypeRequiredDescription
protocolquerystringNoFilter by protocol: tcp, udp, or comma-separated list
userquerystringNoFilter by user (exact match)
portqueryintegerNoFilter by specific port number
ipquerystringNoFilter by IP address (comma-separated list)
skip_programquerystringNoExclude specific programs (comma-separated list)
http_onlyquerybooleanNoOnly return HTTP services
hoody_onlyquerybooleanNoOnly return Hoody Kit services
Terminal window
curl -X GET 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/ports?protocol=tcp&http_only=true'
[
{
"protocol": "tcp",
"port": 7681,
"ip": "0.0.0.0",
"pid": 1234,
"user": "user",
"program": "hoody-terminal",
"cmdline": "./hoody-terminal -p 7681",
"is_http": true,
"hoody_kit": true
}
]

Returns information about the displays connected to the container, as reported by the external display script. Each entry includes a display identifier, the current resolution, and the session name it is attached to. To stop a running display, see the stop endpoint below.

This endpoint takes no parameters.

Terminal window
curl -X GET 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/displays'
[
{
"display": "0",
"resolution": "1920x1080",
"session_name": "session1"
}
]

POST /api/v1/system/displays/{display}/stop

Section titled “POST /api/v1/system/displays/{display}/stop”

Stops the X display :{display} and everything drawing on it. A display started by a terminal session (the session’s display, with or without desktop/desktop_env) keeps running when that session is deleted, desktop environment included, so it stays usable from other sessions and from Hoody Display; this route is how it ends. The display’s session server receives SIGTERM, which shuts down its X server (a session server that exits while still starting up can leave its X server running; that X server then receives SIGTERM too). The window manager, panels, and applications on the display exit with it. A display without a session server has its X server signalled directly. Whatever is still running after 10 seconds receives SIGKILL (forced is true). The response is sent once the display is gone. Only displays the terminal service can reach are found, so an X server you started with -nolisten local is not found. Background services a desktop started outside the display (for example a D-Bus session bus) are not stopped. Sessions whose DISPLAY points at the stopped display keep running; the next session created with that display starts it again.

NameInTypeRequiredDescription
displaypathintegerYesDisplay number (the N in :N), 0-65535
Terminal window
curl -X POST 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/displays/1/stop'
{
"display": 1,
"stopped": true,
"pid": 4321,
"x_server_pid": 4330,
"xpra": true,
"forced": false,
"message": "Display :1 stopped"
}

Returns the array of daemon programs loaded from the hoody-daemon configuration. Each entry includes the daemon’s name, the command used to launch it, and whether it is currently enabled.

This endpoint takes no parameters.

Terminal window
curl -X GET 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/daemon'
[
{
"name": "nginx",
"command": "/usr/sbin/nginx",
"enabled": true
}
]

Initiates a system reboot. The kernel enforces the permission check, so the caller must have root or sudo privileges. The optional delay parameter schedules the reboot for a future time, in seconds.

NameInTypeRequiredDescription
delayqueryintegerNoDelay in seconds before reboot, 0..86400 (default: 0 for immediate). shutdown(8) schedules in whole minutes, so the server rounds UP to the nearest minute and reports the actual scheduled value as effective_minutes in the response.
Terminal window
curl -X POST 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/reboot?delay=60'
{
"success": true,
"message": "Reboot scheduled in 1 minute(s) (requested 60 seconds, rounded up)",
"delay_seconds": 60,
"effective_minutes": 1
}

Initiates a system shutdown. The kernel enforces the permission check, so the caller must have root or sudo privileges. The optional delay parameter schedules the shutdown for a future time, in seconds.

NameInTypeRequiredDescription
delayqueryintegerNoDelay in seconds before shutdown, 0..86400 (default: 0 for immediate). shutdown(8) schedules in whole minutes, so the server rounds UP to the nearest minute and reports the actual scheduled value as effective_minutes in the response.
Terminal window
curl -X POST 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/shutdown?delay=60'
{
"success": true,
"message": "Shutdown scheduled in 1 minute(s) (requested 60 seconds, rounded up)",
"delay_seconds": 60,
"effective_minutes": 1
}

Optional telemetry endpoint. The terminal client posts its own render and connection health (frontend build, effective renderer, the reason for the beacon) so the server can correlate client-side stalls with server-side session state.

This endpoint takes no parameters.

FieldTypeRequiredDescription
build_idstringNoFrontend build identifier
rendererstringNoEffective renderer (webgl or dom)
reasonstringNoWhat triggered this beacon
Terminal window
curl -X POST 'https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/state' \
-H 'Content-Type: application/json' \
-d '{"build_id": "2026.04.14-rc1", "renderer": "webgl", "reason": "stall-detected"}'
{}

The server acknowledges the beacon. No fields are returned.