The terminal service exposes endpoints for inspecting the runtime state of a container instance (CPU, memory, processes, network ports, displays, and daemons) and for actively managing it: sending signals to processes, freezing/resuming workloads, and controlling system power. Use these endpoints to power dashboards, automate cleanup, or correlate resource pressure with running workloads.
All endpoints on this page are scoped to a single container instance. The base URL targets one terminal replica; replace {projectId}, {containerId}, and {server} with values from your environment.
Liveness probe for the terminal service. Returns the standardized 9-field health envelope. Unauthenticated. Always returns HTTP 200 with application/json when the service is responsive.
This endpoint takes no parameters.
curl -X GET " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/health "
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . health . check ();
" started_at " : " 2025-01-15T10:00:00Z " ,
Returns comprehensive system statistics: CPU usage (per-core and aggregate), memory, swap, network interfaces, uptime, and disk usage.
This endpoint takes no parameters.
curl -X GET " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/resources "
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . getResources ();
" hostname " : " terminal-1 " ,
" boot_time " : " 2025-01-15T10:00:00Z " ,
" load_average " : [ 0.42 , 0.38 , 0.31 ],
" model " : " Intel(R) Xeon(R) Platinum 8358 " ,
" per_core_percent " : [ 10.2 , 14.1 , 8.7 , 11.0 , 15.3 , 13.2 , 12.8 , 14.7 ]
" total_bytes " : 17179869184 ,
" available_bytes " : 8589934592 ,
" used_bytes " : 8589934592 ,
" buffers_bytes " : 268435456 ,
" cached_bytes " : 1610612736
" total_bytes " : 4294967296 ,
" total_bytes " : 536870912000 ,
" used_bytes " : 214748364800 ,
" available_bytes " : 322122547200 ,
Returns information about connected displays, sourced from the host’s external display script. Useful for graphics-aware tooling and remote-desktop dashboards.
This endpoint takes no parameters.
curl -X GET " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/displays "
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . getDisplayInfo ();
" resolution " : " 3840x2160 " ,
Returns the JSON array of daemon programs from the hoody-daemon configuration. Use this to discover long-running background services available on the instance.
This endpoint takes no parameters.
curl -X GET " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/daemon "
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . getDaemonConfig ();
" command " : " /usr/local/bin/hoody-watcher " ,
" args " : [ " --config " , " /etc/hoody/watcher.yaml " ],
" HOODY_LOG_LEVEL " : " info "
" command " : " /usr/local/bin/hoody-metrics " ,
" args " : [ " --port " , " 9090 " ],
Returns the array of all running processes, with CPU, memory, and state information. Supports sorting, filtering by name (case-insensitive substring), and limiting result count.
Name In Type Required Description sortquery string No Sort by field. One of cpu, memory, pid, name. Default: pid. limitquery integer No Maximum number of processes to return. Default: all. filterquery string No Filter by process name (substring match, case-insensitive).
curl -X GET " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/processes?sort=cpu&limit=20&filter=node "
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . listProcessesIterator ({ sort : ' cpu ' , limit : 20 , filter : ' node ' });
" memory_rss_bytes " : 723517440 ,
" cmdline " : " node /srv/app/server.js --port 3000 " ,
" started_at " : " 2025-01-15T10:05:21Z " ,
" memory_rss_bytes " : 309329920 ,
" cmdline " : " node /srv/app/worker.js " ,
" started_at " : " 2025-01-15T10:05:22Z " ,
Returns detailed information about a specific process: full stats, command line, environment variables, and open files.
Name In Type Required Description pidpath integer Yes Process ID.
curl -X GET " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/processes/1024 "
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . getProcess ( 1024 );
" memory_rss_bytes " : 723517440 ,
" memory_vms_bytes " : 2748779069 ,
" cmdline " : [ " node " , " /srv/app/server.js " , " --port " , " 3000 " ],
" started_at " : " 2025-01-15T10:05:21Z " ,
" exe " : " /usr/local/bin/node " ,
" NODE_ENV " : " production " ,
" message " : " Process not found "
Error Code Title Description Resolution PROCESS_NOT_FOUNDProcess does not exist The specified PID does not correspond to a running process. Check PID is valid and process is running.
Send a Unix signal to one or more processes. Target by pid (single process) or by name (signals every matching process — case-insensitive comm match, truncated to 15 characters). Supports all standard signals including SIGTERM, SIGKILL, SIGSTOP, SIGCONT, and realtime signals (32..64 on Linux). Pass the signal as a string (SIGTERM, TERM, 15) or as an integer.
Field Type Required Description pidinteger No Process ID to signal. Mutually exclusive with name. namestring No Process name to signal — signals ALL matching processes. Mutually exclusive with pid. signalstring or integer No Signal 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. forceboolean No Shorthand for SIGKILL (true) or SIGTERM (false) — overrides the signal parameter.
curl -X POST " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/process/signal " \
-H " Content-Type: application/json " \
-d ' {"pid": 1024, "signal": "SIGTERM"} '
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . sendSignal ({ pid : 1024 , signal : ' SIGTERM ' });
" message " : " Missing target "
Error Code Title Description Resolution MISSING_TARGETMust specify pid or name Neither pid nor name was provided in the request body. Provide either pid or name parameter. INVALID_SIGNALInvalid signal name The signal name or integer is not recognized by the kernel. Use a valid signal (SIGTERM, SIGKILL, etc.).
" message " : " Permission denied "
Error Code Title Description Resolution PERMISSION_DENIEDNo permission to signal process The kernel returned EPERM because the caller is not permitted to signal the target. Check process ownership.
" error " : " Method Not Allowed " ,
" message " : " Method is not POST "
" error " : " Internal Server Error " ,
" message " : " Failed to send signal "
Error Code Title Description Resolution SIGNAL_FAILEDFailed to send signal The signal could not be delivered. Check process exists.
SIGSTOP suspends a process’s entire thread group; SIGCONT resumes it. These endpoints let you pause background workloads (builds, fine-tunes, AI inference) without losing in-memory state, then resume them later.
Target by pid (a single process) or by name (every process whose comm matches case-insensitively). Linux truncates comm to 15 characters; a longer name silently matches nothing. Set include_descendants: true to fan out across the target’s child processes via a one-shot /proc PPID snapshot bounded at 65535 PIDs; the parent is signalled first so a forked child cannot escape, but the operation is best-effort and not atomic. By-name descendant traversal dedupes overlapping subtrees.
Caution
PID 1 (init), PID 2 (kthreadd), the server’s own PID, and its parent PID are guarded. Freezing any of these would wedge the host or the daemon itself, so they are rejected with HTTP 403. Non-root callers can only target processes they own — the kernel returns EPERM otherwise (surfaced as 403).
Suspend execution by delivering SIGSTOP to the target process or process tree. Resumed by a matching call to POST /api/v1/system/processes/unfreeze.
Field Type Required Description pidinteger No Process ID to freeze. Mutually exclusive with name. PIDs 1, 2, the server’s own PID, and the server’s parent PID are guarded and return 403. namestring No Process name (case-insensitive comm match; freezes EVERY matching process). Mutually exclusive with pid. Truncated to 15 characters by Linux. include_descendantsboolean No When true, also freezes every descendant via a /proc PPID snapshot (bounded at 65535 PIDs). Default false.
curl -X POST " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/processes/freeze " \
-H " Content-Type: application/json " \
-d ' {"pid": 1024, "include_descendants": true} '
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . freezeProcess ({ pid : 1024 , include_descendants : true });
" frozen " : [ 1024 , 1025 , 1102 , 1103 ],
" include_descendants " : true
" message " : " Missing target "
Error Code Title Description Resolution MISSING_TARGETMust specify pid or name Neither pid nor name was provided in the request body. Provide either pid or name parameter. INVALID_PIDpid must be a positive integer within int rangeThe supplied pid was not a positive integer or overflowed the int type. Contact support.
" message " : " Permission denied or PID guarded "
Error Code Title Description Resolution PERMISSION_DENIEDNo permission to freeze process Either the kernel returned EPERM (different UID) or the PID is in the guarded set (init/kthreadd/self/parent). Either run as the owning UID or target a non-guarded PID.
" message " : " Process not found "
Error Code Title Description Resolution PROCESS_NOT_FOUNDNo process matching pid/name The supplied selector did not match any running process. Verify the target PID or process name.
" error " : " Method Not Allowed " ,
" message " : " Method is not POST "
" error " : " Internal Server Error " ,
" message " : " Failed to freeze process "
Error Code Title Description Resolution FREEZE_FAILEDFailed to freeze process The SIGSTOP could not be delivered to one or more targets. Check process exists. PROC_SNAPSHOT_OOM/proc snapshot exhausted memory; transientThe PPID snapshot ran out of memory while resolving descendants. Contact support. PROC_TABLE_TOO_LARGE/proc PID table exceeds HT_PID_TABLE_MAX (65535)The descendant snapshot bound was exceeded. Contact support.
Resume execution by delivering SIGCONT. The body schema mirrors /freeze exactly — same pid/name selector and include_descendants option. Calling unfreeze on a process that is already running is harmless: SIGCONT is a no-op for non-stopped processes.
Field Type Required Description pidinteger No Process ID to unfreeze. Mutually exclusive with name. The guarded-PID set (1, 2, self, parent) returns 403. namestring No Process name (case-insensitive comm match). Mutually exclusive with pid. Truncated to 15 characters by Linux. include_descendantsboolean No Also unfreeze all descendants via a /proc PPID snapshot (bounded at 65535 PIDs). Default false. By-name traversal dedupes overlapping subtrees.
curl -X POST " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/processes/unfreeze " \
-H " Content-Type: application/json " \
-d ' {"pid": 1024, "include_descendants": true} '
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . unfreezeProcess ({ pid : 1024 , include_descendants : true });
" resumed " : [ 1024 , 1025 , 1102 , 1103 ],
" include_descendants " : true
" message " : " Missing target "
Error Code Title Description Resolution MISSING_TARGETMust specify pid or name Neither pid nor name was provided in the request body. Provide either pid or name parameter. INVALID_PIDpid must be a positive integer within int rangeThe supplied pid was not a positive integer or overflowed the int type. Contact support.
" message " : " Permission denied or PID guarded "
Error Code Title Description Resolution PERMISSION_DENIEDNo permission to unfreeze process Either the kernel returned EPERM (different UID) or the PID is in the guarded set (init/kthreadd/self/parent). Either run as the owning UID or target a non-guarded PID.
" message " : " Process not found "
Error Code Title Description Resolution PROCESS_NOT_FOUNDNo process matching pid/name The supplied selector did not match any running process. Verify the target PID or process name.
" error " : " Method Not Allowed " ,
" message " : " Method is not POST "
" error " : " Internal Server Error " ,
" message " : " Failed to unfreeze process "
Error Code Title Description Resolution UNFREEZE_FAILEDFailed to unfreeze process The SIGCONT could not be delivered to one or more targets. Check process exists. PROC_SNAPSHOT_OOM/proc snapshot exhausted memory; transientThe PPID snapshot ran out of memory while resolving descendants. Contact support. PROC_TABLE_TOO_LARGE/proc PID table exceeds HT_PID_TABLE_MAX (65535)The descendant snapshot bound was exceeded. Contact support.
Returns all listening TCP/UDP ports with owning process information. Supports extensive filtering so you can narrow the result to a specific protocol, user, port, or IP range.
Name In Type Required Description protocolquery string No Filter by protocol: tcp, udp, or a comma-separated list. userquery string No Filter by user (exact match). portquery integer No Filter by specific port number. ipquery string No Filter by IP address (comma-separated list). skip_programquery string No Exclude specific programs (comma-separated list). http_onlyquery boolean No Only return HTTP services. hoody_onlyquery boolean No Only return Hoody Kit services.
curl -X GET " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/ports?protocol=tcp&http_only=true "
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . listPortsIterator ({ protocol : ' tcp ' , http_only : true });
" local_address " : " 0.0.0.0 " ,
" local_address " : " 127.0.0.1 " ,
" process_name " : " hoody-metrics " ,
" local_address " : " 0.0.0.0 " ,
Both endpoints schedule via shutdown(8), which only schedules in whole minutes — sub-minute delays are rounded up. The actual scheduled delay is reported in the response as effective_minutes. Both require root/sudo; the Linux kernel enforces permission checks.
Initiate a system reboot. Optionally delay the action by up to 24 hours.
Name In Type Required Description delayquery integer No Delay in seconds before reboot, in the range 0..86400 (default 0 for immediate). The server rounds up to the nearest minute and reports effective_minutes in the response.
curl -X POST " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/reboot?delay=60 "
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . reboot ({ delay : 60 });
" message " : " Delay out of range (> 86400) "
" message " : " Reboot requires root privileges "
Error Code Title Description Resolution ROOT_REQUIREDReboot requires root privileges The caller is not running as root/sudo. Run with sudo or as root user.
" error " : " Method Not Allowed " ,
" message " : " Method is not POST "
" error " : " Internal Server Error " ,
" message " : " Failed to execute reboot "
Error Code Title Description Resolution REBOOT_FAILEDFailed to execute reboot The reboot system call failed. Check system logs.
Initiate a system shutdown. Optionally delay the action by up to 24 hours.
Name In Type Required Description delayquery integer No Delay in seconds before shutdown, in the range 0..86400 (default 0 for immediate). The server rounds up to the nearest minute and reports effective_minutes in the response.
curl -X POST " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/system/shutdown?delay=300 "
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . system . shutdown ({ delay : 300 });
" message " : " Delay out of range (> 86400) "
" message " : " Shutdown requires root privileges "
Error Code Title Description Resolution ROOT_REQUIREDShutdown requires root privileges The caller is not running as root/sudo. Run with sudo or as root user.
" error " : " Method Not Allowed " ,
" message " : " Method is not POST "
" error " : " Internal Server Error " ,
" message " : " Failed to execute shutdown "
Error Code Title Description Resolution SHUTDOWN_FAILEDFailed to execute shutdown The shutdown system call failed. Check system logs.
A terminal client posts its own render/connection health here so the server can correlate client-side stalls (frozen UI, dropped WebSocket, WebGL fallback) with server-side session state.
Post a client-state envelope for diagnostics correlation. The request body is optional; if omitted, the server just records that the client reached the endpoint.
Field Type Required Description build_idstring No Frontend build identifier. rendererstring No Effective renderer, typically webgl or dom. reasonstring No What triggered this beacon (for example, connection_resumed, render_stall).
curl -X POST " https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com/api/v1/terminal/state " \
-H " Content-Type: application/json " \
-d ' {"build_id": "web-1.4.2", "renderer": "webgl", "reason": "connection_resumed"} '
import { HoodyClient } from ' hoody-sdk ' ;
const client = new HoodyClient ({ baseURL : ' https://{projectId}-{containerId}-terminal-1.{server}.containers.hoody.com ' , token : process . env . HOODY_TOKEN });
await client . terminal . terminalState . postTerminalState ({
reason : ' connection_resumed ' ,