claudeers.
// Uncategorized / Others

witr

Why is this running? Trace any process, port, container, or file back to what started it - CLI + TUI.

// Uncategorized / Others[ cli ][ api ][ desktop ][ web ][ claude ]#claude#cli#containers#devops#docker#freebsd#go#golang#uncategorized◷ Apache-2.0$open-sourceupdated about 24 hours ago

Install with your AI

Paste into Claude Code, Cursor, or any agent — it reads the repo and wires the tool into your project.

Install and set up witr (claude-plugin project) into my current project.
Found on https://claudeers.com/witr
Repo: https://github.com/pranshuparmar/witr
Homepage/docs: https://pranshuparmar.github.io/witr/
Detected install method: claude-plugin → /plugin install witr@pranshuparmar/witr
Category: uncategorized. Platforms: cli, api, desktop, web.
Read the repo's README for exact setup and env vars, then install it and wire it into my project.

Claudeers Health Verdict:
unknown; community-verified: false. Confirm the source before running anything.
// or install directly (claude-plugin)

⚠ Unverified / not recently updated — review before pasting a run-this config.

/plugin marketplace add pranshuparmar/witr
/plugin install witr@pranshuparmar/witr
// or clone
git clone https://github.com/pranshuparmar/witr

// compatibility

Platformscli, api, desktop, web
Operating systems—
AI compatibilityclaude
LicenseApache-2.0
Pricingopen-source
LanguageGo

Get your FREE $2.50 API credits to access TickAtlas financial data ↗

witr

Why is this running?

Trace any process, port, container, or file back to the exact chain that started it —
one command, machine-readable JSON, or an interactive TUI.


pranshuparmar/witr on Trendshift witr - Why is this running? Trace process, port, container or file. | Product Hunt

🎮 Try witr in your browser →

Investigate a simulated Linux box — a guided tutorial and free-play sandbox, no install required.

witr's interactive TUI and CLI answering why a node process is running — the same systemd → PM2 → node chain in both


Purpose • Installation • TUI • Flags • Core Concept • Examples
Output Behavior • Platforms • Success Criteria • Sponsors


1. Purpose

witr exists to answer a single question:

Why is this running?

When something is running on a system, whether it is a process, a service, or something bound to a port, there is always a cause. That cause is often indirect, non-obvious, or spread across multiple layers such as supervisors, containers, services, or shells.

Existing tools (ps, top, lsof, ss, systemctl, docker ps) expose state and metadata. They show what is running, but leave the user to infer why by manually correlating outputs across tools.

witr makes that causality explicit.

It explains where a running thing came from, how it was started, and what chain of systems is responsible for it existing right now, in a single, human-readable output or an interactive TUI dashboard.

📖 Curious how witr came to be? Read the story or browse the Hacker News discussion.


2. Installation

witr is distributed as a single static binary for Linux, macOS, FreeBSD, and Windows.

witr is also independently packaged and maintained across multiple operating systems and ecosystems. An up-to-date overview of packaging status is available on Repology. Please note that community packages may lag GitHub releases due to independent review and validation.

[!TIP] If you use a package manager (Homebrew, Conda, Winget, etc.), we recommend installing via that for easier updates. Otherwise, the install script is the quickest way to get started.


2.1 Quick Install

Unix (Linux, macOS & FreeBSD)

curl -fsSL https://raw.githubusercontent.com/pranshuparmar/witr/main/install.sh | bash
Script Details

The script will:

  • Detect your operating system (linux, darwin or freebsd)
  • Detect your CPU architecture (amd64, arm64 or loong64 on Linux)
  • Download the latest released binary and man page
  • Install it to /usr/local/bin/witr
  • Install the man page to /usr/local/share/man/man1/witr.1
  • Pass INSTALL_PREFIX to override default install path

Windows (PowerShell)

irm https://raw.githubusercontent.com/pranshuparmar/witr/main/install.ps1 | iex
Script Details

The script will:

  • Download the latest release (zip) and verify checksum.
  • Extract witr.exe to %LocalAppData%\witr\bin.
  • Add the bin directory to your User PATH.

