Brand logo
HomeHardwarePolicy & RegulationSoftwareCommunicationsConsumer ElectronicsGeneral
  1. Home
  2. /
  3. software
  4. /
  5. proc-port-pid-name-path-workflow

proc 1.14.5 in Your Software Stack: Inspect, Pause, and Clear Runaway Processes on macOS, Linux, and Windows

By Sarah Chen · MyTechDailyNews, Software desk

Deadlines usually slip over process chores rather than architecture: a dev server that will not bind, a build that outlived the terminal that launched it, a port quietly held by something nobody can name. proc is a semantic command-line tool for process work on macOS, Linux, and Windows, and its version 1.14.5 update is organised around one idea — address a process the way you already describe it out loud. A leading colon means a port, a bare number means a PID, and anything else is compared against process names and full command lines. This guide maps that grammar across nineteen commands and three jobs, flags the permission-sensitive corners, and shows where one command replaces a pipeline of lsof, ps, grep, pgrep, xargs, kill, and sleep.

For a daily-tools reader, three things decide whether a CLI earns a place in the workflow: what it actually does, how much trust it costs, and what you can type right now. On the trust question, proc is conservative by default — it asks before changing state, and --dry-run converts any change into a preview. On the typing question, every example below uses the same four target shapes: port 3000, PID 1234, the name node, or a path.

The target grammar: six shapes that name a process

  • Leading colon = port. :3000 selects the listener for port 3000. Paired with kill, that listener ends immediately via SIGKILL; the tool asks before changing state, and --dry-run supplies the preview instead.
  • Bare number = PID. 1234 affects only process 1234, and no other process in the table.
  • Anything else = name. node is checked against both the name and the full command line of every process, so nodemon and node server.js match too. Under kill, each matched node process is listed first and ended only after confirmation.
  • Commas build a target group. :3000,:8080,node is handled together after a single confirmation, and a process that matches more than one selector is still acted on only once.
  • --in narrows by folder. node --in . limits node matches to the current folder and its subfolders, which keeps your editor and other projects out of the blast radius. Most commands accept --in.
  • A path is a file selector for the for command. ./server.py — relative, absolute, or starting with ~ — finds processes running server.py from this folder; ./logs/app.log finds processes with app.log open, such as a server still writing to it.

Phase one: read-only discovery

on — the answer to "what is there?"

Use on to inspect without modifying anything. Against :3000 it returns the listening process with name, PID, folder, CPU, memory, and running time. Against 1234 it returns that process plus every port it listens on. Against node it returns each matching process and its ports. Hand it the group :3000,:8080,node and it answers all three questions in one pass — what sits on those two ports, and which ports the node processes hold. Add --in . and the reply covers only node processes started under this folder.

why — the answer to "how did it get here?"

why traces origin. proc why :3000 walks backward through parent processes from the listener on port 3000 and reveals the start point: a terminal tab, a tmux session, an editor. With 1234 it prints the parent chain that produced that process, along with each parent's running time. With node it traces every matching process to whatever launched it, and with :3000,:8080 it returns one parent chain per held port.

for, by, in — file, name, and folder searches

Three commands, three axes. for works on files: ./server.py finds processes running server.py from this folder, and ./logs/app.log finds processes that have app.log open — a long-running server still writing to its own log is the typical case. by works on names: node lists every process whose name or command line matches, and node --in . trims that list to the current folder and below. in works on folders: . lists everything started where you are standing, while ~/code/shop lists everything started in ~/code/shop wherever you run the command — and it still resolves even if that folder has since been deleted.

list and info — inventory and dossier

With no target, list walks every process and sorts by highest resource use first. Add node to filter to matching processes. Add --status zombie to surface exited work its parent never cleaned up; --status also accepts running, sleeping, and stopped. When you need the whole record, info 1234 returns folder, path, user, parent, status, CPU, memory, and uptime for PID 1234; :3000 returns the same full detail for the listener; node returns it for every match.

ports and tree — network view and lineage view

ports with no target lists every listening port and the process using it. --exposed cuts the output down to ports reachable by other machines — those listening on 0.0.0.0 or :: — while --local keeps the localhost ones. --in . shows only ports held by processes started in this folder. tree answers a different question: with no target it prints every process as parents and children; node prints each node process together with the processes it started; and 1234 --ancestors reverses the direction, climbing from PID 1234 up to the first process the system started.

