Skip to main content

A btop-like Kubernetes TUI dashboard for pods, nodes, CPU, memory, events, PVC usage, alerts, and health checks.

Project description

kutop

Latest release PyPI version Wheel CI Release workflow Python kubectl Metrics Server License Issues Stars Last commit

kutop is a modern, like-btop Kubernetes TUI dashboard for the terminal. It turns kubectl and your kubeconfig into a fast, readable view of pods, nodes, namespaces, CPU, memory, restarts, OOMKilled pods, warning events, PVC storage, Alertmanager alerts, and custom health checks.

It is built with Textual and runs locally with no in-cluster agent. kutop is useful when you want a Kubernetes terminal dashboard, pod monitor, node resource view, k8s observability console, or a kubetop/ktop style CLI that feels closer to btop.

Highlights

  • Kubernetes pod and node monitoring directly in the terminal.
  • Live CPU and memory trend sparklines plus per-pod usage-vs-limit gauges.
  • Problem-first signals for Pending, Failed, OOMKilled, CrashLoopBackOff, and restarting workloads.
  • Optional Events, PVC storage, Alertmanager, health-check, and contextual Keys sidebar panels.
  • Multi-namespace views, sorting, filtering, grouping, and a configurable sidebar for fast cluster triage.
  • Profile-driven thresholds, pod ordering, timezone, alert sources, and health probes so the core stays generic.
  • Headless SVG screenshots for README assets, release notes, and visual QA.
NODES 2/2 │ PODS(R/P/F) 18/1/0 │ RESTARTS 7 │ OOM 1 │ WARN 2 │ ALERTS 3
CPU OVERALL  ▁▂▃▅▆▇█  62%  5.1/16        MEM OVERALL  ▃▄▅▆▇█  74%  47/64Gi
◆ worker-pool  node-a │
  ● api-0 (1/1)        ███████░░░ 70%   STS
  ● worker-9 OOMKilled (0/1)  █████████░ 95%   Deploy

Requirements

kutop is a local terminal app. It does not install an in-cluster agent; it uses your local kubectl and kubeconfig exactly as kubectl would.

Dependency Required version / contract Used for
Python 3.9+ running the installed kutop package
Textual / Rich textual==8.2.7, rich==15.0.0 terminal UI rendering
kubectl installed on PATH; use a client within +/- 1 minor version of your cluster's kube-apiserver all live cluster reads and actions
kubeconfig current context from ~/.kube/config, KUBECONFIG, or --context cluster auth and target selection
Metrics Server 0.6.x+ on Kubernetes 1.19+ recommended kubectl top CPU/MEM metrics

Live dashboard mode requires kubectl. kutop --self-test and kutop --dump-config are cluster-free and do not require kubectl.

CPU and memory values use kubectl top nodes and kubectl top pods --containers, then sum container rows so multi-container pods show pod-level usage. If container-level top is unavailable, kutop falls back to pod-level kubectl top pods.

On live startup, kutop checks kubectl top nodes plus the metrics.k8s.io discovery endpoint. If Metrics Server appears absent and the terminal is interactive, kutop asks before changing the cluster. Pressing y runs the official components manifest:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

Pressing N leaves the cluster unchanged and prints both the components manifest path and the official Helm route for review. Use --no-metrics-bootstrap or KUTOP_NO_METRICS_BOOTSTRAP=1 to skip this startup prompt in scripted runs.

PVC storage usage is fetched through the Kubernetes API-server proxy with kubectl get --raw /api/v1/nodes/<node>/proxy/stats/summary; this reuses the same kubeconfig auth and does not need a localhost port-forward.

RBAC needs depend on which panels/actions you use:

  • Core dashboard: get/list pods, nodes, events, and PVCs in the selected namespaces.
  • CPU/MEM metrics: access to the Metrics API used by kubectl top.
  • PVC usage and profile proxy URLs: permission for get --raw API-server proxy paths.
  • Logs/describe/delete: the corresponding pod logs, get, or delete permissions. Delete remains disabled unless --allow-destructive is set and the confirmation prompt is accepted.

Install

python -m pip install kutop
python -m pip install "kutop[profiles]"   # backward-compatible; YAML support is built in
python -m pip install "kutop[profiles] @ git+https://github.com/ken-jo/kutop.git"
python -m pip install "kutop @ git+https://github.com/ken-jo/kutop.git@v0.2.2"
python -m pip install -e ".[profiles]"   # local development from this directory

