---
title: Why I built PortPilot
description: Developers already run lsof, copy PIDs, and juggle clipboard and local DBs every day. PortPilot sits in the tray and puts that loop in one place.
date: 2026-08-19
slug: why-i-built-portpilot
topic: Desktop
series: PortPilot
seriesOrder: 1
featured: true
tags:
  - portpilot
  - electron
  - dx
---

You start a frontend. Then an API. Then yesterday’s debugger is still on `:9229`. “Port already in use.” Terminal. `lsof`. A PID. The wrong `kill`. Again.

That is not a rare bug. It is the **daily cycle**: ports, a JSON blob, a local database. Every developer already has a tool for each piece. I built PortPilot because I was tired of opening four of them before the stack was even running.

## What it replaces

`lsof -i :3000` works. So does Activity Monitor. You still do it after lunch, and again when two Vite servers collide. You copy a PID and hope it is the right process. CPU meters do not say “this is the dashboard repo.”

PortPilot is the tray utility for that loop:

- Live ports, with the project folder on the row
- Kill, restart, or open localhost from the row — no PID paste
- Clipboard, JSON, JS Playground, Time Bench, and local DBs in the same window
- `Cmd + Option + P` from anywhere, so it feels like part of the OS

<Note>
`lsof` is not hard. It is slow in the human sense: find the port, read the PID, kill it, do it again tomorrow. PortPilot is meant to live on the machine — always there, one hotkey away — and cover the daily kit in one window. You should not need a terminal to babysit localhost.
</Note>

It stays in the menu bar. No login. No cloud. The data is already on the laptop.

## Three rooms, one desk

The afternoon is rarely “only ports.” You kill a process, copy an error, check local Postgres. PortPilot is three rooms, not three apps:

<ArchitectureDiagram
  label="One app, three rooms"
  nodes={[
    { id: 'ports', title: 'Ports', subtitle: 'Listeners, kill, jump', icon: 'terminal' },
    { id: 'text', title: 'Text & Data', subtitle: 'Clipboard, JSON, JS Playground', icon: 'schema' },
    { id: 'db', title: 'Database', subtitle: 'Local DBs, optional SSH', icon: 'cloud' },
  ]}
/>

`Cmd + 1 / 2 / 3` switch rooms. Cold start always opens **Ports**. Each room remembers the last screen you used.

<SignalPath
  caption="Same loop. One window."
  steps={[
    { label: 'Run', hint: 'Vite + API' },
    { label: 'Map', hint: 'Port, folder, PID' },
    { label: 'Act', hint: 'Kill, restart, open' },
    { label: 'Paste', hint: 'JSON, JS, Time Bench' },
  ]}
/>

It is not a DBA studio and not a cloud IDE. It is the all-in-one I leave running.

Next: the actual features, and a playground you can drive — kill a port, open Text & Data, inspect a connection.
