Loading...
Loading...
CLI and TUI tool that explains why processes, services, and ports are running by tracing causality chains across supervisors, containers, and shells.
npx skill4agent add aradotso/trending-skills witr-process-inspectorSkill by ara.so — Daily 2026 Skills collection.
pslsofsssystemctldocker pscurl -fsSL https://raw.githubusercontent.com/pranshuparmar/witr/main/install.sh | bashirm https://raw.githubusercontent.com/pranshuparmar/witr/main/install.ps1 | iex# Homebrew (macOS/Linux)
brew install witr
# Conda
conda install -c conda-forge witr
# Arch Linux (AUR)
yay -S witr-bin
# Windows winget
winget install -e --id PranshuParmar.witr
# Windows Scoop
scoop install main/witr
# Alpine / apk
sudo apk add --allow-untrusted ./witr-*.apk
# Go source install
go install github.com/pranshuparmar/witr/cmd/witr@latest# Inspect a process by PID
witr <pid>
# Inspect by process name (substring match)
witr <name>
# Inspect what's bound to a port
witr --port <port>
witr -p <port>
# Launch interactive TUI dashboard
witr --interactive
witr -i
# Show all running processes with causality info
witr --all
witr -a
# Output as JSON (for scripting)
witr --json <pid>
# Follow/watch mode — refresh automatically
witr --watch <pid>
witr -w <pid>
# Verbose output — show full environment and metadata
witr --verbose <pid>
witr -v <pid>
# Filter processes by user
witr --user <username>
# Show version
witr --version| Flag | Short | Description |
|---|---|---|
| | Inspect by port number |
| | Launch TUI dashboard |
| | Show all processes |
| Output as JSON | |
| | Auto-refresh/follow |
| | Full metadata output |
| Filter by OS user | |
| Print version |
witr -i
# or
witr --interactive| Key | Action |
|---|---|
| Navigate process list |
| Expand process detail / causality chain |
| Filter/search processes |
| Sort by column |
| Refresh |
| Toggle JSON view |
| Quit |
witr 1234PID: 1234
Name: node
Binary: /usr/local/bin/node
Started: 2026-03-18 09:12:44
User: ubuntu
Why is this running?
└─ Started by: npm (PID 1200)
└─ Started by: bash (PID 1180)
└─ Started by: sshd (PID 980)
└─ Started by: systemd (PID 1) [service: sshd.service]witr --port 8080Port: 8080 (TCP, LISTEN)
Process: python3 (PID 4512)
Binary: /usr/bin/python3
User: deploy
Why is this running?
└─ Started by: gunicorn (PID 4490)
└─ Started by: systemd (PID 1) [service: myapp.service]
Unit file: /etc/systemd/system/myapp.service
ExecStart: /usr/bin/gunicorn app:app --bind 0.0.0.0:8080witr --json 4512{
"pid": 4512,
"name": "python3",
"binary": "/usr/bin/python3",
"user": "deploy",
"started_at": "2026-03-18T09:00:00Z",
"causality_chain": [
{"pid": 4490, "name": "gunicorn", "type": "parent"},
{"pid": 1, "name": "systemd", "type": "supervisor", "service": "myapp.service"}
]
}# Refresh every 2 seconds
witr --watch 4512# Quick check: who owns port 5432 (Postgres)?
witr --port 5432
# Get machine-readable output for automation
witr --json --port 5432 | jq '.causality_chain[-1].service'# List everything with causality, pipe to less
witr --all | less
# Export full audit to JSON
witr --all --json > audit.json# witr understands container boundaries
witr <pid-of-containerized-process>
# Output will show: container → container runtime → systemd chain#!/usr/bin/env bash
# Check if port 8080 is in use and why
if witr --json --port 8080 > /tmp/witr_out.json 2>/dev/null; then
SERVICE=$(jq -r '.causality_chain[-1].service // "unknown"' /tmp/witr_out.json)
echo "Port 8080 is owned by service: $SERVICE"
else
echo "Port 8080 is not in use"
fi# Show only processes owned by www-data and why they're running
witr --all --user www-data| Platform | Architectures | Notes |
|---|---|---|
| Linux | amd64, arm64 | Full support |
| macOS | amd64, arm64 (Apple Silicon) | Full support |
| Windows | amd64 | Full support |
| FreeBSD | amd64, arm64 | Full support |
go get github.com/pranshuparmar/witrpackage main
import (
"fmt"
"github.com/pranshuparmar/witr/pkg/inspector"
)
func main() {
// Inspect a process by PID
result, err := inspector.InspectPID(1234)
if err != nil {
panic(err)
}
fmt.Printf("Process: %s\n", result.Name)
for _, link := range result.CausalityChain {
fmt.Printf(" └─ %s (PID %d)\n", link.Name, link.PID)
}
}// Inspect by port
result, err := inspector.InspectPort(8080, "tcp")
if err != nil {
panic(err)
}
fmt.Printf("Port 8080 owned by PID %d (%s)\n", result.PID, result.Name)# witr needs read access to /proc (Linux) or equivalent
# Run with sudo for system-level processes
sudo witr <pid>
sudo witr --port 80# Ensure install location is in PATH
export PATH="$PATH:/usr/local/bin" # Unix default install
# or for Go installs:
export PATH="$PATH:$(go env GOPATH)/bin"# Confirm port is actually listening first
ss -tlnp | grep <port> # Linux
netstat -an | grep <port> # macOS/Windows
# Then retry
witr --port <port># Ensure terminal supports 256 colors
export TERM=xterm-256color
witr --interactive
# If on Windows, use Windows Terminal for best TUI experience# witr can only inspect currently running processes
# Use --watch on a long-running process to monitor it
witr --watch <pid># System Integrity Protection may restrict some process metadata
sudo witr <pid>witr <pid> # Why is PID X running?
witr <name> # Why is process "nginx" running?
witr -p <port> # What's on port 8080 and why?
witr -i # Interactive TUI dashboard
witr -a # Show all processes + causality
witr --json <pid> # Machine-readable output
witr -w <pid> # Watch/follow a process
witr -v <pid> # Verbose: full env + metadata
witr --user <user> # Filter by OS user