Port Pilot

See every local service, understand what launched it, check whether it is healthy, and stop it safely — from a native macOS menu bar companion or an agent-ready terminal toolkit.

npm install && npm run build && npm link
ports
 Port Pilot                 development services   sort: port   4 processes

   Port   Project              Framework   PID     Memory    HTTP       Cmd
  3000   my-blog              Astro       8595    60 MB     200 18ms   node
   4321   site-inspector       Astro       10772   64 MB     200 12ms   node
   5173   client-app           Vite        9201    85 MB     200 9ms    node
   5432   —                    —           1234    50 MB     —          postgres
   8080   api-server           Node.js     4500    200 MB    204 7ms    node
     80   —                    —           1214    26 MB     200 5ms    caddy

 [K] Stop safely  [o] Open  [u/p/c/d] Copy  [f] Filter  [/] Search  [q] Quit

Features

🔍

Native Menu Companion

Browse, search, inspect, open, copy, monitor, and safely stop local services without leaving the macOS menu bar.

Safe Process Trees

Preview the target and confirm before Port Pilot stops descendants and the owning listener gracefully.

🌐

Open in Browser

Press O to open localhost:PORT in your default browser. No copy-pasting URLs.

📝

Open in Editor

Press E to open the project folder in Cursor or VS Code. Jump straight into the code.

🎯

Filter & Search

Start with likely development services, switch to every listener explicitly, or search by project, port, and command.

📊

Health & Context

See HTTP status, page title, Docker mapping, owner, ancestry, CPU, memory, and uptime at a glance.

Keyboard Shortcuts

The TUI dashboard is fully keyboard-driven.

↑ ↓ Navigate up / down
K Preview and confirm safe stop
o Open in browser
e Open in editor
f Cycle filter mode
s Cycle sort field
/ Search
r Refresh

CLI Commands

For quick, non-interactive use.

$ ports check 3000
● Port 3000 is in use

  PID:       8595
  Command:   node
  Project:   my-blog
  Framework: Astro
  Directory: /Users/you/dev/my-blog
  Memory:    60 MB
  Uptime:    3d 0h

  Kill it with: ports kill 3000
$ ports kill 3000
Stop this process tree with SIGTERM? [y/N] y
✓ Freed port 3000; signaled 2 processes
$ ports check 9999
✓ Port 9999 is free

How It Works

1

Uses lsof on macOS or ss on Linux to find every listening TCP port on your machine.

2

Parses PIDs and port numbers, deduplicates IPv4/IPv6 entries for the same process.

3

Adds process owner, ancestry, working directory, CPU, memory, and uptime, then detects projects and frameworks.

4

Probes likely HTTP services with short timeouts and maps published ports to Docker containers when available.

5

Serves the same typed records to the live TUI, JSON commands, availability checks, waits, aliases, and lifecycle events.

Tech Stack

TypeScriptLanguage
Ink + ReactTerminal UI
Commander.jsCLI commands
SwiftUImacOS companion
execaSystem commands
tsupBundler

Get Started

Install
# Clone the repo, then:
npm install
npm run build
npm link

# Now use it from anywhere:
ports              # interactive dashboard
ports list         # static table
ports list --all   # include every listener
ports check 3000   # check a specific port
ports is-free 3000 # script-friendly exit code
ports wait 3000 --http 200 # wait for health
ports kill 3000    # preview and stop safely

# Build the native macOS companion:
cd macos/PortPilotMenuBar
./scripts/build-app.sh

Requires Node.js 20+ and macOS or Linux. The native companion requires macOS 13+.