A modern, zero-dependency TUI thread manager for shared Linux hosts.
Hunt ghost processes. Reclaim threads. Beat the ulimit -u wall.
╭─ 💀 ThreadReaper v1.0.0 ──────────────────────────────────────────────────╮
│ 🧵 1,272/2,000 [████████████▋ ] 63.6% ✅ 📈 ▂▃▄▄▅▅▆ │
├─ 🏆 TOP THREAD HOGS ──────────────────────────────────────────────────────┤
│ 1. ▶ rtorrent ( 4521) 482 thr 38.0% ███████████████░░░░░ │
│ 2. 💤 python3 ( 8832) 312 thr 24.6% ██████████░░░░░░░░░░ │
│ 3. 💤 java ( 9102) 198 thr 15.6% ███████░░░░░░░░░░░░░ 🐷 │
├─ 👻 GHOSTS (3) ───────────────────────────────────────────────────────────┤
│ 💀 PID 3301 transmission ZOMBIE parent owes wait() 🟢 0.99 │
│ 🐷 PID 5508 java IDLE HOG 94 thr, 0% CPU 60s 🟡 0.72 │
│ 👻 PID 2219 wget ORPHAN ppid=1, alive 3h 🟡 0.81 │
├─ 📋 PROCESSES — sort: Threads ↓ ──────────────────────────────────────────┤
│ ◆ ▶ 4521 rtorrent 482 thr 12.3% 1.2G 2d ▂▃▄▅▆▇█▇▆▅ 👻 │
│ 💤 8832 python3 312 thr 4.1% 800M 1d ▁▁▂▂▁▁▁▁▁▁ │
╰─ j/k nav K kill T tree / filter R reaper ? help q quit ────────────╯
Shared seedboxes, dev servers, and CI runners enforce a per-user
process/thread limit (RLIMIT_NPROC). Hit it and your shell starts
refusing to fork anything — including the tools you'd use to fix it.
top and htop don't sort by thread count, and they don't tell you
which of your processes are ghosts.
ThreadReaper does. It scans /proc, detects four classes of
ghost processes with confidence scores, and offers a guided "Reaper
Mode" that walks you through the highest-impact suspects, SIGTERM-first,
with a 3-second grace window before optional SIGKILL escalation.
- Thread-centric — the gauge, the sort, the alerts are all about threads first, not CPU or RSS.
- Five ghost detectors with confidence scoring:
- 💀 Zombie —
state=Z, parent never reaped - 👻 Orphan —
ppid=1, user-initiated, not a system service - 🐷 Idle Hog — high thread count, zero CPU, zero ctx-switches
- 🧊 Frozen — every activity metric flat across 6 cycles
- 🧲 Stuck-D — persistent uninterruptible disk sleep
- 💀 Zombie —
- Reaper Mode — guided, impact-sorted triage with SIGTERM→SIGKILL escalation, tree-kill, and end-of-run summary.
- Smooth UI — sub-cell Unicode block bars, sparkline trends per process, rounded box-drawing, animated refresh spinner.
- Process inspector — full cmdline, spawn chain, open files, CPU/thread history sparklines, safety verdict.
- Filter / sort / pin / group —
/filter,s/Ssort cycle & direction,ppin to top,Ggroup by binary. - Scripting modes —
--oncefor text reports,--jsonfor machine-readable snapshots. Plays nicely with cron and pipelines. - Zero dependencies — only Python 3.11+ stdlib (curses, /proc). No pip, no compile, no service to install.
- Safe by default — never kills itself, refuses to signal protected system binaries, prefers SIGTERM, asks before SIGKILL.
Single file, no packaging. Drop it on your $PATH:
curl -fsSL https://raw.githubusercontent.com/kpg-anon/threadreaper/main/threadreaper.py \
-o ~/.local/bin/threadreaper
chmod +x ~/.local/bin/threadreaperOr clone and symlink:
git clone https://github.com/kpg-anon/threadreaper.git
ln -s "$PWD/threadreaper/threadreaper.py" ~/.local/bin/threadreaperRequires Python 3.11+ and a Linux kernel with /proc. No third-party
libraries.
threadreaper # full TUI
threadreaper --once # text snapshot, suitable for cron / SSH
threadreaper --json > snap.json # JSON snapshot for scripts
threadreaper --ascii # ASCII-only mode for limited terminals
threadreaper --filter rtorrent # start with a process filter
threadreaper --refresh 1.0 # snappier refresh rate
threadreaper --limit 4000 # override detected thread limit| Key | Action |
|---|---|
↑/↓ j/k |
navigate |
PgUp PgDn |
page through list |
Home End |
jump to top / bottom |
K |
SIGTERM selected — press again within 5s for SIGKILL |
T |
kill selected process tree |
i |
inspect selected process |
p |
pin/unpin (pinned processes float to top) |
R |
enter Reaper Mode |
/ |
filter process list by name or cmdline |
s |
cycle sort column |
S |
toggle sort direction |
g |
toggle ghost panel |
G |
toggle group-by-binary view |
r |
force immediate refresh |
E |
export current snapshot to ~/.threadreaper/ |
? |
help overlay |
q / Esc |
quit |
R triggers a guided cleanup. Suspects are ordered by composite
impact (confidence × thread_count × severity_weight), with zombies
ranked highest because they're already dead. For each card you can:
k— SIGTERM this PIDT— SIGTERM this PID + all descendantss— skipi— open inspector overlay!— kill all remaining (with[h]HIGH-only opt-out)q— bail out, jump to summary
After SIGTERM you get a 3-second visual countdown. If the process
survives, ThreadReaper does not auto-escalate — you get
[9] SIGKILL, [w] wait 5s more, or [s] skip. This protects
session files for things like torrent clients.
~/.threadreaper/events.log— append-only kill log across runs~/.threadreaper/reaper-YYYY-MM-DD-HHMMSS.log— Reaper Mode session logs~/.threadreaper/snapshot-YYYY-MM-DD-HHMMSS.log—Eexports
Override the directory with THREADREAPER_HOME=/some/path.
ThreadReaper only reads /proc/PID/* for processes owned by your UID
(unless you pass --all-users, which is best-effort on shared hosts
where most reads will be permission-denied). It never phones home, never
opens a network socket, and never writes outside ~/.threadreaper/.
MIT — see LICENSE.