The project name, PyPI distribution, and Python package namespace are kutop. The kubetop command and python -m kubetop remain available only as compatibility aliases:

kutop --version
kubetop --version
python -m kutop --version
python -m kubetop --version

The PyPI name kubetop belongs to a different package. Pinned deps: textual==8.2.7, rich==15.0.0. Python 3.9+.

pip install @ken-jo/kutop is not valid pip syntax; use pip install kutop for PyPI releases, or the kutop @ git+https://... form for a GitHub branch, commit, or tag.

Other package managers after a tagged release:

brew tap ken-jo/kutop
brew install kutop

# One-shot install without a separate tap step:
brew install ken-jo/kutop/kutop

curl -fsSL https://ken-jo.github.io/kutop/apt/kutop.gpg \
  | sudo gpg --dearmor -o /usr/share/keyrings/kutop-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/kutop-archive-keyring.gpg] https://ken-jo.github.io/kutop/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/kutop.list
sudo apt update
sudo apt install kutop

Release setup for PyPI, Homebrew, and apt is documented in docs/release.md.

Run

kutop                               # generic view, namespace 'default'
kutop demo-ns 3                     # namespace demo-ns, 3s refresh
kutop ns-a,ns-b                     # multiple namespaces (comma list)
kutop --profile example             # load a profile (ordering / tz / thresholds)
python -m kutop demo-ns 3           # module form
python -m kubetop demo-ns 3         # legacy module alias
kutop --context demo-context demo-ns  # pick a kubeconfig context
kutop --allow-destructive           # enable pod delete (still confirm-gated)
kutop --no-metrics-bootstrap        # skip startup Metrics Server prompt
kutop --dump-config                 # print the full annotated config skeleton
kutop --self-test                   # headless smoke test (no cluster), exits 0
kutop --snapshot out.svg            # render one frame to SVG and exit
kutop --snapshot out.svg --detail full  # wider diagnostic capture

Positional namespaces/interval only seed the first run; your in-app choices are saved to ~/.config/kutop/config.yaml and win on the next launch. Existing ~/.config/kubetop and legacy ~/.config/ktop configs are migrated on first load; named profiles are also resolved from those legacy profile directories.

Keybindings

Key Action
q q quit (first press shows a confirmation toast)
r refresh now
o options / settings (tabbed: View, Columns, Panels, Thresholds, Cluster, Profile)
Tab / b toggle the control sidebar
/ search / filter pods by name
s / S cycle sort column / flip sort direction (or click a column header)
g group pods under their node
l live logs for the focused pod (kubectl logs -f)
d describe the focused pod
x delete the focused pod (only with --allow-destructive, then confirm)
e / v toggle the Events / PVC panels
a / h toggle the Alerts / Health panels (profile-driven)
R reload ~/.config/kutop/config.yaml live

The NODE/POD column is resizable: drag the handle on its header to widen or narrow it (the width persists). Click any column header to sort by it.

The sidebar Keys panel intentionally shows only the current work context. For example, a focused pod row surfaces l logs, d describe, and x delete, while the search bar surfaces /, Enter, and Esc; global shortcut summaries stay in the footer and native help.

Screenshots

kutop can render a headless SVG frame for README images, reviews, and visual QA. It uses live cluster data when reachable and falls back to a generic synthetic frame when not.

Main dashboard with every panel enabled: Summary, Trends, Alerts, the custom Health plugin panel, Pods, Events, and PVC storage:

kutop main dashboard with alerts, custom health, events, and PVC panels

Options modal views:

View Columns Panels
kutop options view tab kutop options columns tab kutop options panels tab
Thresholds Cluster Profile
kutop options thresholds tab kutop options cluster tab kutop options profile tab
kutop --snapshot /tmp/kutop.svg
kutop --snapshot /tmp/kutop-wide.svg --detail wide
kutop --snapshot /tmp/kutop-full.svg --detail full
kutop --snapshot /tmp/kutop-full.svg --detail full --size 220x54
kutop --snapshot /tmp/kutop-options.svg --snapshot-view options-panels --size 96x30

The detail presets are one-shot column layouts:

Detail Default size Use
normal 140x40 Same visible columns as the interactive default
wide 160x44 Prioritises namespace, readiness, phase, reason, owner, node, and key resources
full 220x54 Enables every table column and the PVC panel; increase --size for far-right columns

