A top-like tool for containers that displays resource usage based on cgroup limits, not the host's resources.
Traditional monitoring tools like top or htop, when run inside a container, report resource usage as a percentage of the host machine's total resources. When working in containerized environments like Kubernetes Pods, it is hard to monitor the resource usage from inside the container.
For example, a container with a 2GB memory limit on a 128GB host may be using 1.8GB of RAM. While htop would show a negligible system-wide usage, the container is actually at 90% of its capacity and is dangerously close to being OOMKilled with no warning.
topic (top inside a container) is a simple terminal-based monitoring tool that solves this problem. It reads the container's resource limits directly from the cgroup filesystem and calculates all usage percentages based on those limits.
This provides an accurate view of how close a container is to its resource boundaries, without the need to access the host or external monitoring tools.
The screenshot is captured inside a demo container limited to 2 CPUs, 2 GiB of memory, and 256 PIDs, with a synthetic CUDA workload using an attached GPU.
The system panel adapts to the terminal width. Wide terminals use two aligned resource columns; narrower terminals switch to one column and truncate secondary details before hiding primary measurements.
- CPU, memory, storage, and GPU rows share the same label, percentage, bar, and detail alignment.
- Network and disk throughput, PID usage, cgroup pressure, and metric history use a shared label gutter for quick scanning.
- Utilization is green below 70%, gold from 70% to 89.9%, and red at 90% or above.
- Docker, Kubernetes, and NVIDIA/NVML availability is shown in the compact status panel. Missing integrations remain non-fatal.
- CPU: when the cgroup sets a CPU limit that differs from the host core count, usage is a percentage of that limit. Otherwise
topicshows host CPU usage. Container CPU is calculated from the change between two readings, so the first refresh shows 0%. - Memory: usage is the working set, which is memory in use minus the inactive file cache the kernel can reclaim, the same measure
kubectl topreports. It is shown as a percentage of the cgroup memory limit. With no limit (maxon cgroup v2, or the near-maximum value cgroup v1 uses for "unlimited"),topicshows host memory instead. - Processes:
%CPUis usage since the previous refresh as a percentage of the CPU limit, so a process shows 0 on its first refresh.%MEMis resident memory as a percentage of the memory limit, or of host memory when there is no limit.%GPUMEMis the GPU memory a process uses as a percentage of its GPU's total memory. The static build reads%GPUand%GPUMEMwithnvidia-smi pmon, which is costly to start, so it updates them at most every 3 seconds; the NVML build updates them every refresh. - Storage: virtual filesystems, system mounts such as
/dev,/proc,/run, and/tmp, and single files bind-mounted into the container, such as/etc/hosts, are hidden. Mount paths are compared by whole path segment, so a disk mounted at/developerstays visible. - GPU: GPUs are labelled by their
nvidia-smiindex. If a GPU does not report its total memory, its memory row shows the amount used at 0%. - Docker and Kubernetes: container IDs are read from the cgroup paths used by cgroupfs and systemd drivers, including
docker-<id>.scope,cri-containerd-<id>.scope,crio-<id>.scope, andlibpod-<id>.scope.
You can install the latest version of topic with a single command. The script will automatically detect your system's architecture (amd64/arm64) and install the binary to a directory in your PATH.
curl -s https://raw.githubusercontent.com/yurirocha15/topic/main/install.sh | bashor for containers based on alpine:
wget -qO- https://raw.githubusercontent.com/yurirocha15/topic/main/install.sh | shOn a machine with an NVIDIA driver and glibc, the script installs the NVML build (topic-linux-<arch>-nvml), which reads GPU usage directly from the driver library and uses about half the CPU of the static build. Everywhere else, including Alpine, it installs the static build (topic-linux-<arch>), which runs in any Linux container. To always install the static build, run the script with TOPIC_BUILD=static, as in curl -s https://raw.githubusercontent.com/yurirocha15/topic/main/install.sh | TOPIC_BUILD=static bash.
The script will attempt to install to /usr/local/bin (prompting for sudo if needed). If that fails, it will fall back to $HOME/.local/bin and notify you if you need to add this directory to your PATH.
The script checks the download against the release's SHA256SUMS file. To confirm that a binary was built by this repository's release workflow, verify its attestation with the GitHub CLI:
gh attestation verify topic-linux-amd64 --repo yurirocha15/topicAfter installation, simply run the command:
topicCommon options:
topic --refresh=2s # change refresh interval
topic --no-gpu # disable GPU collection
topic --no-docker # disable Docker metadata lookup
topic --no-kubernetes # disable Kubernetes metadata lookup
topic --no-nvml # read GPU usage with nvidia-smi instead of NVML
topic --ascii # start with the large ASCII logo visible
topic --once # print one text snapshot and exit
topic --once --json # print one JSON snapshot for scripts
topic --sort=mem # initial sort: cpu, mem, gpu, gpumem, pid, user, command
topic --version # print the version and exit--once and --json take two readings 250 ms apart, so CPU, network, and disk rates are measured over that window.
Press ? in topic to see the same list. Once you pick a process, the highlight follows it when the list re-sorts, and Enter and k act on the PID shown in the highlighted row.
| Where | Keys | Action |
|---|---|---|
| General | q / Ctrl+C |
quit |
| General | ? |
show or close the key help |
| General | p |
pause or resume refreshing |
| General | a |
show or hide the logo |
| Process table | ↑↓ PgUp PgDn Home End |
move the highlight (or click a row) |
| Process table | ← → |
scroll the table sideways |
| Process table | Enter |
details of the highlighted process |
| Process table | k |
signal the highlighted process |
| Process table | / |
filter by command, user, or PID |
| Process table | s |
choose the sort column and direction |
| Process table | r |
reverse the sort |
| Process table | t |
show or hide the process tree |
| Filter mode | Backspace |
delete the last character |
| Filter mode | Ctrl+U |
clear the filter |
| Filter mode | Enter / Esc |
stop typing and keep the filter |
| Sort mode | ← → |
choose the sort column |
| Sort mode | ↓ / ↑ |
sort high to low / low to high |
| Sort mode | Enter / Esc |
leave sort mode |
| Dialogs | ← → / Tab |
choose a button (starts on Cancel) |
| Dialogs | Enter |
press the chosen button |
| Dialogs | Esc / q |
close the dialog |
If you prefer to build the project yourself, you will need:
- Go (version 1.26 or later)
make
Clone the repository and run the build command:
git clone https://github.com/yurirocha15/topic.git
cd topic
make buildThe compiled binary will be available at ./dist/topic.
Contributions are welcome! If you find a bug or have a feature request, please open an issue on the GitHub Issues page. See CONTRIBUTING.md for how to test the project.
This project is licensed under the MIT License.