2.2 Package Managers

APT (Debian, Ubuntu & Derivatives) Debian

You can install witr from the official Debian and Ubuntu repositories (Ubuntu 26.04+, Debian sid and later), as well as derivative distributions like Kali Linux, Devuan, and Raspbian:

sudo apt install witr

Note: The apt-shipped version may lag the latest GitHub release. For the newest features, use the install script or another installation method.

Homebrew (macOS & Linux)

You can install witr using Homebrew on macOS or Linux:

brew install witr
MacPorts (macOS) MacPorts

You can install witr using MacPorts on macOS:

sudo port install witr
Conda (macOS, Linux & Windows)

You can install witr using conda, mamba, or pixi on macOS, Linux, and Windows:

conda install -c conda-forge witr
# alternatively using mamba
mamba install -c conda-forge witr
# alternatively using pixi
pixi global install witr
Arch Linux (AUR)

On Arch Linux and derivatives, install from the AUR package:

yay -S witr-bin
# alternatively using paru
paru -S witr-bin
# or use your preferred AUR helper
Winget (Windows)

You can install witr via winget:

winget install -e --id PranshuParmar.witr
NPM (Cross-platform)

You can install witr using npm:

npm install -g @pranshuparmar/witr
FreeBSD Ports FreeBSD Port

You can install witr on FreeBSD from the FreshPorts port:

pkg install witr
# or
pkg install sysutils/witr

Or build from Ports:

cd /usr/ports/sysutils/witr/
make install clean
Chocolatey (Windows)

You can install witr using Chocolatey:

choco install witr
Scoop (Windows)

You can install witr using Scoop:

scoop install main/witr
AOSC OS AOSC OS

You can install witr from the AOSC OS repository:

oma install witr
GNU Guix GNU Guix

You can install witr from the GNU Guix repository:

guix install witr
Uniget (Linux)

You can install witr using uniget:

uniget install witr
Aqua (macOS, Linux & Windows)

You can install witr using aqua:

# Add package
aqua g -i pranshuparmar/witr

# Install package
aqua i pranshuparmar/witr
Brioche (Linux)

You can install witr using brioche:

brioche install -r witr
Mise (macOS, Linux & Windows)

You can install witr using mise:

mise use github:pranshuparmar/witr
Prebuilt Packages (deb, rpm, apk)

witr provides native packages for major Linux distributions. You can download the latest .deb, .rpm, or .apk package from the GitHub releases page.

  • Generic download command using curl:

    # Replace <package name with the actual package that you need>
    curl -LO https://github.com/pranshuparmar/witr/releases/latest/download/<package-name>
    
  • Debian/Ubuntu (.deb):

    sudo dpkg -i ./witr-*.deb
    # Or, using apt for dependency resolution:
    sudo apt install ./witr-*.deb
    
  • Fedora/RHEL/CentOS (.rpm):

    sudo rpm -i ./witr-*.rpm
    
  • Alpine Linux (.apk):

    sudo apk add --allow-untrusted ./witr-*.apk
    

2.3 Source & Manual Installation

Go (cross-platform)

You can install the latest version directly from source:

go install github.com/pranshuparmar/witr/cmd/witr@latest

This will place the witr binary in your $GOPATH/bin or $HOME/go/bin directory. Make sure this directory is in your PATH.

Manual Installation

If you prefer manual installation, follow these simple steps for your platform:

Unix (Linux, macOS, FreeBSD)

# 1. Determine OS and Architecture
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
[ "$ARCH" = "x86_64" ] && ARCH="amd64"
[ "$ARCH" = "aarch64" ] && ARCH="arm64"
[ "$ARCH" = "loongarch64" ] && ARCH="loong64"

# 2. Download the binary
curl -fsSL "https://github.com/pranshuparmar/witr/releases/latest/download/witr-${OS}-${ARCH}" -o witr

