npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sriinnu/portpilot

v3.0.2

Published

Port management from your menu bar — monitor ports, discover daemons, proxy traffic, kill processes. macOS app + cross-platform CLI + rich terminal UI.

Readme

PortPilot


Why PortPilot?

Port conflicts kill developer flow. PortPilot gives you instant visibility into every listening port and every local app daemon on your machine.

Unlike basic lsof wrappers, PortPilot:

  • Classifies processes as System, App, or Developer Tool — so you see what matters
  • Detects tunnels — SSH forwards, kubectl port-forward, Cloudflare tunnels with meaningful names
  • Discovers Unix sockets — local daemons like databases, dev servers, custom services
  • Proxies traffic — native TCP proxy built on Apple's Network.framework
  • Lives in your menu bar — no Dock icon, zero distraction

Features

Menu Bar Dropdown (Liquid Display)

A glass-panel dropdown anchored to the menu bar with a unified, theme-synced design:

  • Header — PortPilot branding with refresh, settings, and more actions
  • Live stats — Active ports, Sockets, and Connections counts with pulsing status dot
  • Integrated search — Filter by port number, PID, or process name (Cmd+F hint)
  • Protocol filters — All / TCP / UDP toggle chips
  • Source filters — Local / Database / OrbStack / Tunnels
  • Top Activity — Top ports ranked by CPU + memory usage with See All toggle
  • List View — Ports grouped by connection type (Local, Database, Kubernetes, Cloudflare, SSH)
  • Tree View — Ports grouped by process name with expandable sections showing individual ports
  • Schedules — Cronjobs (user + system) with schedule, command, next-run time
  • Port rows — Port number, protocol badge, process name, PID, memory/CPU badges, hover kill/copy actions
  • More menu — Refresh, Kill All (with confirmation), Settings, Quit
  • Footer — Open PortPilot App / Tree View toggle + Sponsor link with author credit
  • No Dock icon — pure menu bar accessory app

Main Window

Open via menu bar → "Open PortPilot"

  • Port list with filter pills (TCP/UDP/Unix, Web/Database/Dev/System/Favorites)
  • CPU usage — inline CPU % badge per process, color-coded by load
  • Configuration panel — connection details, process class, PID, uptime, CPU, CWD, port mapping
  • Quick Proxy — start/stop TCP proxy for any port from the config panel
  • Port flow visualization — ASCII diagram showing traffic path
  • Logs panel — activity log with per-port filtering
  • Favorites, history, custom programs, reserved ports

Appearance & Themes

Fully customizable look and feel — Settings uses the same Liquid card design as the dropdown:

  • 6 color themes — Classic, Graphite, Sunset, Oceanic, Noir, Retro — each with a recommended font pairing
  • Theme sync — dropdown, settings panel, and main window all use the same theme-derived colors
  • Custom fonts — pick any system font for UI and monospaced text, or drop .ttf/.otf files into the Fonts/ folder
  • Font size — adjustable from 9px to 18px, applied consistently across all views
  • Settings panels — Liquid glass card design with themed sections, accent-colored icons, and sponsor link

| Theme | Character | Recommended Fonts | |-------|-----------|-------------------| | Classic | Vibrant and balanced | System Default + System Monospaced | | Graphite | Calm and professional | SF Pro + SF Mono | | Sunset | Warm and expressive | Avenir Next + Menlo | | Oceanic | Deep and focused | SF Pro Rounded + SF Mono | | Noir | Sharp and minimal | Helvetica Neue + Fira Code | | Retro | Warm and nostalgic | American Typewriter + Courier New |

Native TCP Proxy

Built on Apple's Network.framework (NWListener + NWConnection):

  • Forward traffic between any local ports
  • Bidirectional relay with byte counting
  • Start/stop from the Configuration panel
  • Active proxy indicator with "Stop All"

Process Classification

Uses proc_pidpath to resolve executable paths and classify by heuristic:

| Type | Examples | How detected | |------|----------|-------------| | System | mDNSResponder, WindowServer, launchd | /System/, /usr/libexec/, known daemons | | Developer | node, postgres, docker, nginx, redis | Homebrew paths, known dev tools | | App | Electron apps, .app bundles | /Applications/, .app/ in path | | Other | Unclassified | Fallback |

Blocklist Detection

