witr
The witr skill traces running processes, ports, containers, and file locks back to their origins, identifying which systemd unit, launchd job, container, cron…
Community author
- Agents
- Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode, claude.ai and API
- License
- Apache-2.0 (permissive)
- Pin
- 7e46fa6pinned Oct 9, 2026
- Context cost
- about 1,200 tokenswhen the skill loads
- GitHub stars
- 22,629on pranshuparmar/witr
- Scripts
- None found
What it does
“Explains why a process is running and what started it, using the witr CLI. Use when a port is already in use (EADDRINUSE), a dev server or other process was left running, an unknown or stuck process needs explaining, or you need to know which service, container, shell, supervisor or scheduled job started a process, holds a port or holds a file lock. Use it instead of chaining lsof, ps, ss, netstat and docker ps.”
Generated summary from the skill's own text
The witr skill traces running processes, ports, containers, and file locks back to their origins, identifying which systemd unit, launchd job, container, cron job, or other manager started them. It provides detailed process information in JSON format and suggests appropriate stop commands based on the process manager type.
When to use it
- Resolving EADDRINUSE errors and finding which process holds a port
- Identifying what started or manages a running process or container
- Finding which application holds a file lock or socket
- Investigating stuck, unknown, or unexpected processes on the system
When not to
- When you need to directly stop or kill processes, as witr only analyzes and reports
- If you lack permissions to inspect system processes without sudo
Install
These commands install from the publisher's repository and need no account.
skills CLI
npx skills add pranshuparmar/witr --skill witrInstalls from the repository's default branch, which may have changed since the commit we checked.
GitHub CLI 2.90 or later
gh skill install pranshuparmar/witr witr@7e46fa68151fd7c59fb7a0cf4247a9a0ac0fbb6eInstalls the commit we checked (7e46fa6).
Copy by hand
Download the folder at 7e46fa6 and put it in .claude/skills/witr for Claude Code and in .agents/skills/witr for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode.
Copy for your agent
A prompt for any coding agent. It installs this skill from GitHub at the pinned commit, copies the files as they are, and runs nothing unless you ask.
Prompt
Install the agent skill "witr" by pranshuparmar. Source, pinned to commit 7e46fa68151fd7c59fb7a0cf4247a9a0ac0fbb6e: https://github.com/pranshuparmar/witr/tree/7e46fa68151fd7c59fb7a0cf4247a9a0ac0fbb6e/plugins/witr/skills/witr 1. Download that folder at exactly this commit. Do not use the default branch. 2. Copy every file unchanged, keeping the folder structure, into .claude/skills/witr/ for Claude Code and .agents/skills/witr/ for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode. Create the folders if they do not exist. 3. Do not edit the files, and do not run any script in the folder unless I ask you to. 4. When you are done, list the files you copied and where you put them. Listing and checks: https://www.agentnative.dev/skills/pranshuparmar/witr
SKILL.md at the pin
---
name: witr
description: Explains why a process is running and what started it, using the witr CLI. Use when a port is already in use (EADDRINUSE), a dev server or other process was left running, an unknown or stuck process needs explaining, or you need to know which service, container, shell, supervisor or scheduled job started a process, holds a port or holds a file lock. Use it instead of chaining lsof, ps, ss, netstat and docker ps.
license: Apache-2.0
---
# witr: why is this running?
`witr` traces a process, port, container or open file back to what started it and keeps it running (a systemd unit, launchd job, container, cron job, shell, PM2 or supervisor, a Windows service, ...), and flags anything suspicious. It only reads. It never stops, kills or changes anything.
Reach for it instead of chaining `lsof`, `ps`, `ss`, `netstat` and `docker ps`.
## Before you start
Check that it's installed with `witr --version`. If it isn't, tell the user and suggest one of these; don't install anything without asking:
- macOS or Linux: `brew install witr`, or `curl -fsSL https://raw.githubusercontent.com/pranshuparmar/witr/main/install.sh | bash`
- Windows: `winget install -e --id PranshuParmar.witr`
- With Go: `go install github.com/pranshuparmar/witr/cmd/witr@latest`
Always give a target and `--json`. Without a target, `--json` exits with code 4 and asks for one; a bare `witr` opens an interactive dashboard, or exits with code 4 when there's no terminal.
## Pick the command
| Situation | Command |
|-----------|---------|
| Port already in use (`EADDRINUSE`) | `witr --port 3000 --json` |
| A process by name | `witr node --json` (matches substrings; add `--exact` for the exact name) |
| A known PID | `witr --pid 1234 --json` |
| A container | `witr --container web --json` (name, image, Compose service or ID prefix) |
| What holds a file or lock | `witr --file /var/lib/dpkg/lock --json` |
| Just the chain of parents | `witr --pid 1234 --short` (one line) or `--tree` |
| Several things at once | `witr --port 3000 --port 5432 --json` (a JSON list, one entry per target, in order) |
| A process's environment | `witr --pid 1234 --env --json` |
| More detail | add `--verbose` (memory, I/O, open files, socket state) |
## Read the result
Check the exit code first:
| Exit | Meaning | What to do |
|------|---------|------------|
| 0 | Found, no warnings | Report it |
| 1 | Found, with warnings. Not a failure | Report it and mention the warnings that matter |
| 2 | Not found | Nothing on this system runs or listens there; say so. For a port, `Error` may say something outside this system (another WSL distro, a VM) holds it |
| 3 | Permission denied | It belongs to another user; suggest re-running with `sudo`, and ask first |
| 4 | Ambiguous or bad input | `Matches` lists the candidates: re-run with `--pid` for the right one, or fix the input |
| 5 | Internal error | Report the `Error` |
| 6 | Found, but what started it can't be traced (Linux, macOS, FreeBSD) | The process that started it has exited; say so |
With several targets, the most severe result wins.
Then the JSON (the full contract is in the README, section "7.4 JSON Output"):
- **Found:** `Process` (`PID`, `Command`, `Cmdline`, `User`, `StartedAt`, `WorkingDir`, `Sockets`, ...), `Ancestry` (the chain from the top down to the process), `Source` (`Type`: `systemd`, `launchd`, `bsdrc`, `container`, `shell`, `ssh`, `cron`, `supervisor`, `windows_service`, `init` or `unknown`; `Name`; `Description`), `Warnings`, and `Container` when it runs in one.
- **Failed lookup:** `{Target, Error}`, plus `Matches` when the target was ambiguous.
- **`--short --json`:** a list of `{PID, Command}`. Where the process that started one has exited, that entry also has `PPID` and `ParentExited: true`.
- **A container whose processes aren't visible** (Docker Desktop, a VM): `{ContainerName, Image, Ports, ..., Note}`.
Match on fields and exit codes, not on wording: the text of `Error`, `Note`, `Description` and warnings can change between releases.
## Explain it to the user
Lead with the answer: what it is, and what started it. For example: "Port 3000 is held by `node` (pid 4821), started by PM2 from `~/work/api`." Mention warnings that matter, such as a public bind, running as root, a deleted binary or a restart loop.
## Freeing a port or stopping something
witr only explains. Don't kill or stop anything on your own: tell the user what holds the port and what manages it, and ask before acting.
When they agree, stop it through whatever manages it, or it will come straight back. Use `Source.Type`, `Source.Name` and `Container`:
| Managed by | Stop with |
|------------|-----------|
| systemd | `systemctl stop <unit>` (`--user` for a user unit) |
| launchd | `launchctl bootout gui/$(id -u)/<label>` (`sudo launchctl bootout system/<label>` for a daemon) |
| FreeBSD rc (`bsdrc`) | `service <name> stop` |
| Docker / Podman | `docker stop <name>` / `podman stop <name>` |
| PM2 | `pm2 stop <name>` |
| supervisor | `supervisorctl stop <name>` |
| Windows service | `Stop-Service <name>` |
| A shell or nothing traceable | `kill <pid>` (`Stop-Process -Id <pid>` on Windows) |
From pranshuparmar/witr at 7e46fa6, shown as plain text under its license: Apache-2.0 (permissive). The license text is in plugins/witr/skills/witr/SKILL.md.
View SKILL.md on GitHub at 7e46fa6Files
- SKILL.md5.2 KB · 12454fb19183
1 file, 5.2 KB in total. Each file has a sha256 in the pin's manifest; the first 12 characters are shown.
Skill folder on GitHub at 7e46fa6Related in Cloud and DevOps
debug-openshell-cluster
Diagnoses OpenShell gateway deployment problems across Docker, Podman, Kubernetes, and VM compute platforms.
by NVIDIAOfficial publisher
Claude Code, Codex, Cursor +4 · about 19.1K tokens · pinned 6 days ago
huggingface-spaces
Create and deploy machine-learning applications on Hugging Face Spaces using Gradio, Docker, or Static SDKs.
by Hugging FaceOfficial publisher
Claude Code, Codex, Cursor +4 · about 4.3K tokens · pinned 6 days ago
upgrading-mwaa-environments
Upgrades an MWAA environment to a newer Apache Airflow version by computing the optimal version-jump path, selecting a deployment approach (new environment…
by Amazon (AWS)Official publisher
Claude Code, Codex, Cursor +4 · about 7K tokens · pinned 6 days ago
deploying-airflow
This skill guides deploying Airflow DAGs and projects using Astro (Astronomer's managed platform), open-source Airflow on Docker Compose, or Kubernetes with…
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.7K tokens · pinned 6 days ago
deploying-go-sdk-bundles
This skill builds, packs, and deploys Go SDK bundles as self-contained AFBNDL01 executable artifacts for Airflow's ExecutableCoordinator to run.
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 1.7K tokens · pinned 6 days ago
deploying-java-sdk-bundles
This skill teaches how to build Java SDK bundles as JAR files using Gradle or Maven, then deploy them to Airflow workers so the coordinator can execute Java…
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.6K tokens · pinned 6 days ago