# 3. Verify checksum (Optional)
curl -fsSL "https://github.com/pranshuparmar/witr/releases/latest/download/SHA256SUMS" -o SHA256SUMS
grep "witr-${OS}-${ARCH}" SHA256SUMS | (sha256sum -c - 2>/dev/null || shasum -a 256 -c - 2>/dev/null)
rm SHA256SUMS

# 4. Rename and install
chmod +x witr
sudo mkdir -p /usr/local/bin
sudo mv witr /usr/local/bin/witr

# 5. Install man page (Optional)
sudo mkdir -p /usr/local/share/man/man1
sudo curl -fsSL https://github.com/pranshuparmar/witr/releases/latest/download/witr.1 -o /usr/local/share/man/man1/witr.1

Windows (PowerShell)

# 1. Determine Architecture
if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64") {
    $ZipName = "witr-windows-amd64.zip"
} elseif ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") {
    $ZipName = "witr-windows-arm64.zip"
} else {
    Write-Error "Unsupported architecture: $($env:PROCESSOR_ARCHITECTURE)"
    exit 1
}

# 2. Download the zip
Invoke-WebRequest -Uri "https://github.com/pranshuparmar/witr/releases/latest/download/$ZipName" -OutFile "witr.zip"
# 3. Extract the binary
Expand-Archive -Path "witr.zip" -DestinationPath "." -Force

# 4. Verify checksum (Optional)
Invoke-WebRequest -Uri "https://github.com/pranshuparmar/witr/releases/latest/download/SHA256SUMS" -OutFile "SHA256SUMS"
$hash = Get-FileHash -Algorithm SHA256 .\witr.zip
$expected = Select-String -Path .\SHA256SUMS -Pattern $ZipName
if ($expected -and $hash.Hash.ToLower() -eq $expected.Line.Split(' ')[0]) { Write-Host "Checksum OK" } else { Write-Host "Checksum Mismatch" }

# 5. Install to local bin directory
$InstallDir = "$env:LocalAppData\witr\bin"
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
Move-Item .\witr.exe $InstallDir\witr.exe -Force

# 6. Add to User Path (Persistent)
$UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($UserPath -notlike "*$InstallDir*") {
    [Environment]::SetEnvironmentVariable("Path", "$UserPath;$InstallDir", "User")
    $env:Path += ";$InstallDir"
    Write-Host "Added to Path. You may need to restart PowerShell."
}

# 7. Cleanup
Remove-Item witr.zip
Remove-Item SHA256SUMS

2.4 Run Without Installation

Nix Flake

If you use Nix, you can build witr from source and run without installation:

nix run github:pranshuparmar/witr -- --help
Pixi

If you use pixi, you can run without installation on Linux or macOS:

pixi exec witr --help

2.5 Other Operations

Verify Installation
witr --version
man witr
Shell Completions

witr supports tab completion for all flags. To enable it, add the appropriate line to your shell configuration:

Bash

echo 'eval "$(witr completion bash)"' >> ~/.bashrc
source ~/.bashrc

Zsh

echo 'eval "$(witr completion zsh)"' >> ~/.zshrc
source ~/.zshrc

Fish

witr completion fish | source
# To make it permanent:
witr completion fish > ~/.config/fish/completions/witr.fish

PowerShell

witr completion powershell | Out-String | Invoke-Expression
# To make it permanent, add the above line to your $PROFILE
Uninstallation

If you installed via a package manager (Homebrew, Conda, etc.), please use the respective uninstall command (e.g., brew uninstall witr).

To completely remove script/manual installation of witr:

Unix (Linux, macOS, FreeBSD)

sudo rm -f /usr/local/bin/witr
sudo rm -f /usr/local/share/man/man1/witr.1

Windows

Remove-Item -Recurse -Force "$env:LocalAppData\witr"

3. Interactive Mode (TUI)

Running witr without any arguments or with the -i flag launches the Interactive Mode (TUI). This provides a real-time, terminal-based dashboard with four tabs for exploring processes, ports, containers, and file locks. Combine -i with a target to open the TUI already focused on it: witr -i -p 1234 selects that PID, witr -i nginx pre-fills the process filter, and witr -i -o 5432 / -c web / -f /path open the Ports / Containers / Locks tab with the filter set.