Suspicious connections are flagged by matching against ~/.portpilot/blocklist.txt:

# ~/.portpilot/blocklist.txt — one domain, IP, or CIDR per line
upload.dev
52.45.119.88
192.168.1.0/24
2a06:98c1:310b

Supports:

  • Exact domain/IP matching
  • Domain suffix matching (.evil.com matches cdn.evil.com)
  • IPv6 prefix matching
  • CIDR ranges
  • Blocklisted connections show 🚨 in CLI, TUI, and menu bar

Terminal UI (Cross-Platform)

A full-featured terminal interface — works on macOS, Linux, and WSL. Zero dependencies.

portpilot-tui
╭─────────────────────────────────────────────────────────────────────────╮
│                        PortPilot TUI                            Linux  │
│  Ports   Sockets   Connections   Schedules                             │
│─────────────────────────────────────────────────────────────────────────│
│  PORT    PROTO  PID      CPU%     MEM     USER         COMMAND    TYPE │
│  ─────────────────────────────────────────────────────────────────────  │
│  3000    TCP    12345    0.3      45M     user         node       Web  │
│▸ 5432    TCP    789      1.2      120M    postgres     postgres   DB   │
│  8080    TCP    4567     5.1      300M    user         java       Web  │
│  6379    TCP    1122     0.1      8M      redis        redis      DB   │
│  9090    TCP    3344     0.0      15M     user         grafana    Web  │
│                                                                    ░░  │
│                                                                    ░░  │
├─────────────────────────────────────────────────────────────────────────┤
│ ↑↓/jk Navigate │ Enter Kill │ / Search │ Tab Switch │ i Info │ q Quit │
│ 5 process(es) on Linux                                                 │
╰─────────────────────────────────────────────────────────────────────────╯

Keybindings:

| Key | Action | |-----|--------| | ↑↓ / j k | Navigate | | Enter | Kill process (with confirmation) | | / | Search / clear filter | | Tab | Switch between Ports, Sockets, Connections, Schedules tabs | | i | View detailed process info + connections | | r | Refresh | | q | Quit |

Connections tab shows all established outbound connections grouped by process with blocklist 🚨 markers.

Schedules tab shows cronjobs (user + system) with next-run calculation.

Detail View — press i on any port:

╭ Process Info ──────────────────────────────────────────╮
│  Port:        5432                                     │
│  Protocol:    TCP                                      │
│  PID:         789                                      │
│  User:        postgres                                 │
│  Command:     postgres                                 │
│  CPU:         1.2%                                     │
│  Memory:      120M                                     │
│  Path:        /usr/lib/postgresql/15/bin/postgres       │
│  Work Dir:    /var/lib/postgresql/15/main               │
╰────────────────────────────────────────────────────────╯
╭ Connections (3) ───────────────────────────────────────╮
│  LOCAL ADDRESS        REMOTE ADDRESS        STATE      │
│  127.0.0.1:5432      127.0.0.1:48210       ESTABLISHED│
│  127.0.0.1:5432      127.0.0.1:48212       ESTABLISHED│
│  *:5432              *:*                    LISTEN     │
╰────────────────────────────────────────────────────────╯
 Esc Back │ x Kill │ X Force Kill │ q Quit

CLI Tool (Cross-Platform)

portpilot list                          # All listening ports (with CPU%)
portpilot list --start 3000 --end 9999  # Port range
portpilot list --proto tcp --json       # JSON output (includes cpuUsage)
portpilot kill 5173 --force             # Kill by port
portpilot kill :8080                    # Colon prefix syntax
portpilot pid 8080                      # Get PID for port
portpilot pids 3000 3001 3002           # Multiple PIDs
portpilot connections                   # All established connections (grouped by process)
portpilot connections --suspect         # Only processes with >50 connections
portpilot connections --kill 12345      # Kill process by PID
portpilot connections --json            # JSON output
portpilot schedules                     # User + system cronjobs
portpilot schedules --json              # JSON output
portpilot interactive                   # TUI mode
portpilot proxy --port 1080 --host user@server  # SOCKS proxy

CLI table output includes CPU%, memory, and project/source info:

PORT     PROTO  PID      CPU%     MEM      USER         COMMAND            PATH/PROJECT
3000     TCP    21082    0.0      45M      user         node               wooosh/client
5432     TCP    63341    9.4      120M     user         postgres           postgresql/15/main
8080     TCP    4567     5.1      300M     user         java               my-api/server

