Your exporters. A terminal away.
Live dashboards for the Prometheus metrics your host already exposes.
Discover, explore, and investigate — locally or over SSH.
Try it without a host:
nix run github:clushie/etop -- --demoWatch the MP4 tour. The screenshots and recordings use synthetic metrics generated by etop; they contain no real host data.
Sometimes you want to understand one host, right now. etop discovers its exporters, recognizes their metrics, and builds useful terminal views while you investigate. It needs no Prometheus server, saved dashboards, or etop installation on the observed host.
- An overview that is ready to use. CPU, memory, network and disk activity, filesystems, busy services, and the series you choose to watch.
- Cgroups with explanations. Navigate the hierarchy and separate anonymous memory, file cache, kernel memory and swap. Drill into pressure, I/O, limits, throttling and OOM events without adding overlapping memory categories. First-class integration with arianvp/cgroup-exporter.
- Queries without the setup. Start with suggestions from the selected exporter. Edit label filters, rates, grouping and top-k; results refresh live.
- Your metrics, directly. Browse every exposed metric and label. Resource values come from exporters, with session history held in memory.
- A terminal citizen. Keyboard navigation, narrow-terminal layouts, automatic light/dark appearance, explicit theme overrides, and one SSH connection.
# Synthetic demo — no network access or target host required by the app
nix run github:clushie/etop -- --demo
# Observe another host with your existing SSH configuration
nix run github:clushie/etop -- user@host
# Observe this machine
nix run github:clushie/etop -- --localNix packages support x86_64-linux and aarch64-linux and bundle the local
collection tools. The observed SSH host needs curl; ss is optional but enables
listener discovery. Existing SSH identities, aliases, ports and jump hosts work.
No sudo is required by etop.
Add the input to your existing system flake. Following your nixpkgs input makes
etop use the same package set as the rest of your system.
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
etop.url = "github:clushie/etop";
etop.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { nixpkgs, etop, ... }: {
nixosConfigurations.my-host = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; # Or aarch64-linux.
modules = [
./configuration.nix
({ pkgs, ... }: {
environment.systemPackages = [
etop.packages.${pkgs.stdenv.hostPlatform.system}.default
];
})
];
};
};
}Merge this into your existing configuration, keeping your machine's modules and
host name, then run sudo nixos-rebuild switch --flake .#my-host.
The complete example is in examples/nixos-flake.nix.
The followed package set must provide the supported Textual version; the
project's pinned package set is tested with Textual 8.2.6.
For Home Manager, use the same inputs, pass etop through
extraSpecialArgs = { inherit etop; };, and add this to your home module:
{ pkgs, etop, ... }: {
home.packages = [ etop.packages.${pkgs.stdenv.hostPlatform.system}.default ];
}Release assets include a standard Python wheel, a source archive and checksums. Install the wheel with pipx (or pip inside a virtual environment):
pipx install https://github.com/clushie/etop/releases/download/v0.1.0/etop-0.1.0-py3-none-any.whl
etop --demoLinux and Python 3.11+ are required. For non-demo collection, install curl and
openssh; install iproute2 for ss, and GLib's gdbus for desktop appearance
detection. Terminal appearance detection works independently of gdbus.
This project distributes through GitHub Releases; pip install etop from PyPI
is not the installation method documented here.
To build or install from a checkout:
python -m pip install .
# Or, inside nix develop:
python -m build
python -m twine check dist/*| Key | View or action |
|---|---|
1 |
Host overview and watched series |
2 |
Cgroup hierarchy and resource details |
3 |
Dashboard for the selected exporter |
4 |
Metrics, labels and history |
5 |
Alloy components and discovery diagnostics |
6 |
Live queries and automatic suggestions |
/ |
Search or edit the query |
Enter / Esc |
Drill in / return |
e |
Add a metrics URL; works without ss |
a / x |
Merge a known duplicate route / hide an exporter |
t |
Cycle auto, light and dark themes |
Space / r |
Pause collection / rediscover |
q |
Quit |
In Cgroups, c, m and i sort by CPU, RAM and I/O; h toggles the tree.
In metric details, r switches raw/rate and w adds the selected series to your
watch list. Tab, arrows and the mouse work throughout.
# Skip listener discovery and use explicit endpoints
etop user@host --no-discover \
-e http://127.0.0.1:9100/metrics \
-e http://127.0.0.1:8080/internal/metrics
# Discover an Alloy instance on a custom port
etop user@host --alloy http://127.0.0.1:12345
# A JSON snapshot with two scrapes to warm up rates
etop user@host --onceURLs are fetched from the observed host. If ss is unavailable, etop tries
common ports and explains how to add endpoints. Known metric prefixes identify
exporters; Alloy's configured names are retained. Equal URLs are deduplicated.
Matching metric schemas suggest possible alternate routes, but independent
replicas are never silently merged.
arianvp/cgroup-exporter is the recommended exporter for etop's cgroup v2 exploration. It collects measurements; etop turns them into an interactive hierarchy, resource explanations, charts and query suggestions. See services and slices as well as containers.
Additional metrics, including NUMA and zswap, are accessible through Metrics and
Queries without dedicated resource rows. Compatible cgroup_* schemas and
cAdvisor also work.
With the exporter running on its default port:
# On the observed machine
etop --local --endpoint http://127.0.0.1:13232/metrics
# From another machine; the URL is fetched over SSH on the observed host
etop user@host --endpoint http://127.0.0.1:13232/metricsAutomatic discovery recognizes its metric schema. When ss is missing, etop
also probes port 13232; press e to add a custom endpoint.
For an optional NixOS setup, add these inputs alongside etop:
cgroup-exporter.url = "github:arianvp/cgroup-exporter";
cgroup-exporter.inputs.nixpkgs.follows = "nixpkgs";Include cgroup-exporter in your flake's outputs arguments, then add these
entries to your NixOS modules:
cgroup-exporter.nixosModules.default
{
services.prometheus.exporters.cgroup = {
enable = true;
listenAddress = "127.0.0.1";
port = 13232;
};
}The complete example installs etop and enables the exporter using its upstream module. Merge it into your existing system configuration. The loopback binding works for both local collection and etop's SSH workflow, without exposing a new public port. Enabling this example starts the exporter service; etop itself only reads metrics.
In Queries, choose a suggestion or write an expression:
topk(10, rate(cgroup_cpu_usage_seconds_total) * 100)
topk(10, cgroup_memory_anon_bytes)
cgroup_memory_swap_current_bytes{cgroup=~".*worker.*"}
sum by (cgroup) (rate(cgroup_io_read_bytes_total[1m]))
The language is a local PromQL-style subset: selectors, label matchers,
arithmetic, rate, sum, avg, min, max, count, by, and topk.
It uses only the selected endpoint's retained session samples. It does not
query a Prometheus server or provide full PromQL compatibility.
local terminal ── optional SSH connection ── observed host
├─ ss: listener addresses
├─ Alloy HTTP API: local targets
└─ exporter /metrics: measurements
etop makes read-only requests, keeps history in memory, and closes its SSH
connection on exit. It does not install an agent, change services, or read
/proc or systemd for resource measurements. Non-metric inputs are discovery
metadata, local scrape timings and local appearance detection.
History starts when you open etop. Counter resets and scrape gaps suppress rates; failed scrapes retain a clearly marked stale snapshot. Cgroup parents include descendants, and memory detail categories can overlap. The UI explains these relationships rather than presenting their sum as a new total.
Supported profiles include Linux/node, cgroups/cAdvisor, nginx, PostgreSQL, Alloy, Chrome and common runtime metrics. Other exporters remain browsable and receive generic metric cards. Authenticated endpoints, native/protobuf histograms, historical backfill and replaying Alloy authentication settings are outside the current scope. See the full user guide for discovery, appearance, query semantics and collection limits.
Terminal UIs only. Snapshot 2026-10-20, sorted by GitHub stars (descending). Release dates refer to the earliest published stable GitHub release and GitHub's latest stable release. — = not documented; No = unsupported; None = no published release; Backend = a separate metrics server. Column headings and dates link to sources.
| Feature | btop | below | otel-tui | Ember | grom | promexplorer | Peat | etop |
|---|---|---|---|---|---|---|---|---|
| GitHub stars | 35,047 | 2,536 | 1,109 | 386 | 54 | 29 | 0 | 0 |
| First GitHub release | 2021-09-18 | 2025-02-25 | 2024-06-17 | 2026-03-26 | 2026-07-07 | 2023-04-02 | None | 2026-10-20 |
| Latest release | 2026-05-01 (v1.4.7) | 2025-09-24 (v0.11.0) | 2026-09-12 (v0.7.5) | 2026-10-12 (v1.6.2) | 2026-07-09 (v0.3.0) | 2023-05-03 (v0.0.5) | None | 2026-10-20 (v0.1.0) |
| Metric source | Kernel | Kernel | OTLP / exporters | Caddy APIs | Prometheus | Exporter | Prometheus | Exporters |
| Target setup | Local host | Local host | Explicit targets | Caddy address | Backend | Explicit URL | Backend | Listeners + Alloy |
| Built-in SSH collection | — | — | — | — | — | — | — | Yes |
| Cgroup tree | — | Yes | — | — | — | — | — | Yes |
| Queries | — | — | — | — | Backend PromQL | — | Backend PromQL | Local subset · Full PromQL: Vote for this feature |
| History | Session charts | Record / replay | JSON import | Session charts | Backend | — | Backend | Session · Save & replay: Vote for this feature |
| Grafana JSON import | — | — | — | — | Yes | — | — | No · Vote for this feature |
| Traces | — | — | Yes | — | — | — | — | No · Vote for this feature |
| Logs | — | — | Yes | Yes | — | — | — | No · Vote for this feature |
Feature votes use GitHub Discussion upvotes; proposals are not release commitments.
nix develop
python -m etop --demo
pytest -q
ruff check .
nix flake check
nix buildThe test suite covers discovery, missing tools, alternate routes, parsing,
rates, memory accounting, queries, terminal replies, SSH cleanup and keyboard
navigation. nix develop also includes the Python packaging and demo recording
tools. Rebuild the synthetic screenshots and MP4 tours with:
python scripts/record_demo.pyThe website is buildless HTML/CSS/JS in site/, with no analytics, external fonts,
or third-party scripts. Preview it using python -m http.server 8080 --directory site.
GitHub Actions deploys that directory to Pages when main changes. A v* tag
runs tests, builds the wheel/source archive, checks metadata and publishes release
assets. The tag must match the version in pyproject.toml.
Contributions and bug reports are welcome. Include your terminal, etop version, and a small sanitized metric example when reporting exporter behavior.
MIT · Built with Textual, Prometheus client and Nix.