Key Features:

  • Processes Tab: Live, sortable, filterable list of all running processes with a side panel showing the ancestry tree of the highlighted process.
  • Ports Tab: Open/listening ports with the owning processes attached in a side panel. Toggle between LISTEN-only and ALL with a. Enter on an owner opens it, or the container a port is published for; an owner hidden from your user shows the user it runs as (run with sudo to see the process).
  • Containers Tab: All running containers across Docker, Podman, nerdctl, K8s/crictl, Incus, LXC, LXD, and FreeBSD jails in one list - name, image, status, ports, command, plus a per-container detail view with mounts, networks, and compose project metadata.
  • Locks Tab: System-wide file locks (POSIX/FLOCK on Linux, lsof-derived on macOS/FreeBSD). Press a to switch into "all open files" mode, where locked entries are merged with every interesting open fd; type into / to search across the merged set.
  • Process Details: Deep-dive into a process to see its full ancestry tree, child processes, environment variables, working directory, sockets, file context, and more.
  • Process Actions: Send signals (Kill, Terminate, Pause, Resume) or Renice processes directly from the UI (Unix only). Press a on a process in the list or in its detail view; the confirmation names the exact process before anything is sent.
  • Mouse Support: Navigate, sort columns, and click rows using your mouse.
  • Adaptive Theme: Colors adapt automatically to light and dark terminal backgrounds.
  • Auto-Refresh: The process, port, container, and lock lists refresh automatically on an adaptive cadence (starts at 3 seconds, backing off under load).

4. Flags & Options

  -c, --container strings container(s) to look up (repeatable)
      --env              show environment variables for the process
  -x, --exact            use exact name matching (no substring search)
  -f, --file strings     file(s) held open by a process (repeatable)
  -h, --help             help for witr
  -i, --interactive      interactive mode (TUI)
      --json             show result as JSON
      --no-color         disable colorized output
  -p, --pid strings      pid(s) to look up (repeatable)
  -o, --port strings     port(s) to look up (repeatable)
  -s, --short            show only ancestry
  -t, --tree             show only ancestry as a tree
      --verbose          show extended process information
  -v, --version          version for witr
      --warnings         show only warnings

Positional arguments (without flags) are treated as process or service names. Multiple names can be passed. By default, name matching uses substring matching (fuzzy search). Use --exact to match only processes with the exact name.

All target flags (--pid, --port, --file, --container) are repeatable and can be mixed with each other and with positional name arguments. When multiple targets are provided, results are shown sequentially with labeled dividers. All output modes (standard, short, tree, JSON, env, warnings, verbose) work with multiple inputs.

The --container flag searches across Docker, Podman, nerdctl, K8s/crictl, Incus, LXC, LXD, and FreeBSD jails, and matches against container name, image, command, and compose project/service labels, or a container ID (full, short, or a prefix of at least 4 characters).

The TUI is launched if no arguments or relevant flags (--pid, --port, --file, --container) are provided, or if the --interactive flag is explicitly used. It needs a terminal: run without one (from a script, a pipe or CI) and witr exits with code 4 and asks for a target instead. An output mode with no target (witr --json, --short, --tree, --warnings, --verbose or --env) also exits with code 4 and asks for a target, rather than opening the TUI.


5. Core Concept

witr treats everything as a process question.

Ports, services, containers, and commands all eventually map to PIDs. Once a PID is identified, witr builds a causal chain explaining why that PID exists.

At its core, witr answers:

  1. What is running?
  2. How did it start?
  3. What is keeping it running?
  4. What context does it belong to?

6. Example Outputs

💡 Prefer learning by doing? The interactive browser tutorial walks you through outputs like these live on a simulated box — for a better feel of witr, no install required.

6.1 Name Based Query

witr node
Target      : node

Process     : node (pid 14233)
User        : pm2
Command     : node index.js
Started     : 2 days ago (Mon 2025-02-02 11:42:10 +05:30)