Connections output with blocklist detection:

REMOTE              PROCESS      PID     USER     STATE         COUNT
52.45.119.88:443    node         12345   user     ESTABLISHED   1847   🚨
54.210.12.45:443    chrome       999     user     ESTABLISHED   23
...

Schedules output:

SCHEDULE          NEXT RUN        USER     COMMAND                        SOURCE
@hourly          04-03 14:00     user     /usr/bin/some-script.sh       user
*/5 * * * *      04-03 13:35     root     /usr/bin/monitoring.sh        /etc/cron.d/sys

Installation

Download from GitHub Releases

For end users, the easiest path is the Releases page:

  • Download PortPilot-macOS-app.zip
  • Unzip it
  • Move PortPilot.app to /Applications

The release currently attaches:

  • PortPilot-macOS-app.zip
  • portpilot-macos-cli
  • SHA256SUMS.txt

macOS (App + CLI + TUI)

git clone https://github.com/sriinnu/portpilot.git
cd portpilot
npm run release

This builds everything and installs:

  • PortPilot.app/Applications/ (menu bar app)
  • portpilot CLI → /usr/local/bin/
  • portpilot-tui/usr/local/bin/ (terminal UI)
portpilot list              # CLI: list all listening ports
portpilot-tui               # TUI: full interactive terminal UI

Linux / WSL

1. Install Swift (if not already installed):

curl -L https://swiftlang.github.io/swiftly/swiftly-install.sh | bash
source ~/.profile  # or restart your shell
swiftly install latest
swift --version    # verify: should show Swift 6.x

See the official Swiftly Getting Started guide for details.

2. Build & install:

git clone https://github.com/sriinnu/portpilot.git
cd portpilot
npm run setup:linux   # builds CLI + TUI and installs to /usr/local/bin

Or step by step:

npm run build:all:linux
sudo cp .build/release/portpilot /usr/local/bin/
sudo cp .build/release/portpilot-tui /usr/local/bin/

3. Use it:

portpilot list              # all listening ports with project paths
portpilot tui               # launch rich terminal UI
portpilot-tui               # direct launch
portpilot kill 8080         # kill by port

Windows

Requires Swift for Windows:

git clone https://github.com/sriinnu/portpilot.git
cd portpilot
swift build -c release --product portpilot
copy .build\release\portpilot.exe "C:\Program Files\PortPilot\"

Uses netstat + tasklist automatically:

portpilot list              # all listening ports
portpilot kill 5000 --force # force kill
portpilot list --json       # pipe to tools

Note: The TUI (portpilot-tui) requires a POSIX terminal and works on macOS, Linux, and WSL. On Windows, use WSL or the CLI directly.

No config, no setup, no runtime dependencies. Platform detection is automatic — same interface everywhere.

npm scripts

# macOS
npm run build            # Build macOS app (xcodebuild)
npm run release          # Build all + install app/CLI/TUI

# Linux / WSL
npm run setup:linux      # One-command: build + install CLI + TUI
npm run build:all:linux  # Build CLI + TUI only

# Common
npm run build:cli        # Build CLI
npm run build:tui        # Build TUI
npm run install:cli      # Install CLI to /usr/local/bin
npm run install:tui      # Install TUI to /usr/local/bin
npm run uninstall        # Remove everything
npm run clean            # Remove build artifacts

Platform Support

| Platform | GUI App | TUI | CLI | Port Discovery | Install | |----------|---------|-----|-----|---------------|---------| | macOS 13+ | Menu bar + window | portpilot-tui | portpilot | lsof + proc_pidpath | npm run release | | Linux | - | portpilot-tui | portpilot | ss | npm run build:all:linux | | WSL | - | portpilot-tui | portpilot | ss | npm run build:all:linux | | Windows | - | via WSL | portpilot | netstat + tasklist | swift build -c release |

Keyboard Shortcuts

| Shortcut | Action | |----------|--------| | Cmd+R | Refresh ports | | Cmd+F | Search | | Cmd+, | Settings |

Architecture