--snapshot-view accepts main, options-view, options-columns, options-panels, options-thresholds, options-cluster, and options-profile.

Profiles

A profile externalises everything that would otherwise be hardcoded. See kutop/profiles/example.yaml for a fully commented template:

name: my-stack
namespaces: [team-a, team-b]
timezone: ""                  # "" -> host local tz; or an IANA name
ordering:
  - { prefix: ingress-, weight: 10 }
  - { prefix: api-,     weight: 20 }
thresholds:
  cpu_warn: 75
  cpu_crit: 90
  mem_warn: 80
  mem_crit: 92
# alertmanager_url: "/api/v1/namespaces/monitoring/services/<svc>:9093/proxy/api/v2/alerts"

Profiles resolve by name from ~/.config/kutop/profiles/<name>.yaml and the packaged kutop/profiles/ directory, or by explicit path. Without a profile the core runs fully (alphabetical ordering, local timezone, generic thresholds).

Alerts & custom panels (no port-forward)

The Alerts and custom Health panels are opt-in and profile-driven. A /-prefixed URL in alertmanager_url / health_probes[].url is fetched via kubectl get --raw through the Kubernetes API-server proxy, so it uses your kubeconfig auth with no localhost port-forward. Health is a self-contained custom panel plugin (kutop/plugins/health.py); the core does not depend on it.

To update the custom panel without changing code, edit a profile or ~/.config/kutop/config.yaml:

panels:
  keys: true
  health: true
probes:
  health_probes:
    - name: api
      url: /api/v1/namespaces/default/services/api/proxy/health
      fields:
        ready: "ready=(\\w+)"
        latency: "latency_ms=(\\d+)"
    - name: worker
      url: /api/v1/namespaces/default/services/worker/proxy/metrics
      fields:
        lag: "queue_lag=(\\d+)"

For a new code-backed custom panel, use the existing plugin seam:

  1. Add a module under kutop/plugins/<name>.py.
  2. Expose a PLUGIN object with panel_id, is_enabled(config), fetch(fetcher, snapshot), make_panel(), and render(panel, snapshot).
  3. Append the module path to _BUILTIN_PLUGIN_MODULES in kutop/plugins/__init__.py.
  4. Keep plugin fetch/render best-effort: a custom panel must never crash the main Kubernetes dashboard.

How it works

  • kubectl calls run in a background thread worker; the UI thread never blocks, and a refresh is skipped while one is in flight (no thrashing on slow clusters).
  • Node/pod CPU & memory come from kubectl top + kubectl get -o json.
  • PVC usage comes from the kubelet summary API (/api/v1/nodes/<node>/proxy/stats/summary) because metrics-server does not expose it — a node whose summary call fails is skipped, others still report.
  • OOMKilled / CrashLoopBackOff / Pending pods are highlighted distinctly; node rows lead with the nodegroup (EKS/GKE/AKS label), then the short instance name.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kutop-0.3.3.tar.gz (109.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kutop-0.3.3-py3-none-any.whl (100.8 kB view details)

Uploaded Python 3

File details

Details for the file kutop-0.3.3.tar.gz.

File metadata

  • Download URL: kutop-0.3.3.tar.gz
  • Upload date:
  • Size: 109.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for kutop-0.3.3.tar.gz
Algorithm Hash digest
SHA256 6d50913d503d1f1bdec8883f92c30ac86bff9883ebcf2fd29bf14eda62698772
MD5 324133262c95d11847b532c6616e71e3
BLAKE2b-256 b42487ae4075092145c73c89dda01099bcae8897c27497b67dd66d6b1ed434f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for kutop-0.3.3.tar.gz:

Publisher: release.yml on ken-jo/kutop

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kutop-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: kutop-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 100.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for kutop-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f9b134e3f4f316061cd78a6a8af9411f343901f479ecd33ed49298489ad2c304
MD5 3a0a60cb7c533b1c2292d1c7210e0b41
BLAKE2b-256 eb3b71b44304eedd8ee8160c24343bdbd05aa6efc4f0dc9d885c34f5181dfd44

See more details on using hashes here.

Provenance

The following attestation bundles were made for kutop-0.3.3-py3-none-any.whl:

Publisher: release.yml on ken-jo/kutop

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page