Why It Exists :
  systemd (pid 1) → pm2 (pid 5034) → node (pid 14233)

Source      : pm2

Working Dir : /opt/apps/expense-manager
Git Repo    : expense-manager (main)
Sockets     : 127.0.0.1:5001 (TCP | LISTENING, 2 connections)
              127.0.0.1:51744 → 127.0.0.1:5432 (TCP | ESTABLISHED)

6.2 Short Output

witr --port 5000 --short
systemd (pid 1) → PM2 v5.3.1: God (pid 1481580) → python (pid 1482060)

6.3 Tree Output

witr --pid 143895 --tree
systemd (pid 1)
  └─ init-systemd(Ub (pid 2)
    └─ SessionLeader (pid 143858)
      └─ Relay(143860) (pid 143859)
        └─ bash (pid 143860)
          └─ sh (pid 143886)
            └─ node (pid 143895)
              ├─ node (pid 143930)
              ├─ node (pid 144189)
              └─ node (pid 144234)

Note: Tree view includes child processes (up to 10) and highlights the target process.


6.4 Multiple Matches

witr ng
Multiple matching processes found:

[1] nginx (pid 2311)
    nginx -g daemon off;
[2] nginx (pid 24891)
    nginx -g daemon off;
[3] ngrok (pid 14233)
    ngrok http 5000

Re-run with:
  witr --pid <pid>

To avoid substring matching and only find processes with an exact name, use the --exact flag:

witr nginx -x

6.5 File Based Query

witr --file /var/lib/dpkg/lock

Explains the process holding a file open.


6.6 Container Based Query

witr --container redis

Looks up a container by name, ID, image, command, or compose project/service across every detected runtime (Docker, Podman, nerdctl, K8s/crictl, Incus, LXC, LXD, FreeBSD jails). The output includes the container's image and, for Compose services, the Compose file and project directory on the host. Pass --verbose to include mounts.


6.7 Multiple Inputs

witr nginx --port 5432 --pid 1234
----- [name: nginx] -----
Target      : nginx
Process     : nginx (pid 2311)
...

----- [port: 5432] -----
Target      : postgres
Process     : postgres (pid 891)
...

----- [pid: 1234] -----
Target      : node
Process     : node (pid 1234)
...

All target flags are repeatable and can be mixed. Results appear in the order you typed them. All output modes (--short, --tree, --json, --env, --warnings, --verbose) work with multiple inputs.


7. Output Behavior

7.1 Output Principles

  • Single screen by default (best effort)
  • Deterministic ordering
  • Narrative-style explanation
  • Best-effort detection with explicit uncertainty

7.2 Exit Codes

witr returns meaningful exit codes for use in scripts, CI pipelines, and monitoring:

CodeMeaning
0Clean: process found, no warnings
1Warnings: process found but has one or more warnings
2Not found: no matching process or service (also a port no process on this system holds, when witr runs as root or on Windows)
3Permission denied: insufficient privileges (retry with sudo)
4Invalid input: bad arguments or ambiguous match
5Internal error: an unexpected failure occurred
6Cause unknown: process found, but what started it can't be traced (its warnings say why). Not used on Windows, where this is routine

With several targets, the most severe result wins. Cause unknown ranks above warnings but below every failure (2 to 5).

Example Usage:

witr nginx --short
case $? in
  0) echo "All clear" ;;
  1) echo "Warnings detected" ;;
  2) echo "Process not running" ;;
  3) echo "Need elevated privileges" ;;
  4) echo "Invalid input or ambiguous match" ;;
  5) echo "Internal error" ;;
  6) echo "Cannot tell what started it" ;;
esac

7.3 Standard Output Sections

Target

What the user asked about.

Process

Executable, PID, user, command, start time and restart count. The restart count comes from the managing system: a systemd unit, or the container runtime (Docker, Podman, nerdctl and Kubernetes), which also shows the container's restart policy, e.g. Restarts : 12 (policy: unless-stopped).