Sources/
├── PortPilot/                  # macOS menu bar app (SwiftUI + AppKit)
│   ├── PortPilotApp.swift            # Pure AppKit entry (no Dock icon)
│   ├── ContentView.swift             # Main window layout
│   ├── PortViewModel.swift           # State, filtering, tunnel detection
│   ├── MenuBarController.swift       # Status item + panel management
│   ├── MenuBarDropdownView.swift     # Liquid display dropdown (Top Activity, List/Tree View, Schedules)
│   ├── MenuBarPanel.swift            # Floating NSPanel
│   ├── PortListPanel.swift           # Port list with classification badges
│   ├── ConfigurationPanel.swift      # Config + proxy controls
│   ├── MainWindowToolbar.swift       # Toolbar with filter pills
│   ├── LogsPanel.swift               # Activity logs
│   ├── Theme.swift                   # 6 color themes + Liquid display tokens
│   ├── FontManager.swift             # Custom font loading
│   ├── SettingsView.swift            # Liquid card settings (appearance, fonts, themes)
│   └── AppSettings.swift             # UserDefaults + font/theme settings
├── TerminalTUI/                # Reusable TUI engine (zero dependencies)
│   ├── Terminal.swift                # Raw mode, terminal size, cursor, alt screen
│   ├── ANSI.swift                    # Escape codes — 16/256/TrueColor, styles
│   ├── KeyEvent.swift                # Key reading — arrows, ctrl, UTF-8, escape seqs
│   ├── Screen.swift                  # Double-buffered diff renderer
│   ├── Widget.swift                  # Widget protocol + geometry types
│   ├── Box.swift                     # Bordered container (4 border styles)
│   ├── Table.swift                   # Scrollable table with columns + selection
│   ├── StatusBar.swift               # Bottom bar with keybinding hints
│   └── App.swift                     # TUIApp event loop + screen stack
├── PortPilotTUI/               # Terminal UI app (macOS + Linux + WSL)
│   ├── main.swift                    # Entry point
│   ├── PortListScreen.swift          # Port/Socket/Connection/Schedule tables, search, kill
│   ├── PortDetailScreen.swift        # Process info + connections
│   ├── ConnectionDetailScreen.swift  # Connection remote details, kill option
│   └── CronjobDetailScreen.swift    # Cronjob schedule info, next run
├── PortManagerLib/             # Shared library (all platforms)
│   ├── PortManager.swift             # Port + socket + connection + cronjob discovery
│   ├── ProcessClassifier.swift       # proc_pidpath classification
│   ├── TCPProxyManager.swift         # Network.framework TCP proxy
│   ├── PortWatcher.swift             # Port monitoring
│   ├── FavoritesManager.swift        # Favorites
│   └── HistoryManager.swift          # Kill history (thread-safe)
├── PortKillerCLI/              # CLI tool
│   ├── CLI.swift                     # Argument parsing
│   └── InteractiveMode.swift         # Basic interactive mode
└── Fonts/                      # Drop .ttf/.otf here for custom fonts

Tech Stack

  • Swift 5.9 + SwiftUI — native macOS UI
  • AppKit — menu bar, NSWindow management
  • TerminalTUI — custom zero-dependency TUI engine (ANSI rendering, key handling, widget system)
  • Network.framework — TCP proxy (NWListener + NWConnection)
  • CoreText — runtime font registration from custom font files
  • proc_pidpath — process classification via executable path (with bounds-checked buffer)
  • Thread safety — NSLock on shared caches; process execution with 10s timeout

Using TerminalTUI in Your Own Project

TerminalTUI is a standalone, zero-dependency Swift library. Add it to your Package.swift:

dependencies: [
    .package(url: "https://github.com/sriinnu/portpilot.git", from: "3.0.0"),
],
targets: [
    .executableTarget(
        name: "MyApp",
        dependencies: [.product(name: "TerminalTUI", package: "portpilot")]
    ),
]
import TerminalTUI

struct MyScreen: TUIScreen {
    mutating func render(into screen: inout Screen) {
        screen.put(row: 0, col: 0, text: "Hello, TUI!", style: ANSI.bold + ANSI.fg(.cyan))
    }
    mutating func handleKey(_ key: KeyEvent) -> ScreenAction {
        key == .char("q") ? .quit : .continue
    }
}

let app = TUIApp(screen: MyScreen())
app.run()

License

MIT — see LICENSE for details.