The Terminal System Monitoring service exposes endpoints to inspect and control the host running the Hoody daemon. Use it to build process inspectors, port scanners, system dashboards, and lifecycle automation. Operations cover system resources, daemon configuration, displays, listening ports, process introspection, signal delivery, process freeze/unfreeze, and full system power management.
All endpoints are served under /api/v1/system/... except the health probe, which lives at /api/v1/terminal/health.
Returns the standardized 9-field health response. Unauthenticated. Always returns HTTP 200 with application/json when the service is up.
This endpoint takes no parameters.
curl -X GET https://api.hoody.com/api/v1/terminal/health
const health = await client . terminal . health . check ();
"timestamp" : " 2025-01-15T14:22:08Z " ,
"load_average" : [ 0.42 , 0.51 , 0.48 ]
Returns comprehensive system statistics including CPU usage, memory, network interfaces, uptime, and disk usage.
This endpoint takes no parameters.
curl -X GET https://api.hoody.com/api/v1/system/resources \
-H " Authorization: Bearer <token> "
const stats = await client . terminal . system . getResources ();
"load_average" : [ 0.42 , 0.51 , 0.48 ]
"total_bytes" : 16777216000 ,
"used_bytes" : 7011696640 ,
"free_bytes" : 9765519360 ,
"hostname" : " hoody-prod-01 " ,
"total_bytes" : 536870912000 ,
"used_bytes" : 214748364800 ,
"free_bytes" : 322122547200 ,
Returns the JSON array of daemon programs from the hoody-daemon config.
This endpoint takes no parameters.
curl -X GET https://api.hoody.com/api/v1/system/daemon \
-H " Authorization: Bearer <token> "
const daemons = await client . terminal . system . getDaemonConfig ();
"name" : " hoody-supervisor " ,
"command" : " /usr/local/bin/hoody-supervisor " ,
"restart_policy" : " on-failure "
"command" : " /usr/local/bin/hoody-watcher " ,
"restart_policy" : " always "
Returns information about connected displays from the external display script.
This endpoint takes no parameters.
curl -X GET https://api.hoody.com/api/v1/system/displays \
-H " Authorization: Bearer <token> "
const displays = await client . terminal . system . getDisplayInfo ();
"resolution" : " 2560x1440 " ,
Returns a JSON array of all TCP/UDP listening ports with associated process information. Supports extensive filtering on protocol, user, port, IP, program name, and HTTP/Hoody-Kit service detection.
Name In Type Required Description protocolquery string No Filter by protocol: tcp, udp, or 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://api.hoody.com/api/v1/system/ports?protocol=tcp&user=root&http_only=true " \
-H " Authorization: Bearer <token> "
for await ( const port of client . terminal . system . listPortsIterator ({
"program" : " hoody-server " ,
Returns a JSON array of all processes with CPU, memory, and state information. Supports sorting, filtering, and limiting.
Name In Type Required Description sortquery string No Sort by field. Allowed values: 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://api.hoody.com/api/v1/system/processes?sort=cpu&limit=10 " \
-H " Authorization: Bearer <token> "
for await ( const proc of client . terminal . system . listProcessesIterator ({
"memory_bytes" : 2030043136 ,
"command" : " /usr/local/bin/hoody-server --config /etc/hoody/server.yml "
"memory_bytes" : 704643072 ,
"command" : " python3 /opt/hoody/inference/worker.py "
Returns detailed information about a specific process including all stats, command line, environment, and open files.
Name In Type Required Description pidpath integer Yes Process ID
curl -X GET https://api.hoody.com/api/v1/system/processes/4127 \
-H " Authorization: Bearer <token> "
const proc = await client . terminal . system . getProcess ( { pid: 4127 } );
"memory_bytes" : 2030043136 ,
"start_time" : " 2025-01-14T03:11:42Z " ,
"cmdline" : [ " /usr/local/bin/hoody-server " , " --config " , " /etc/hoody/server.yml " ],
"PATH" : " /usr/local/bin:/usr/bin:/bin " ,
"HOODY_HOME" : " /var/lib/hoody "
" /var/log/hoody/server.log "
"error" : " PROCESS_NOT_FOUND " ,
"message" : " No process with PID 99999 "
Error Code Title Description Resolution PROCESS_NOT_FOUNDProcess does not exist Check PID is valid and process is running Check PID is valid and process is running
Send a Unix signal to one or more processes by PID or name. Supports all standard signals (SIGTERM, SIGKILL, SIGSTOP, SIGCONT, etc.). When targeting by name, the signal is delivered to every matching process.
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 | 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
You must supply either pid or name (not both) and either signal or force.
curl -X POST https://api.hoody.com/api/v1/system/process/signal \
-H " Authorization: Bearer <token> " \
-H " Content-Type: application/json " \
await client . terminal . system . sendSignal ({
"error" : " MISSING_TARGET " ,
"message" : " Must specify pid or name "
Error Code Title Description Resolution MISSING_TARGETMust specify pid or name Provide either pid or name parameter Provide either pid or name parameter INVALID_SIGNALInvalid signal name Use valid signal (SIGTERM, SIGKILL, etc.) Use valid signal (SIGTERM, SIGKILL, etc.)
"error" : " PERMISSION_DENIED " ,
"message" : " No permission to signal process "
Error Code Title Description Resolution PERMISSION_DENIEDNo permission to signal process Check process ownership Check process ownership
"error" : " method_not_allowed " ,
"message" : " POST required "
"error" : " SIGNAL_FAILED " ,
"message" : " Failed to send signal "
Error Code Title Description Resolution SIGNAL_FAILEDFailed to send signal Check process exists Check process exists
The freeze and unfreeze endpoints let you suspend and resume processes (or whole process trees) without losing in-memory state. They are useful for pausing background workloads such as builds, fine-tunes, or AI inference.
Caution
The kernel enforces permissions: non-root callers can only freeze/unfreeze processes owned by their own UID (EPERM otherwise).
PIDs 1 (init), 2 (kthreadd), the server’s own PID, and the server’s parent PID are guarded and return 403 — freezing them would wedge the host or the daemon.
Linux truncates comm to TASK_COMM_LEN-1 = 15 characters . A name longer than 15 characters silently matches nothing.
The pid and name selectors are mutually exclusive — supply exactly one.
Operations are best-effort, not atomic. When include_descendants is true, descendants are enumerated from a one-shot /proc PPID snapshot (bounded at 65535 PIDs) and the parent is signalled first to shrink the fork/escape race window.
Suspend execution of one or more processes by delivering SIGSTOP. Pair this with /api/v1/system/processes/unfreeze (SIGCONT) to resume.
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 rejected with 403 namestring No Process name (case-insensitive comm match — freezes every matching process). Mutually exclusive with pid. Truncated to 15 characters by the kernel include_descendantsboolean No When 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/escape race window. With descendants, by-name dedupes overlapping subtrees so the same PID isn’t signalled twice
curl -X POST https://api.hoody.com/api/v1/system/processes/freeze \
-H " Authorization: Bearer <token> " \
-H " Content-Type: application/json " \
"include_descendants": true
await client . terminal . system . freezeProcess ({
include_descendants: true
"include_descendants" : true
"error" : " MISSING_TARGET " ,
"message" : " Must specify pid or name "
Error Code Title Description Resolution MISSING_TARGETMust specify pid or name Provide either pid or name parameter Provide either pid or name parameter INVALID_PIDpid must be a positive integer within int range pid must be a positive integer within int range Contact support
"error" : " PERMISSION_DENIED " ,
"message" : " PID 1 is guarded or kernel returned EPERM "
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 the kernel returned EPERM (different UID) or the PID is in the guarded set (init/kthreadd/self/parent)
"error" : " PROCESS_NOT_FOUND " ,
"message" : " No process matching pid/name "
Error Code Title Description Resolution PROCESS_NOT_FOUNDNo process matching pid/name No process matching pid/name Contact support
"error" : " method_not_allowed " ,
"message" : " POST required "
"error" : " FREEZE_FAILED " ,
"message" : " Failed to freeze process "
Error Code Title Description Resolution FREEZE_FAILEDFailed to freeze process Check process exists Check process exists PROC_SNAPSHOT_OOM/proc snapshot exhausted memory; transient /proc snapshot exhausted memory; transient Contact support PROC_TABLE_TOO_LARGE/proc PID table exceeds HT_PID_TABLE_MAX (65535) /proc PID table exceeds HT_PID_TABLE_MAX (65535) Contact support
Resume execution of one or more previously-stopped processes by delivering SIGCONT. The body schema mirrors /freeze exactly. 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) is the same as for freeze namestring No Process name (case-insensitive comm match). Mutually exclusive with pid. Truncated to 15 characters by the kernel include_descendantsboolean No Also unfreeze all descendants via /proc PPID snapshot (bounded at 65535 PIDs). Default: false. By-name dedupes overlapping subtrees
curl -X POST https://api.hoody.com/api/v1/system/processes/unfreeze \
-H " Authorization: Bearer <token> " \
-H " Content-Type: application/json " \
"include_descendants": true
await client . terminal . system . unfreezeProcess ({
include_descendants: true
"include_descendants" : true
"error" : " MISSING_TARGET " ,
"message" : " Must specify pid or name "
Error Code Title Description Resolution MISSING_TARGETMust specify pid or name Provide either pid or name parameter Provide either pid or name parameter INVALID_PIDpid must be a positive integer within int range pid must be a positive integer within int range Contact support
"error" : " PERMISSION_DENIED " ,
"message" : " PID 1 is guarded or kernel returned EPERM "
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 the kernel returned EPERM (different UID) or the PID is in the guarded set (init/kthreadd/self/parent)
"error" : " PROCESS_NOT_FOUND " ,
"message" : " No process matching pid/name "
Error Code Title Description Resolution PROCESS_NOT_FOUNDNo process matching pid/name No process matching pid/name Contact support
"error" : " method_not_allowed " ,
"message" : " POST required "
"error" : " UNFREEZE_FAILED " ,
"message" : " Failed to unfreeze process "
Error Code Title Description Resolution UNFREEZE_FAILEDFailed to unfreeze process Check process exists Check process exists PROC_SNAPSHOT_OOM/proc snapshot exhausted memory; transient /proc snapshot exhausted memory; transient Contact support PROC_TABLE_TOO_LARGE/proc PID table exceeds HT_PID_TABLE_MAX (65535) /proc PID table exceeds HT_PID_TABLE_MAX (65535) Contact support
Initiate a system reboot with optional delay. Requires root/sudo permissions — the Linux kernel enforces the check.
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.
Name In Type Required Description delayquery integer No Delay in seconds before reboot, 0..86400 (default: 0 for immediate). The server rounds up to the nearest whole minute
curl -X POST " https://api.hoody.com/api/v1/system/reboot?delay=60 " \
-H " Authorization: Bearer <token> "
await client . terminal . system . reboot ({ delay: 60 });
"message" : " Delay out of range (> 86400) "
"error" : " ROOT_REQUIRED " ,
"message" : " Reboot requires root privileges "
Error Code Title Description Resolution ROOT_REQUIREDReboot requires root privileges Run with sudo or as root user Run with sudo or as root user
"error" : " method_not_allowed " ,
"message" : " POST required "
"error" : " REBOOT_FAILED " ,
"message" : " Failed to execute reboot "
Error Code Title Description Resolution REBOOT_FAILEDFailed to execute reboot Check system logs Check system logs
Initiate a system shutdown with optional delay. Requires root/sudo permissions — the Linux kernel enforces the check.
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.
Name In Type Required Description delayquery integer No Delay in seconds before shutdown, 0..86400 (default: 0 for immediate). The server rounds up to the nearest whole minute
curl -X POST " https://api.hoody.com/api/v1/system/shutdown?delay=120 " \
-H " Authorization: Bearer <token> "
await client . terminal . system . shutdown ({ delay: 120 });
"message" : " Delay out of range (> 86400) "
"error" : " ROOT_REQUIRED " ,
"message" : " Shutdown requires root privileges "
Error Code Title Description Resolution ROOT_REQUIREDShutdown requires root privileges Run with sudo or as root user Run with sudo or as root user
"error" : " method_not_allowed " ,
"message" : " POST required "
"error" : " SHUTDOWN_FAILED " ,
"message" : " Failed to execute shutdown "
Error Code Title Description Resolution SHUTDOWN_FAILEDFailed to execute shutdown Check system logs Check system logs