orphans and stuck — two hunts with an optional kill switch

orphans finds processes whose parent has exited, which is exactly the profile of dev servers left behind after a terminal closes; system services are omitted from the result. With no target it checks all parentless processes, --in . limits the scan to this folder, and --in . --kill shows those orphans, asks, and then ends them. stuck looks for busy long-running work: with no target it reports processes running over 5 minutes that currently use more than half a CPU, and --kill ends whatever it finds after display and confirmation.

Phase two: changing process state

kill and stop — hard exit versus graceful exit

kill is immediate termination. :3000 kills the listener on port 3000 with SIGKILL, 1234 kills only PID 1234, node lists every match and ends them after confirmation, :3000,:8080,node clears the whole group after one confirmation, and node --in . kills only the node processes located under the current folder.

stop is the polite version. :3000 asks the listener on port 3000 to exit with SIGTERM and forces it after 10 seconds if it is still there; 1234 behaves the same way for that PID; node gracefully stops every match after confirmation; node --in . limits the stop to the current folder. You can also swap the signal: :3000 --signal HUP sends HUP instead of SIGTERM, and many servers treat HUP as "reload your config" — the fastest way to apply a config change without dropping the port.

free — when the port is the goal, not the process

free works on ports only. :3000 stops the process holding port 3000 politely first and forcefully second, then confirms the port is genuinely free. Commas combine ports, so :3000,:8080 frees both in one operation.

freeze and thaw — pause the build, keep the process

freeze pauses without ending. On macOS and Linux, node sends SIGSTOP to every matching process; 1234 pauses PID 1234 — the practical use being a heavy build that you freeze while you need the machine back; :3000 pauses the listener, which leaves existing connections hanging until you thaw it. thaw reverses it: node resumes previously frozen node processes with SIGCONT, and 1234 resumes PID 1234 whether proc freeze or Ctrl+Z paused it.

unstick — recovery attempted before termination

With no target, unstick finds stuck processes, wakes them with SIGCONT, and interrupts them the way Ctrl+C would; nothing is terminated unless you add --force. unstick 1234 runs the same gentle recovery on that PID. node --force escalates, falling back to terminating stuck node processes with SIGTERM and then SIGKILL.

Phase three: watching and waiting

watch

watch is live monitoring. With no target it renders a busy-first table refreshed every 2 seconds, and q quits. node restricts the display to node processes; :3000 restricts it to the listener on port 3000.

wait

wait blocks until a target exits, which is what makes it useful in scripts. :3000 waits until the process on port 3000 has gone, letting a script launch the next server; 1234 waits for that PID. In CI, node --timeout 60 abandons the wait after 60 seconds if node processes remain, preventing the job from hanging forever, and a timed-out --timeout exits 1 so the pipeline can fail loudly instead of silently.

Shared behavior: one grammar for every command

Every command accepts the same target forms, which is the main reason the tool is guessable on the first try. Almost all of them support --in for project scoping, --json for machine-readable output, and --dry-run to preview a change before it happens. Listing flags narrow the search instead of acting on it: --status filters process states, --exposed filters ports. --kill takes whatever a listing command discovered and applies that command's action to it after asking — the same confirmation flow as proc kill. The whole surface is nineteen commands covering three jobs: inspect, change state, and watch or wait.

Permissions, exposure, and the checks worth running on shared machines

Two read-only commands carry real security value for anyone on a shared host or a laptop that visits untrusted networks. proc ports --exposed lists the ports other machines can reach, meaning those bound to 0.0.0.0 or ::, so a dev database or admin panel that was supposed to stay on localhost is easy to spot; proc ports --local shows the localhost set for comparison. proc orphans --in . reveals background servers you started days ago and forgot about — a forgotten listener is both a resource leak and an exposure. On the acting side, note the asymmetry: --dry-run only identifies what would be touched, nothing is terminated by unstick unless --force is supplied, and a permission problem is reported as a distinct exit code (3) rather than a silent partial success.

Step by step: reclaiming port 3000