On Windows the user carries the process's integrity level when it isn't the normal Medium: (elevated) for a process run as administrator, (system integrity), (low integrity) or (untrusted integrity) for sandboxed ones. On Linux, a Security line shows the AppArmor profile or SELinux context confining the process; unconfined processes have none.

Why It Exists

A causal ancestry chain showing how the process came to exist. This is the core value of witr.

When the process that started it has exited, the chain marks the break with ? (original parent exited) (or ? (parent pid N exited) when that parent's PID no longer exists or now belongs to an unrelated process) instead of crediting whatever adopted it.

Source

The primary system responsible for starting or supervising the process (best effort).

Examples:

  • systemd unit with schedule info for timer-triggered services (Linux)
  • launchd service with schedule/trigger details (macOS)
  • SSH session (with remote IP and terminal)
  • docker container
  • pm2
  • cron
  • interactive shell (detects tmux/screen sessions)
  • Snap/Flatpak sandbox (Linux)

Only one primary source is selected. If the original parent has exited and nothing about the process itself (its container, service unit, login session or app scope, or launchd job) explains it, the source is reported as unknown rather than guessed. On systems without such a service manager it stays init, with a note that init only adopted it.

Context (best effort)

  • Working directory
  • Git repository name and branch
  • Container name / image (docker, podman, kubernetes, colima, containerd)
  • Sockets: listeners first, each with the number of connections it accepted, then other sockets; a connection shows local → remote
  • Public vs private bind

Warnings

Non‑blocking observations such as:

  • Process is running as root
  • Dangerous Linux capabilities on non-root processes (CAP_SYS_ADMIN, etc.)
  • Process is listening on a public interface (0.0.0.0 / ::)
  • Restarted multiple times (warning only if above threshold)
  • Process is using high memory (>1GB RSS)
  • Process has been running for over 90 days
  • Deleted binary, library injection indicators (LD_PRELOAD, DYLD_*)
  • Original parent process has exited, so what started the process can't be traced

7.4 JSON Output

--json is meant for scripts and tools, and its output is a contract:

  • Stable: field names, what they mean, and their types. Releases may add fields, so ignore any you don't recognise.
  • Not part of the contract: field order, whitespace, and the wording of human-readable text (Error, Note, Description and warning messages). Match on fields and exit codes, not on sentences.
  • Empty values may be null, an empty list, or left out.
  • Breaking changes (renaming, removing or retyping a field) only ship in a release whose notes call them out.
CommandOutput
witr <target> --jsonThe full report: Target, Process, Ancestry, Source, Warnings and the rest
--short --jsonA list of {PID, Command} from the top of the chain to the process, with PPID and ParentExited where the process that started it has exited
--tree --json{Ancestry, Children}, each a list of the same entries
--warnings --json{PID, Process, Command, Warnings}
--env --json{PID, Process, Command, Env}
A container whose processes aren't visible{Target, Runtime, ContainerID, ContainerName, Image, …, Note}
A failed lookup{Target, Error}, plus Matches when the target was ambiguous
Several targetsA list of the above, one entry per target, in the order given

A test pins every field of every shape, so an accidental rename fails the build.

7.5 Using witr with AI Coding Agents

AI coding agents (Claude Code, Codex, Cursor and others) regularly run into ports that are already in use, leftover dev servers and confusing containers, and work around them by chaining lsof, ps, netstat and docker ps. witr answers the same questions in one command, and two things make it easy for an agent to use:

  • --json prints the result as JSON: for a process, the full report (the process, its ancestry chain, the source that started it and any warnings). A failed or ambiguous lookup prints {Target, Error}, with the candidates in Matches when it is ambiguous, and several targets print an array.
  • Exit codes say what happened without parsing any text (see 7.2 Exit Codes). Exit code 1 means the process was found and has warnings; it is not a failure.

Add a short note like this to your project's agent instructions (AGENTS.md, CLAUDE.md or similar):

## Process and port debugging

Use `witr` instead of chaining lsof/ps/netstat/docker commands:

- Port already in use: `witr --port <PORT> --json`
- Unknown or stuck process: `witr <name> --json`, or `witr --pid <PID> --tree`
- Container: `witr --container <name or ID> --json`

Exit codes: 0 found, 1 found with warnings (not a failure), 2 not found,
3 permission denied (retry with sudo), 4 ambiguous name or bad input
(re-run with --pid), 5 internal error, 6 found but what started it can't
be traced. Run `witr --help` for all options.

Official agent skill

For fuller guidance, install the official skill: it tells an agent which command fits the situation, how to read the JSON and exit codes, and to ask before stopping anything witr finds. The witr binary still needs to be installed.

  • Claude Code: run /plugin marketplace add pranshuparmar/witr, then /plugin install witr@witr.
  • Other agents that read Agent Skills, or a manual install: copy plugins/witr/skills/witr into the agent's skills folder (for Claude Code, ~/.claude/skills/).

8. Platform Support

  • Linux (x86_64, arm64, loong64) - Full feature support (/proc).
  • macOS (x86_64, arm64) - Uses ps, lsof, sysctl, pgrep.
  • Windows (x86_64, arm64) - Native Win32 APIs (ToolHelp32, PSAPI, Service Control Manager). No PowerShell or WMI dependency.
  • FreeBSD (x86_64, arm64) - Uses procstat, ps, lsof.

8.1 Feature Compatibility Matrix

FeatureLinuxmacOSWindowsFreeBSDNotes
Process Selection
By Name✅✅✅✅
By PID✅✅✅✅
By Port✅✅✅✅
By File✅✅✅✅
By Container✅✅✅✅Requires the runtime CLI on PATH (docker/podman/nerdctl/crictl/incus/lxc/lxc-ls/jls).
Multiple/mixed inputs✅✅✅✅Repeatable flags, mixed types.
Exact Match✅✅✅✅
Full command line✅✅✅✅
Process start time✅✅✅✅
Working directory✅✅✅✅
Environment variables✅⚠️⚠️✅macOS: SIP restrictions; Windows: protected processes inaccessible.
Network
Listening ports✅✅✅✅
Connections (remote end)✅✅✅✅Connections show their remote end; connections a listener accepted are counted on its row.
Bind addresses✅✅✅✅
Port → PID resolution✅✅✅✅
Port → Container fallback✅✅✅✅Used when the port is owned by PID 1 via systemd socket activation or a container runtime. A port published by Docker's docker-proxy, Docker Desktop's forwarders (com.docker.backend, plus wslrelay on Windows), rootless Podman's rootlessport or pasta, or RootlessKit (rootless nerdctl and Docker), is explained by the container's own process when it is visible, and by this view otherwise. So is a port that no process holds but a Docker, Podman or nerdctl container publishes (published through firewall rules). In the TUI's Ports tab, opening such a port's owner shows the container.
Service Detection
Service Manager✅✅✅✅Linux: systemd, macOS: launchd, Windows: Services, FreeBSD: rc.d
Service Description✅✅✅✅Linux: Description, macOS: Comment, Windows: Display Name, FreeBSD: rc header
Configuration Source✅✅✅✅Linux: Unit File, macOS: Plist, Windows: Registry Key, FreeBSD: Rc Script
Supervisor✅✅✅✅
Containers✅✅✅✅Docker (plus compose mappings), Podman, nerdctl, K8s (Kubepods/crictl), Containerd. Colima on macOS/Linux. Incus/LXC/LXD on Linux. Jails on FreeBSD.
SSH session detection✅✅✅✅Detects remote IP and terminal.
tmux/screen detection✅✅❌✅Shows session name in source.
Schedule detection✅✅❌❌Linux: systemd timers, macOS: launchd intervals/calendar.
Restart count✅⚠️⚠️❌systemd restarts on Linux; container restart count and policy wherever Docker, Podman, nerdctl or Kubernetes runs.
Exited parent detection✅✅⚠️✅Marks where the process that started it exited. Windows shows the break but doesn't treat it as a finding (no exit code 6): its launchers routinely exit.
Snap/Flatpak detection✅❌❌❌
Health & Diagnostics
CPU usage detection✅✅✅✅
Memory usage detection✅✅✅✅
Health status detection✅✅✅✅
Open Files / Handles✅✅⚠️✅Windows: count only.
File Locks✅✅❌✅Linux: /proc/locks; macOS/FreeBSD: derived from lsof/fstat.
Deleted binary detection✅✅✅✅Warns if executable is missing.
Capability warnings✅❌❌❌Warns about dangerous capabilities on non-root processes.
Security context✅❌✅❌Linux: AppArmor profile or SELinux context; Windows: integrity level (elevated, system, low).
Context
Git repo/branch detection✅✅✅✅
Interactive Mode (TUI)
Processes Tab✅✅✅✅
Ports Tab✅✅✅✅
Containers Tab✅✅✅✅
Locks Tab✅✅❌✅Toggle (a) shows all open files.
Process Details✅✅✅✅
Process Actions✅✅❌✅

Legend: ✅ Full support | ⚠️ Partial/limited support | ❌ Not available


8.2 Permissions Note

Linux/FreeBSD

witr inspects system directories which may require elevated permissions.

If you are not seeing the expected information, try running witr with sudo:

sudo witr [your arguments]

Without root, a port held by another user's process still shows which user it belongs to (it belongs to postgres), but not the process. With root, a port that no process on the system holds is reported as such (exit code 2): on WSL that's usually a process in another distro, since all distros share one network.

macOS

On macOS, witr uses ps, lsof, and launchctl to gather process information. Some operations may require elevated permissions:

sudo witr [your arguments]

Note: Due to macOS System Integrity Protection (SIP), some system process details may not be accessible even with sudo.

Windows

On Windows, witr talks directly to Win32 APIs (ToolHelp32, PSAPI, Service Control Manager) rather than spawning PowerShell or WMI, startup is fast and there's no Get-CimInstance hang. To see details for processes owned by other users or system services, you must run the terminal as Administrator.

# Run in Administrator PowerShell
.\witr.exe [your arguments]

9. Success Criteria

witr is successful if:

  • A user can answer "why is this running?" within seconds
  • It reduces reliance on multiple tools
  • Output is understandable under stress
  • Users trust it during incidents

10. Sponsors

Special thanks to the people who supported witr ❤️

witr witr

// faq

What is witr?

Why is this running? Trace any process, port, container, or file back to what started it - CLI + TUI. . It is open-source on GitHub.

Is witr free to use?

witr is open-source under the Apache-2.0 license, so it is free to use.

What category does witr belong to?

witr is listed under uncategorized in the Claudeers registry of Claude-compatible tools.

4 views
★ 22,578 stars
unclaimed
updated about 24 hours ago

// embed badge

witr on Claudeers
[![Claudeers](https://claudeers.com/api/badge/witr.svg)](https://claudeers.com/witr)

// retro hit counter

witr hit counter
[![Hits](https://claudeers.com/api/counter/witr.svg)](https://claudeers.com/witr)

// reviews

// guestbook

0/500

// related in Uncategorized / Others

🔓

Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.

// uncategorizedn8n-io/⟨TypeScript⟩★ 205,721◷ NOASSERTION[ claude ]
🔓

The agent engineering platform.

// uncategorizedlangchain-ai/⟨Python⟩★ 146,945◷ MIT[ claude ]
🔓

FULL Augment Code, Claude Code, Cluely, CodeBuddy, Comet, Cursor, Devin AI, Junie, Kiro, Leap.new, Lovable, Manus, NotionAI, Orchids.app, Perplexity, Poke, Q…

// uncategorizedx1xhlol/★ 143,887◷ GPL-3.0[ claude ]
🔓

100+ AI Agent & RAG apps you can actually run — clone, customize, ship.

// uncategorizedShubhamsaboo/⟨Python⟩★ 140,637◷ Apache-2.0[ claude ]

// built by

1 of its contributors also build on official projects — claude-code, claude-cookbooks, claude-plugins-official

→ see how witr connects across the ecosystem