jason 4c59716610
Build Debian Packages / Build .deb for x86_64-unknown-linux-gnu (push) Has been cancelled
Build Debian Packages / Build .deb for aarch64-unknown-linux-gnu (push) Has been cancelled
Build Debian Packages / Build .deb for armv7-unknown-linux-gnueabihf (push) Has been cancelled
Build Debian Packages / Build .deb for riscv64gc-unknown-linux-gnu (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
Build Debian Packages / Combine all .deb packages (push) Has been cancelled
Build Debian Packages / Publish to APT Repository (push) Has been cancelled
Build Debian Packages / Create GitHub Release (push) Has been cancelled
Kill a local process from the TUI, and stop the agent reporting dead ones (#40)
* fix(agent): drop processes that no longer exist

`refresh_processes_specifics` was called with remove_dead_processes = false
against a long-lived System, so the agent accumulated every process it had
ever seen and went on reporting them. Measured on a Pi 5 after a few hours of
build churn: 21,648 processes reported, 289 actually running, growing a few
every poll.

Three consequences, in ascending order of how confusing they are:

  * unbounded memory growth, and every poll iterating ~75x more entries than
    it should
  * process_count — the client's "Top Processes (N total)" — is meaningless
  * a process you kill keeps its row forever, because the agent keeps sending
    it. Killing it again reports "no longer exists", since the kernel is
    telling the truth and the agent is not.

The third is how this was found: no amount of client-side reconciliation could
fix a list whose producer never forgets anything.

Passing `true` is only correct because these two sites use
ProcessesToUpdate::All. With `Some(pids)` sysinfo treats every process outside
the list as dead and removes it, so the per-PID refresh in
collect_process_metrics must keep `false` — noted in a comment there.

Verified by driving the TUI against a rebuilt agent: reported count 292 vs 290
real, and a killed row is removed once and never reappears.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat(socktop): kill a local process from the TUI

btop-style process termination, for local agents only. The signal is sent by
socktop itself through a direct sysinfo call — nothing is transmitted to the
agent, and the agent and connector have no kill capability at all.

Why local-only: the PIDs on screen are reported by the agent, and the signal is
sent with socktop's own OS privileges. A PID is therefore only meaningful, and
only safe to act on, when the agent lives on this machine; acting on a remote
agent's PIDs would signal whatever unrelated local process happened to share
that number. local::agent_is_local treats an address as local when it is
loopback or when an ephemeral bind succeeds (which only works for an address on
one of our own interfaces, so it also covers reaching our own agent by LAN IP),
requires every address a hostname resolves to to be local, and fails closed.

  * `t` on the selected process, and `t` inside Process Details. One key for
    both: `k` scrolls the thread table in the modal, so it could not be reused
    there.
  * The confirmation offers Terminate (focused first, so a reflexive Enter is
    the safe one), Force kill, and Cancel. Keeping SIGKILL behind a second
    button rather than a second keybinding means the destructive option has to
    be chosen deliberately.
  * The selection hint gained the key, but only for a local agent — advertising
    a key that deliberately does nothing is worse than no hint. Same for the
    details modal's help line.

The list is reconciled after a signal rather than left to the next poll. A
signalled PID goes on a watch list re-checked each metrics tick, because SIGTERM
is a request: the process is usually still alive at signal time, and its row
should go when it actually exits (or stay, if it ignores the signal). PIDs
confirmed gone are remembered briefly, since the agent serves Processes from a
1500ms cache and would otherwise hand back a pre-kill snapshot. A selection
whose process has left the list is dropped, and the details view closes for a
process that no longer exists — including when it dies on its own, which
previously flipped that modal to "Agent Update Required" because the wire cannot
distinguish "no such PID" from "endpoint unsupported".

Also fixes two pre-existing UI faults found on the way:

  * The selection hint was sized from its full label including the process name
    and skipped entirely when that exceeded the pane width — so it vanished
    exactly when a long-named process was selected. The name is now the elastic
    part, and widths are measured in columns rather than bytes.
  * Confirmation and Info dialogs laid their content out over the whole modal
    rect instead of the block's inner rect, putting the first line of text on
    the border row, and fell into the catch-all 70%x50% sizing arm, so a
    one-line question got half the screen. They now size to their content and
    use the theme's colors like the connection-error modal does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(kill): close stacked details view, guard PID reuse, scale settle with interval

Review fixes for the process-kill feature:

1. Killing from INSIDE the details view left it open forever, frozen on
   the dead process (reproduced live): the 'Signal sent' Info modal sits
   on top when the death is confirmed on the next tick, the old top-only
   close_process_details missed it, gone-PIDs are processed once, and the
   details-poll fallback was gated on the selection the kill had just
   cleared. The close now removes the dead PID's view wherever it sits in
   the stack — which also retires a dead parent's view from under a child
   in a navigation chain, so backing out lands on the process list rather
   than a frozen corpse view. Tests updated to the new semantics, plus a
   regression test for the Info-stacked case.

2. PID-reuse guard: the PID comes from an agent snapshot and the
   confirmation can sit open indefinitely, so by signal time the kernel
   may have recycled the number. kill_local_process now takes the name
   the user confirmed and refuses to signal a PID whose current owner
   does not match ('PID N now belongs to X, not Y').

3. A transient request error no longer closes the details view: with
   process_details_answered set, any Err was read as 'process gone',
   including socket blips. The view now closes only when the PID is also
   absent from the agent's own process list.

4. PROC_CACHE_SETTLE scales with the user's processes interval (floor at
   the old 1.6s default-TTL value), and the tombstone lifetime rides on
   top of it — users who raise the agent's Processes TTL raise the client
   interval to match, so the interval is the best client-side signal for
   how stale an agent snapshot can be.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(kill): resume polling for the details view that resurfaces from a chain

Reported: kill still orphaned a window via Enter (child details) -> P
(parent details) -> t (terminate parent). The parent's view closed
correctly, but the child's view underneath resurfaced with no selection
(forget_process_row had cleared it — it pointed at the parent) and wiped
data; the selection-gated details poll never refilled it.

close_details_for_gone_process now retargets the selection to the
uppermost remaining ProcessDetails view (looking through stacked
Info/Confirmation modals) and makes the poll due immediately — the same
retarget SwitchToParentProcess performs on the way down the chain.

Same class of hole in plain navigation, fixed alongside: Esc-ing back
from a parent view left the selection on the PARENT, so the resurfaced
child-titled view refilled with the parent's data. The dismiss arm now
retargets the selection to whatever details view it lands on.

Both verified live: child -> P -> kill parent -> child view resurfaces
populated and updating; child -> P -> Esc -> child view shows the child.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: changelog section for the process-kill feature and agent dead-process fix

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 08:11:17 -07:00
2025-08-19 23:24:36 -07:00
2025-09-03 23:10:48 -07:00

socktop

socktop is a remote system monitor with a rich TUI, inspired by top/btop, talking to a lightweight agent over WebSockets.

  • Linux agent: near-zero CPU when idle (request-driven, no always-on sampler)
  • TUI: smooth graphs, sortable process table, scrollbars, readable colors

socktop.io


Features

  • Remote monitoring via WebSocket (JSON over WS)
  • Optional WSS (TLS): agent autogenerates a selfsigned cert on first run; client pins the cert via --tls-ca/-t
  • TUI built with ratatui
  • CPU
    • Overall sparkline + per-core mini bars
    • Accurate per-process CPU% (Linux /proc deltas), normalized to 0100%
  • Memory/Swap gauges with human units
  • Disks: per-device usage
  • Network: per-interface throughput with sparklines and peak markers
  • Temperatures: CPU (optional)
  • Top processes (top 50)
    • PID, name, CPU%, memory, and memory%
    • Click-to-sort by CPU% or Mem (descending)
    • Scrollbar and mouse/keyboard scrolling
    • Total process count shown in the header
    • Only top-level processes listed (threads hidden) — matches btop/top
  • Optional GPU metrics (can be disabled)
  • Optional auth token for the agent
  • Compact layout for small windows: automatically drops the panes that no longer fit so the CPU graph and per-core bars stay visible (see Compact mode)

Prerequisites: Install Rust (rustup)

Rust is fast, safe, and crossplatform. Installing it will make your machine better. Consider yourself privileged.

Linux/macOS:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# load cargo for this shell
source "$HOME/.cargo/env"
# ensure stable is up to date
rustup update stable
rustc --version
cargo --version
# after install you may need to reload your shell, e.g.:
exec bash   # or: exec zsh / exec fish

Windows (for the brave): install from https://rustup.rs with the MSVC toolchain. Yes, youll need Visual Studio Build Tools. You chose Windows — enjoy the ride.

Raspberry Pi / Ubuntu / PopOS (required for GPU support)

Note: GPU monitoring is only supported on x86_64 and aarch64 (64-bit ARM) platforms. ARMv7 (32-bit) and RISC-V builds do not include GPU support.

For 64-bit systems with GPU support:

sudo apt-get update
sudo apt-get install libdrm-dev libdrm-amdgpu1

For ARMv7 (32-bit Raspberry Pi), build with --no-default-features to disable GPU support:

cargo build --release -p socktop_agent --no-default-features

Additional note for Raspberry Pi users. Please update your system to use the newest kernel available through app, kernel version 6.6+ will use considerably less overall CPU to run the agent. For example on a rpi4 the kernel < 6.6 the agent will consume .8 cpu but on the same hardware on > 6.6 the agent will consume only .2 cpu. (these numbers indicate continuous polling at web socket endpoints, when not in use the usage is 0)


Architecture

Two components:

  1. Agent (remote): small Rust WS server using sysinfo + /proc. It collects metrics only when the client requests them over the WebSocket (request-driven). No background sampling loop.

  2. Client (local): TUI that connects to ws://HOST:PORT/ws (or wss://HOST:PORT/ws when TLS is enabled) and renders updates.


Quick start

  • Build both binaries:
git clone https://github.com/jasonwitty/socktop.git
cd socktop
cargo build --release
  • Start the agent on the target machine (default port 3000):
./target/release/socktop_agent --port 3000
  • Connect with the TUI from your local machine:
./target/release/socktop ws://REMOTE_HOST:3000/ws

Cross-compiling for Raspberry Pi

For Raspberry Pi and other ARM devices, you can cross-compile the agent from a more powerful machine:

Quick demo (no agent setup)

Spin up a temporary local agent on port 3231 and connect automatically:

socktop --demo

Or just run socktop with no arguments and pick the builtin demo entry from the interactive profile list (if you have saved profiles, demo is appended). The demo agent:

  • Runs locally (ws://127.0.0.1:3231/ws)
  • Stops automatically (you'll see "Stopped demo agent on port 3231") when you quit the TUI or press Ctrl-C

Install (from crates.io)

You dont need to clone this repo to use socktop. Install the published binaries with cargo:

# TUI (client)
cargo install socktop
# Agent (server)
cargo install socktop_agent

This drops socktop and socktop_agent into ~/.cargo/bin (add it to PATH).

Notes:

  • After installing Rust via rustup, reload your shell (e.g., exec bash) so cargo is on PATH.
  • Windows: you can also grab prebuilt EXEs from GitHub Actions artifacts if rustup scares you. It shouldnt. Be brave.

System-wide agent (Linux)

# If you installed with cargo, binaries are in ~/.cargo/bin
sudo install -o root -g root -m 0755 "$HOME/.cargo/bin/socktop_agent" /usr/local/bin/socktop_agent

# Install and enable the systemd service (example unit in docs/)
sudo install -o root -g root -m 0644 docs/socktop-agent.service /etc/systemd/system/socktop-agent.service
sudo systemctl daemon-reload
sudo systemctl enable --now socktop-agent

# Enable SSL

# Stop service
sudo systemctl stop socktop-agent

# Edit service to append SSL option and port
sudo micro /etc/systemd/system/socktop-agent.service

--
ExecStart=/usr/local/bin/socktop_agent --enableSSL --port 8443
--

# Reload
sudo systemctl daemon-reload

# Restart
sudo systemctl start socktop-agent

# check logs for certificate location
sudo journalctl -u socktop-agent -f

--
Aug 22 22:25:26 rpi-master socktop_agent[2913998]: socktop_agent: generated self-signed TLS certificate at /var/lib/socktop/.config/socktop_agent/tls/cert.pem
--


Usage

Agent (server):

socktop_agent --port 3000
# or env: SOCKTOP_PORT=3000 socktop_agent
# optional auth: SOCKTOP_TOKEN=changeme socktop_agent
# enable TLS (selfsigned cert, default port 8443; you can also use -p):
socktop_agent --enableSSL --port 8443

Client (TUI):

socktop ws://HOST:3000/ws
# with token:
socktop "ws://HOST:3000/ws?token=changeme"
# TLS with pinned server certificate (recommended over the internet):
socktop --tls-ca /path/to/cert.pem wss://HOST:8443/ws
# (By default hostname/SAN verification is skipped for ease on home networks. To enforce it add --verify-hostname)
socktop --verify-hostname --tls-ca /path/to/cert.pem wss://HOST:8443/ws
# shorthand:
socktop -t /path/to/cert.pem wss://HOST:8443/ws
# Note: providing --tls-ca/-t automatically upgrades ws:// to wss:// if you forget
# force the small-window layout at any terminal size (normally automatic):
socktop --compact ws://HOST:3000/ws

Intervals (client-driven):

  • Fast metrics: ~500 ms
  • Processes: ~2 s
  • Disks: ~5 s

The agent stays idle unless queried. When queried, it collects just whats needed.


Compact mode

In a short terminal the fixed layout runs out of rows and the CPU graph and per-core bars are the first things to collapse — exactly the panes you are most likely watching. Once the window is too short for the Disks pane to show even one disk, socktop switches to a compact layout:

  • Disks is dropped. It is the pane that degrades worst when partially drawn.
  • Memory and Swap move side by side into the row Disks vacated.
  • GPU shrinks to a single line — utilisation and VRAM only, no device name. On a host with no GPU the pane disappears entirely.
  • Everything reclaimed goes to the CPU graph and per-core bars, which stay usable well below the size where they used to vanish.

The switch is automatic and needs no configuration. Pass --compact to pin the compact layout at any window size:

socktop --compact ws://HOST:3000/ws

Connection Profiles (Named)

You can save frequently used connection settings (URL + optional TLS CA path) under a short name and reuse them later.

Config file location:

  • Linux (XDG): $XDG_CONFIG_HOME/socktop/profiles.json
  • Fallback (when XDG not set): ~/.config/socktop/profiles.json

Creating a profile

First time you specify a new --profile/-P name together with a URL (and optional --tls-ca), it is saved automatically:

socktop --profile prod ws://prod-host:3000/ws
# With TLS pinning:
socktop --profile prod-tls --tls-ca /path/to/cert.pem wss://prod-host:8443/ws

You can also set custom intervals (milliseconds):

```bash
socktop --profile prod --metrics-interval-ms 750 --processes-interval-ms 3000 ws://prod-host:3000/ws

If a profile already exists you will be prompted before overwriting:

$ socktop --profile prod ws://new-host:3000/ws Overwrite existing profile 'prod'? [y/N]: y


To overwrite without an interactive prompt pass `--save`:

```bash
socktop --profile prod --save ws://new-host:3000/ws

Using a saved profile

Just pass the profile name (no URL needed):

socktop --profile prod
socktop -P prod-tls      # short flag

The stored URL (and TLS CA path, if any) plus any saved intervals will be used. TLS auto-upgrade still applies if a CA path is stored alongside a ws:// URL.

Interactive selection (no args)

If you run socktop with no arguments and at least one profile exists, you will be shown a numbered list to pick from:

$ socktop
Select profile:
  1. prod
  2. prod-tls
Enter number (or blank to abort): 2

Choosing a number starts the TUI with that profile. A builtin demo option is always appended; selecting it launches a local agent on port 3231 (no TLS) and connects to ws://127.0.0.1:3231/ws. Pressing Enter on blank aborts without connecting.

JSON format

An example profiles.json (prettyprinted):

{
  "profiles": {
    "prod": { "url": "ws://prod-host:3000/ws" },
    "prod-tls": {
      "url": "wss://prod-host:8443/ws",
      "tls_ca": "/home/user/certs/prod-cert.pem",
      "metrics_interval_ms": 500,
      "processes_interval_ms": 2000
    }
  },
  "version": 0
}

Notes:

  • The tls_ca path is stored as given; if you move or rotate the certificate update the profile by re-running with --profile NAME --save.
  • Deleting a profile: edit the JSON file and remove the entry (TUI does not yet have an in-app delete command).
  • Profiles are client-side convenience only; they do not affect the agent.
  • Intervals: metrics_interval_ms controls the fast metrics poll (default 500 ms). processes_interval_ms controls process list polling (default 2000 ms). Values below 100 ms (metrics) or 200 ms (processes) are clamped.

Updating

Update the agent (systemd):

# on the server running the agent
cargo install socktop_agent --force
sudo systemctl stop socktop-agent
sudo install -o root -g root -m 0755 "$HOME/.cargo/bin/socktop_agent" /usr/local/bin/socktop_agent
# if you changed the unit file:
# sudo install -o root -g root -m 0644 docs/socktop-agent.service /etc/systemd/system/socktop-agent.service
# sudo systemctl daemon-reload
sudo systemctl start socktop-agent
sudo systemctl status socktop-agent --no-pager
# logs:
# journalctl -u socktop-agent -f

Update the TUI (client):

cargo install socktop --force
socktop ws://HOST:3000/ws

Tip: If only the binary changed, restart is enough. If the unit file changed, run sudo systemctl daemon-reload.


Configuration (agent)

  • Port:
    • Flag: --port 8080 or -p 8080
    • Positional: socktop_agent 8080
    • Env: SOCKTOP_PORT=8080
  • TLS (selfsigned):
    • Enable: --enableSSL
    • Default TLS port: 8443 (override with --port/-p)
    • Certificate/Key location (created on first TLS run):
      • Linux (XDG): $XDG_CONFIG_HOME/socktop_agent/tls/{cert.pem,key.pem} (defaults to ~/.config)
      • The agent prints these paths on creation.
    • You can set XDG_CONFIG_HOME before first run to control where certs are written.
    • Additional SANs: set SOCKTOP_AGENT_EXTRA_SANS (commaseparated) before first TLS start to include extra IPs/DNS names in the cert. Example:
      SOCKTOP_AGENT_EXTRA_SANS="192.168.1.101,myhost.internal" socktop_agent --enableSSL
      
      This prevents client errors like NotValidForName when connecting via an IP not present in the default cert SAN list.
    • Expiry / rotation: the generated cert is valid for ~397 days from creation. If the agent fails to start with an "ExpiredCertificate" error (or your client reports expiry), simply delete the existing cert and key:
      rm ~/.config/socktop_agent/tls/cert.pem ~/.config/socktop_agent/tls/key.pem
      # (adjust path if XDG_CONFIG_HOME is set or different user)
      systemctl restart socktop-agent   # if running under systemd
      
      On next TLS start the agent will generate a fresh pair. Only distribute the new cert.pem to clients (never the key).
  • Auth token (optional): SOCKTOP_TOKEN=changeme
  • Disable GPU metrics: SOCKTOP_AGENT_GPU=0
  • Disable CPU temperature: SOCKTOP_AGENT_TEMP=0

Keyboard & Mouse

  • Quit: q or Esc
  • Processes pane:
    • Click “CPU %” to sort by CPU descending
    • Click “Mem” to sort by memory descending
    • Mouse wheel: scroll
    • Drag scrollbar: scroll
    • Arrow/PageUp/PageDown/Home/End: scroll

Example agent JSON

{
  "sampled_at_ms": 1786752000123,
  "cpu_total": 12.4,
  "cpu_per_core": [11.2, 15.7],
  "mem_total": 33554432,
  "mem_used": 18321408,
  "swap_total": 0,
  "swap_used": 0,
  "process_count": 127,
  "hostname": "myserver",
  "cpu_temp_c": 42.5,
  "disks": [{"name":"nvme0n1p2","total":512000000000,"available":320000000000}],
  "networks": [{"name":"eth0","received":12345678,"transmitted":87654321}],
  "top_processes": [
    {"pid":1234,"name":"nginx","cpu_usage":1.2,"mem_bytes":12345678}
  ],
  "gpus": null
}

Notes:

  • process_count is merged into the main metrics on the client when processes are polled.
  • top_processes are the current top 50 (sorting in the TUI is client-side).

Security

Set a token on the agent and pass it as a query param from the client:

Server:

SOCKTOP_TOKEN=changeme socktop_agent --port 3000

Client:

socktop "ws://HOST:3000/ws?token=changeme"

TLS / WSS

For encrypted connections, enable TLS on the agent and pin the server certificate on the client.

Server (generates selfsigned cert and key on first run):

socktop_agent --enableSSL --port 8443

Client (trust/pin the server cert; copy cert.pem from the agent):

socktop --tls-ca /path/to/agent/cert.pem wss://HOST:8443/ws

Notes:

  • Do not copy the private key off the server; only the cert.pem is needed by clients.
  • When --tls-ca/-t is supplied, the client autoupgrades ws:// to wss:// to avoid protocol mismatch.
  • Hostname (SAN) verification is DISABLED by default; instead the client PINS the certificate: the agent must present a cert byte-identical to one in your --tls-ca file (expiry is ignored in this mode — you pinned that exact cert). Use --verify-hostname to switch to strict chain + SAN validation instead.
  • You can run multiple clients with different cert paths by passing --tls-ca per invocation.

Using tmux to monitor multiple hosts

You can use tmux to show multiple socktop instances in a single terminal.

socktop screenshot monitoring 4 Raspberry Pis using Tmux

Prerequisites:

  • Install tmux (Ubuntu/Debian: sudo apt-get install tmux)

Key bindings (defaults):

  • Split left/right: Ctrl-b %
  • Split top/bottom: Ctrl-b "
  • Move between panes: Ctrl-b + Arrow keys
  • Show pane numbers: Ctrl-b q
  • Close a pane: Ctrl-b x
  • Detach from session: Ctrl-b d

Two panes (left/right)

  • This creates a session named "socktop", splits it horizontally, and starts two socktops.
tmux new-session -d -s socktop 'socktop ws://HOST1:3000/ws' \; \
  split-window -h 'socktop ws://HOST2:3000/ws' \; \
  select-layout even-horizontal \; \
  attach

Four panes (top-left, top-right, bottom-left, bottom-right)

  • This creates a 2x2 grid with one socktop per pane.
tmux new-session -d -s socktop 'socktop ws://HOST1:3000/ws' \; \
  split-window -h 'socktop ws://HOST2:3000/ws' \; \
  select-pane -t 0 \; split-window -v 'socktop ws://HOST3:3000/ws' \; \
  select-pane -t 1 \; split-window -v 'socktop ws://HOST4:3000/ws' \; \
  select-layout tiled \; \
  attach

Tips:

  • Replace HOST1..HOST4 (and ports) with your targets.
  • Reattach later: tmux attach -t socktop

Platform notes

  • Linux: fully supported (agent and client).
  • Raspberry Pi:
    • 64-bit: aarch64-unknown-linux-gnu
    • 32-bit: armv7-unknown-linux-gnueabihf
  • Windows:
    • TUI + agent can build with stable Rust; bring your own MSVC. Youre on Windows; you know the drill.
    • CPU temperature may be unavailable.
    • binary exe for both available in build artifacts under actions.
  • macOS:
    • TUI works; agent is primarily targeted at Linux. Agent will run just fine on macos for debugging but I have not documented how to run as a service, I may not given the "security" feautures with applications on macos. We will see.

Development

cargo fmt
cargo clippy --all-targets --all-features
cargo run -p socktop -- ws://127.0.0.1:3000/ws
# TLS (dev): first run will create certs under ~/.config/socktop_agent/tls/
cargo run -p socktop_agent -- --enableSSL --port 8443

Auto-format on commit

A sample pre-commit hook that runs cargo fmt --all is provided in .githooks/pre-commit. Enable it (one-time):

git config core.hooksPath .githooks
chmod +x .githooks/pre-commit

Every commit will then format Rust sources and restage them automatically.


Roadmap

  • Agent authentication (token)
  • Hide per-thread entries; only show processes
  • Sort top processes in the TUI
  • Configurable refresh intervals (client)
  • Export metrics to file
  • TLS / WSS support (selfsigned server cert + client pinning)
  • Split processes/disks to separate WS calls with independent cadences (already logical on client; formalize API)
  • Outage notifications and reconnect.
  • Per process detailed statistics pane
  • cleanup of Disks section, properly display physical disks / partitions, remove duplicate entries

License

MIT — see LICENSE.


Acknowledgements

  • ratatui for the TUI
  • sysinfo for system metrics
  • tokio-tungstenite for WebSockets
S
Description
No description provided
Readme MIT 352 MiB
Languages
Rust 94.8%
Shell 3.1%
HTML 2.1%