The classic blocker is a dev server that cannot start because port 3000 is taken. The workflow below locates the old tmux session that holds it, releases the port, and cleans up the other processes left running.

  1. Identify, don't guess. Run proc on :3000 and read the name, PID, folder, CPU, memory, and running time of the listener.
  2. Trace the origin. Run proc why :3000. The parent chain tells you whether the listener came from a terminal tab, a tmux session, or your editor — that determines whether killing it also kills your session.
  3. Pull scope into the project. Run proc list --in . and proc ports --in . to see everything else this folder started and the ports those processes hold.
  4. Preview. Run the intended change with --dry-run so the target list is visible before anything moves.
  5. Ask first. Run proc stop :3000, which sends SIGTERM and only forces the issue after 10 seconds. Reserve proc kill :3000 for a listener that ignores SIGTERM.
  6. Verify the port is actually free. Run proc free :3000 — it politely and forcefully stops the holder, then confirms the port is truly released. If several ports are stuck, :3000,:8080 handles both in one operation.
  7. Sweep the leftovers. Run proc orphans --in . --kill to display and, after confirmation, end parentless processes from this folder.
  8. Hand off to the script. If the next launch is automated, proc wait :3000 blocks until the old process has exited, and proc watch :3000 keeps the new listener on screen.

proc versus the shell pipeline

All of this is achievable with lsof, ps, grep, pgrep, xargs, kill, and sleep. The difference is that proc removes the need to remember lsof flags or to pipe PIDs into kill, and it adds a confirmation step in front of every state change.

TaskShell pipelineproc command
Who owns port 3000?lsof -i :3000 -P -nproc on :3000
Where did it come from?lsof -i :3000, then ps -o ppid= up the chainproc why :3000
Release the portlsof -t -i:3000 | xargs kill && sleep 1 && lsof -i:3000proc free :3000
Block until the jobs are gonewhile ps aux | grep node | grep -v grep; do sleep 5; doneproc wait node
Suspend instead of endkill -STOP $(pgrep node)proc freeze node
Hunt leftover processesNo standard toolproc orphans --in .

Install channels for version 1.14.5

The documented install line is brew install yazeed/proc/proc on macOS. Version 1.14.5 also reaches users through npm, cargo, Scoop, Nix, and Docker, so pinning the tool into a project image or a shared devcontainer is a packaging choice rather than a manual task — which matters for teams that want the same command surface on Windows, Linux, and macOS boxes.

Automation and coding-agent use

The tool is explicitly aimed at scripts and coding agents rather than only at interactive use. Each command emits one JSON document when you pass --json, and the exit codes are fixed: 0 success, 1 error, 2 not found, 3 permission denied, 4 invalid input. --dry-run only identifies what would be touched, so an agent can plan a change without risk. An agent skill teaches Claude Code, Codex, Cursor, Gemini CLI, and similar tools when to reach for proc. In the documented example proc on :8080 --json | jq '.process | {pid, cwd, uptime_secs}', the sample values returned are pid 177, cwd /home/dev/code/shop, and uptime_secs 35.

Numbers worth quoting

  • Current release: 1.14.5, distributed through brew, npm, cargo, Scoop, Nix, and Docker.
  • Release cadence: nineteen releases since March, according to the changelog roundup dated October 25, 2026.
  • Command surface: nineteen commands across three jobs — inspect, change state, watch or wait.
  • Grace window: stop escalates to a forced kill after 10 seconds of SIGTERM.
  • Heuristic thresholds: stuck flags processes running over 5 minutes that use more than half a CPU.
  • Refresh and timeout behaviour: watch redraws every 2 seconds; wait node --timeout 60 gives up after 60 seconds and exits 1.
  • Script contract: exit codes 0, 1, 2, 3, 4 map to success, error, not found, permission denied, invalid input.
  • Sample JSON payload: pid 177, cwd /home/dev/code/shop, uptime_secs 35.

