cheat sheet
htop
Interactive process and resource monitor for the terminal. Covers function keys, sorting, filtering, signal sending, tree view, threads, and how to read load averages and memory correctly. Compares with top, btop, and bottom.
htop — Interactive Process Viewer
What it is
htop is an interactive, color, full-screen process and resource monitor for the terminal, written in C by Hisham Muhammad in 2004 (and maintained today by the htop-dev collective). It reads /proc to show every running process, sortable and filterable in real time, plus CPU, memory, and swap meters across the top. Reach for htop whenever a one-shot ps aux or top snapshot isn't enough — it's the standard tool for "what's hogging the CPU?" or "kill this stuck worker"; top is the always-present POSIX fallback, and btop (newer, written in C++) is the visually richer alternative.
Install
htop is packaged on every mainstream Linux distribution and macOS via Homebrew, and ships as a single static binary if you need to drop it on a stripped-down container.
# Debian/Ubuntu
sudo apt install htop
# Fedora
sudo dnf install htop
# Arch
sudo pacman -S htop
# macOS
brew install htop
# Alternatives
brew install btop # nicer UI, more meters
# top ships with every Unix already
Output: (none — exits 0 on success)
Syntax
htop is launched without arguments for the default view, or with a small set of flags to pre-filter what it shows. Once running, all interaction is keyboard-driven (mouse is supported in most terminals).
htop [OPTIONS]
htop -p PID[,PID...]
htop -u USER
htop -s COLUMN
Output: (none — exits 0 on success)
Essential CLI options
| Option | Meaning |
|---|---|
-p PID[,PID...] | Watch only the listed PIDs |
-u USER | Show only USER's processes |
-s COLUMN | Sort by COLUMN at startup (e.g. PERCENT_CPU, PERCENT_MEM) |
-d DELAY | Refresh delay in tenths of a second (default 15 = 1.5s) |
-t | Start in tree view |
-H | Show user threads (kernel threads off) |
-C | Monochrome (no colors) — NO_COLOR=1 env var works too (3.5+) |
--no-mouse | Disable mouse support |
--no-meters | Hide the header meters (3.5+) |
--no-function-bar | Hide the F1–F10 bar at the bottom (3.5+) |
--readonly | Disable kill / nice / setpriority (safe for shared boxes) |
--help | Show all options |
--version | Print version |
Default screen layout
The interface is divided into a header (CPU/memory/swap meters plus load average and uptime), the process list (scrollable, sortable table), and a function-key bar at the bottom showing F1–F10 actions.
1 [||||||||||||||| 38.2%] Tasks: 142, 287 thr; 3 running
2 [||||||||||||||||||||||||||| 72.4%] Load average: 0.84 0.61 0.40
3 [|||||||||| 21.7%] Uptime: 2 days, 04:13:55
4 [|||||||||||| 27.0%]
Mem[||||||||||||||| 3.42G/15.6G]
Swp[ 0K/2.00G]
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
4521 alice 20 0 712M 402M 20M R 88.4 2.6 1:42.11 python3 train.py
1234 www-data 20 0 124M 15M 12M S 0.7 0.1 0:02.31 nginx: worker
8800 root 20 0 23M 6.4M 5.6M S 0.0 0.0 0:00.04 sshd
8821 alice 20 0 18M 4.2M 3.4M S 0.0 0.0 0:00.02 -bash
...
F1Help F2Setup F3Search F4Filter F5Tree F6SortBy F7Nice- F8Nice+ F9Kill F10Quit
Function keys
F1–F10 are the discoverable, always-visible actions. They also have single-letter equivalents that don't require an Fn key (useful in macOS terminals where function keys go to the system).
| Key | Alt | Action |
|---|---|---|
F1 | h | Help screen |
F2 | S | Setup — meters, columns, colors |
F3 | / | Search (incremental, highlights matches) |
F4 | \\ | Filter (only matching processes shown) |
F5 | t | Toggle tree view |
F6 | < > | Choose sort column |
F7 | [ | Decrease nice value (raise priority) |
F8 | ] | Increase nice value (lower priority) |
F9 | k | Kill — send signal to selected process |
F10 | q | Quit |
htop # then press F4, type "nginx", Enter — only nginx procs remain
Output:
PID USER CPU% MEM% Command
1234 www-data 0.5 0.1 nginx: master process /usr/sbin/nginx
1235 www-data 0.3 0.1 nginx: worker process
1236 www-data 0.3 0.1 nginx: worker process
Sorting keys
< and > move through the sort-column list; the on-screen heading shows the active column highlighted. The three most-used one-key shortcuts pre-select the typical sorts:
| Key | Sort by |
|---|---|
M | Memory (descending) |
P | CPU% (descending) |
T | Cumulative TIME+ |
N | PID |
I | Invert current sort order |
htop -s PERCENT_MEM # pre-sort by RAM at launch
htop -s TIME # pre-sort by cumulative CPU time
Output (M sort):
PID USER MEM% RES Command
4521 alice 2.6 402M python3 train.py
2100 postgres 1.2 192M postgres
1234 www-data 0.1 15M nginx: master
Tree view (F5 / t)
Tree view replaces the flat process list with parent → child indentation, so you can see at a glance which daemon spawned a runaway worker. Toggling it preserves the current sort and filter; the indented children still sort by the active column within each parent.
htop -t # start in tree view
# or press F5 / t at any time to toggle
Output:
PID USER CPU% MEM% Command
1 root 0.0 0.0 /sbin/init
423 root 0.0 0.1 ├─ systemd-journald
611 root 0.0 0.0 ├─ cron
800 root 0.0 0.0 ├─ sshd
8800 root 0.0 0.0 │ └─ sshd: alicedev [priv]
8820 alice 0.0 0.0 │ └─ sshd: alicedev@pts/0
8821 alice 0.0 0.0 │ └─ -bash
9210 alice 0.0 0.0 │ └─ htop
1234 www-data 0.5 0.1 └─ nginx: master process
1235 www-data 0.3 0.1 ├─ nginx: worker
1236 www-data 0.3 0.1 └─ nginx: worker
Threads (H)
By default htop shows one row per process. Pressing H toggles user-thread visibility, which is essential for diagnosing multi-threaded apps (a JVM, a Python process with thread pools) — without it, a 16-thread process eating 800% CPU shows up as a single 800% row with no way to see which thread is hot. K toggles kernel threads on/off similarly.
htop -H # threads visible at launch
Output (Java app, H enabled):
PID USER CPU% Command
5821 alice 104.0 java -jar app.jar
5822 alice 32.1 GC Thread#0
5823 alice 28.7 GC Thread#1
5824 alice 18.2 main
5825 alice 12.0 http-worker-1
Search vs. filter (F3 vs. F4)
These look similar but behave differently. Search (F3 / /) jumps the cursor to each matching process but keeps every row visible; press the key repeatedly to walk through hits. Filter (F4 / \\) hides every non-matching row until you press F4 again with an empty query.
# Inside htop:
# /nginx → cursor jumps from match to match; all rows still visible
# \nginx → only matching rows shown; counter at top updates
# \ → with empty pattern, restores full list
Output (after \\nginx):
PID USER CPU% Command
1234 www-data 0.5 nginx: master process
1235 www-data 0.3 nginx: worker process
Sending signals (F9 / k)
Pressing F9 opens a signal-picker side panel; the default is SIGTERM (15) — polite. Use SIGKILL (9) only as a last resort, after SIGTERM and SIGINT (2) have been ignored. SIGHUP (1) is the canonical "reload config" signal for daemons.
| Signal | Number | Use |
|---|---|---|
SIGTERM | 15 | Polite "please exit" (default) |
SIGINT | 2 | Like Ctrl-C |
SIGHUP | 1 | Reload config (for daemons) |
SIGKILL | 9 | Force kill — process can't catch or ignore |
SIGSTOP / SIGCONT | 19 / 18 | Pause / resume |
SIGUSR1 / SIGUSR2 | 10 / 12 | App-defined |
Send signal:
✱ 15 SIGTERM
9 SIGKILL
2 SIGINT
1 SIGHUP
...
You can also select multiple processes with Space (toggles a tag), then press F9 to signal all tagged processes at once.
Watching a single PID (-p)
htop -p <PID> (one or comma-separated PIDs) pins the view to just those processes, with the meters still showing system-wide stats. Combined with pgrep, this is the quickest way to live-monitor one service.
htop -p $(pgrep -d, nginx) # all nginx PIDs as a single arg
htop -p $(pgrep -d, -f 'python.*train.py')
Output:
PID USER CPU% MEM% Command
1234 www-data 0.5 0.1 nginx: master process
1235 www-data 0.3 0.1 nginx: worker
1236 www-data 0.3 0.1 nginx: worker
Setup (F2)
F2 opens a configuration screen where you can change meters in the header, add or remove columns from the process list, and pick a color scheme. Changes are written to ~/.config/htop/htoprc and persist across launches.
Active Available
Left column Meters
> CPU - CPU
> Memory - Memory
- Swap
Right column - Load average
> Tasks - Uptime
> Load average - Battery
> Uptime - Hostname
- All CPUs
- Disk IO
- Network IO
# Common customisations
# - Show all CPU cores as one bar to save space:
# F2 → Meters → CPUs (1/1) [Bar] or [Text]
# - Add Disk IO and Network IO meters
# - Add IO_RATE column to the process list
Output: (none — exits 0 on success)
Configuration
htop persists everything you change in F2 Setup to ~/.config/htop/htoprc — meters, columns, colour scheme, refresh delay, hide-kernel-threads, and so on. The file is plain key=value text and is safe to edit by hand, copy between machines, or version-control alongside your dotfiles. Since 3.4 htop and pcp-htop keep separate config files so the two don't clobber each other.
# Inspect the live config
cat ~/.config/htop/htoprc
# Back up before experimenting
cp ~/.config/htop/htoprc ~/.config/htop/htoprc.bak
# Reset to defaults (htop rewrites the file on next quit)
rm ~/.config/htop/htoprc
htop # change nothing, then F10 — fresh file is written
Output (cat, abridged):
fields=0 48 17 18 38 39 40 2 46 47 49 1
sort_key=46
sort_direction=-1
tree_sort_key=0
hide_kernel_threads=1
hide_userland_threads=0
shadow_other_users=0
show_thread_names=0
show_program_path=1
color_scheme=0
delay=15
left_meters=AllCPUs Memory Swap
left_meter_modes=1 1 1
right_meters=Tasks LoadAverage Uptime
right_meter_modes=2 2 2
| Key | Meaning |
|---|---|
fields=… | Process-list columns, by numeric column ID |
sort_key / sort_direction | Default sort column and direction (-1 desc) |
delay | Refresh delay in tenths of a second |
hide_kernel_threads / hide_userland_threads | What to hide by default |
show_program_path | 1 = full path, 0 = command basename only |
color_scheme | 0=default, 1=monochrome, 5=broken-grey, 6=Nord (3.5+) |
left_meters / right_meters | Header meters by name (CPU, Memory, GPU, DiskIO, …) |
htop writes the file when you quit cleanly; if you edit it while htop is running, your changes will be overwritten on exit. Make sure no other instance is active before hand-editing.
What's new in htop 3.4 and 3.5
The htop-dev team have been steadily landing modern monitoring features. 3.4 (March 2025) added a GPU meter and per-process GPU time column — the first time htop could show NVIDIA/AMD GPU utilisation alongside CPU. 3.5 (released later in 2025) added a backtrace screen built on libunwind-ptrace so you can inspect the call stack of any process without dropping to gdb, plus a clean Nord colour theme, a proper inline line editor for search/filter/screen-rename, and --no-meters / --no-function-bar for embedding htop in tmux panes without visual clutter.
| Version | Headline additions |
|---|---|
| 3.5.x | Backtrace screen (libunwind-ptrace); Nord theme; line editor for search/filter; --no-meters, --no-function-bar; NO_COLOR env support; CPU SMT label option; redesigned DiskIO meter (rate + time sub-meters); macOS GPU meter; OpenRC support |
| 3.4.x | GPU meter (Linux + PCP); per-process GPU time column; single-column header layout; per-platform config file (~/.config/htop/htoprc vs. pcp-htop); dynamic CPU-column width based on max PID; better ARM Darwin support |
| 3.3.x | Docker / Podman container ID shortening (12 chars); FreeBSD truss support; Darwin NetworkIOMeter; 3-column header layouts; container-name filtering from cgroup names |
# Add the GPU meter (3.4+) — F2 → Meters → GPU → add to a column
# Add the GPU time column — F2 → Columns → GPU_TIME
# Open the backtrace screen (3.5+) — select a process, then
# F2 → Screens → add "Backtrace" → assign to F6 or a Tab key
# Embed htop in a tmux pane with no chrome
htop --no-meters --no-function-bar
Output: (none — exits 0 on success)
Reading the header
The header has more nuance than it looks. Load average is a running average of runnable + uninterruptible processes over 1, 5, and 15 minutes — not a CPU percentage. Mem colors mean: green = used, blue = buffers, yellow = cache. The cache portion is "free if anything else needs it" — Linux deliberately uses spare RAM as disk cache, so a host showing 90% used is usually healthy.
| Display | What to look for |
|---|---|
Load average: 1.20 0.80 0.40 | First number > number of CPU cores → over-saturated |
| `Mem[ | |
Swp[ 0K/2.00G] | Any swap use is a yellow flag; sustained use is a red flag |
Tasks: 142, 287 thr; 3 running | "3 running" should generally be ≤ core count |
# Sanity-check load average against core count
nproc
uptime
Output:
4
10:14:33 up 2 days, 4:13, 1 user, load average: 0.84, 0.61, 0.40
htop vs. top vs. btop vs. bottom
top is POSIX and present on every Unix — when you SSH into a box with nothing installed, it's the fallback. htop is the everyday upgrade: colour, scrollable, mouse-aware, function keys for kill/nice/sort, and (since 3.4/3.5) GPU meters and a backtrace screen. btop (the C++ successor to bpytop, which was itself the Python successor to bashtop) is the maximalist option — Braille graphs for CPU/network/disk, mouse-driven menus, animated time-series. bottom (binary name btm) is the keyboard-first Rust alternative with a unique TOML layout system so you can carve the screen into any arrangement of panes you like. bpytop itself is no longer actively developed — it's been fully superseded by btop (and the Rust rewrite is now landing in distros as btop 4.x).
| Feature | top | htop | btop | bottom (btm) |
|---|---|---|---|---|
| In every base install | yes | no | no | no |
| Language / runtime | C | C | C++ (Rust 4.x) | Rust |
| Colour UI | optional | yes | yes | yes |
| Mouse support | no | yes | yes | yes |
| Scroll horizontally | no | yes | yes | yes |
| Tree view | partial (V) | yes (F5) | yes | yes |
| Per-thread view | yes (H) | yes (H) | yes | no |
| CPU/Net/Disk graphs | no | basic meters | rich Braille | rich Braille |
| GPU meter | no | yes (3.4+) | yes | yes |
| Backtrace screen | no | yes (3.5+) | no | no |
| Custom layout | no | header only | preset views | full TOML config |
| Colour themes | no | a few (Nord 3.5+) | many | many |
| Footprint | tiny | small | medium | small |
top -o +%CPU # POSIX top, sorted by CPU
top -H # show threads (Linux top)
btop # if installed; q to quit
btm # bottom; press ? for help, q to quit
btm --basic # bottom in compact, no-graph mode
Output (top -o +%CPU, abridged):
top - 10:14:33 up 2 days, 4:13, 1 user, load average: 0.84, 0.61, 0.40
Tasks: 142 total, 3 running, 139 sleeping
%Cpu(s): 38.2 us, 5.1 sy, 0.0 ni, 56.0 id
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4521 alice 20 0 712340 402100 20012 R 88.4 2.6 1:42.11 python3
1235 www-data 20 0 126484 15280 12044 S 0.7 0.1 0:02.31 nginx
Rule of thumb: reach for top on a stripped-down jumpbox, htop for everyday triage and the backtrace screen, btop when you want pretty graphs over time on a desktop or home-lab box, and bottom when you need a custom multi-pane layout you can check into dotfiles.
Common pitfalls
- "100% CPU" with one core saturated — the per-process
CPU%is summed across cores, so a single thread maxing one of four cores reads as100%, not25%. Toggle to system-percent in Setup if you want the latter. - Memory looks "full" but the system is fine — yellow bar segments are file cache that Linux will release on demand. Real pressure shows up as growing
Swpusage orD-state processes blocked on I/O. - Load average ≠ CPU percentage — a load of
8on a 16-core box is half-utilised; a load of8on a 4-core box is queueing two-deep. Always compare tonproc. - Threads invisible — by default
htophides user threads; pressH(or launch with-H) when investigating Java/Python/Go programs. - Sort column won't stay set — in tree view sorting groups within siblings only; press
F5again to leave tree mode if you need a global sort. - Function keys hijacked by terminal — iTerm2 and macOS Terminal sometimes swallow
F2/F9. Use the letter equivalents (S,k) instead, or remap in Terminal preferences. htopshows wrong colors over SSH —TERMis set toxterminstead ofxterm-256color. Runexport TERM=xterm-256color(ortmux-256colorinside tmux).
Real-world recipes
Find the top three CPU eaters and kill the worst
A two-shortcut workflow: P sorts by CPU, Space tags processes, F9 kills them all at once.
htop
→ press P # sort by CPU
→ Space x3 on top 3 # tag them
→ F9 → 15 # SIGTERM tagged processes
Output: (the tagged rows disappear within a refresh tick)
PID USER CPU% Command
1234 www-data 0.5 nginx: master
8821 alice 0.0 -bash
9210 alice 0.0 htop
Watch a single misbehaving service
When a service is the suspect, narrow the picker to just its PIDs and turn threads on so you can see which worker is hot.
htop -H -p $(pgrep -d, -f 'gunicorn|uwsgi')
Output:
PID USER CPU% MEM% Command
5021 www-data 62.1 3.4 gunicorn: worker [app:wsgi]
5022 www-data 41.9 3.2 gunicorn: worker [app:wsgi]
5020 www-data 0.1 3.1 gunicorn: master [app:wsgi]
"What changed?" snapshot for a bug report
Press F2 → enable "All CPUs (1/1) [Text]" to compact the header, then capture the screen with tmux capture-pane or your terminal's native screenshot. Pair with journalctl -u myapp -n 50 for the matching log slice.
tmux capture-pane -p -S - > /tmp/htop-snapshot.txt
journalctl -u myapp -n 50 --no-pager > /tmp/myapp-50.log
Output: (none — exits 0 on success)
Stuck process: which syscall is it blocked on?
htop shows the S state column — D means "uninterruptible sleep" (usually disk I/O). When you spot one, drop to strace -p PID for the syscall it's stuck in.
htop # find a D-state PID, say 7821
sudo strace -p 7821 -e trace=desc
Output:
strace: Process 7821 attached
read(8, ...
Quick comparison: are these workers balanced?
Run htop filtered to the worker pool. If one row is at 80% and the others near 0%, the load balancer or work queue is misrouting work.
htop -p $(pgrep -d, -f 'celery worker') -s PERCENT_CPU
Output:
PID USER CPU% Command
8801 alice 78.4 celery worker -A app -Q default
8802 alice 2.1 celery worker -A app -Q default
8803 alice 1.0 celery worker -A app -Q default
8804 alice 0.7 celery worker -A app -Q default
On servers you administer alongside others, run
htop --readonly— it disables kill / nice / setpriority so a misclick can't take down a process. Combine withalias htop='htop --readonly'for shared bastions.
If you live in tmux, bind a prefix key to "split + run htop":
bind-key h split-window -h 'htop'. Pressprefix hand you have a live process pane next to whatever you're working on.