Common misconceptions

  • "A name only matches the executable." It does not. node is checked against the name and the full command line, which is why nodemon and node server.js appear in the same result — useful, until you remember that a broad name is a broad blast radius.
  • "stop and kill are the same thing." kill uses SIGKILL immediately; stop sends SIGTERM and only forces after 10 seconds, so processes that clean up temp files or flush logs should be stopped, not killed.
  • "freeze ends the process." freeze sends SIGSTOP on macOS and Linux and simply pauses it; thaw resumes it with SIGCONT. The catch is that freezing a listener leaves its connections hanging until thaw.
  • "orphans lists everything without a parent." System services are deliberately omitted, so treat it as a dev-leftover finder rather than a full process audit.
  • "--dry-run still handles the obvious ones." It only identifies what would be touched; nothing is changed.
  • "--in . is a listing nicety." Most commands accept --in, so the same scoping that trims a list also protects your editor during a kill or stop.
  • "wait is safe in CI." An unbounded wait is exactly what hangs a job; use --timeout 60 so it abandons after 60 seconds and exits 1.

FAQ

Is this Windows-only, or does the grammar hold across all three platforms?

proc covers process work on macOS, Linux, and Windows with the same target forms everywhere. Where the platforms diverge is the pause mechanism: on macOS and Linux, freeze sends SIGSTOP and thaw sends SIGCONT.

How do I stop a name selector from taking down unrelated processes?

Use folder scoping. Because node also matches nodemon and node server.js, node --in . limits the operation to processes started in the current folder and its subfolders. Then run it once with --dry-run to read the target list, and remember that even a batch such as :3000,:8080,node is confirmed once and applied once per process.

What is the difference between kill, stop, free, and unstick?

kill is immediate SIGKILL. stop is polite SIGTERM with a forced escalation after 10 seconds, and --signal HUP swaps the signal — many servers treat HUP as "reload your config". free is port-specific and verifies the port is truly released afterwards. unstick tries recovery first: SIGCONT plus a Ctrl+C-style interrupt, terminating nothing unless --force is given.

Can I script against it safely?

Yes. Pass --json for a single machine-readable document, branch on the fixed exit codes 0, 1, 2, 3, 4, and keep --timeout on wait so a stuck target cannot block a pipeline indefinitely. The jq example above shows the shape of the payload you parse.

Which install route should I pick?

The documented line is brew install yazeed/proc/proc; npm, cargo, Scoop, Nix, and Docker all deliver version 1.14.5 as well. Match the channel to how the machine is already provisioned so upgrades stay automatic.

Do I have to unlearn the Unix signals reference?

No — proc is a wrapper around the same semantics, so SIGTERM, SIGKILL, SIGSTOP, and SIGCONT behave exactly as the signal documentation describes; what changes is that you address processes by port, PID, name, path, or folder instead of assembling the signal call by hand.

Action checklist for the Software desk

  1. Memorise the three selector shapes before anything else: leading colon is a port, bare number is a PID, everything else is a name matched against the command line.
  2. Make proc on and proc why your default first moves — they change nothing and both handle grouped targets.
  3. Scope by folder with --in . in shared directories, including the cleanup case proc orphans --in . --kill.
  4. Preview any state change with --dry-run, and let the confirmation prompt stay on: bypassing it is how a name selector reaches the wrong project.
  5. Reach for stop before kill, and for --signal HUP when a server can reload its config in place.
  6. Prefer free over kill whenever the objective is the port rather than the process.
  7. Run proc ports --exposed monthly on any machine that hosts dev services, and compare with --local.
  8. Add --json plus the documented exit-code contract to CI, always with --timeout 60 on wait.

Related reading from MyTechDailyNews

  • What's new in proc: nineteen releases since March — October 25, 2026
  • Unix signals: the complete reference — March 10, 2026
  • nohup vs disown vs &: running background processes — March 10, 2026
  • Managing child processes in Node.js — March 10, 2026

If your process work currently lives in half-remembered lsof flags and copy-pasted kill pipelines, version 1.14.5 is worth an afternoon: install it through whichever channel already owns your machine, learn the four target shapes, and keep the read-only commands as your reflex. The value is not a new capability — SIGTERM and SIGSTOP have been available for decades — but a single grammar that lets you ask what is on port 3000, why it is there, and how to clear it before your next build starts. Questions or tips for the Software desk: hello@techdaily.com.

Brand logo

Tech Daily

Your Daily Source for Consumer Tech, Policy & Communications

HardwarePolicy & RegulationSoftwareCommunicationsConsumer ElectronicsGeneralAPAC EdmGrowth

© 2026 Tech Daily.

Cookie Notice

We use cookies to improve your experience and analyze website traffic. Read our Privacy Policy to learn more.