Making PortPilot feel instant

Fast here means: you hit the shortcut, the list is already true, kill feels immediate, search does not hitch.

One watcher

The port table is a snapshot on a timer, not a scan on every mouse move. The UI keeps the last snapshot and paints when something actually changed.

:port-watch.ts
function startPortWatch(push: (rows: PortRow[]) => void) {
  const tick = async () => push(await window.portpilot.listPorts())
  void tick()
  const timer = setInterval(() => void tick(), 1500)
  return () => clearInterval(timer)
}

~1.5s is a default. Faster feels busy. Slower feels stale. One watcher, not a watcher per row.

Cmd + K runs Fuse over that in-memory list. No disk crawl. Clipboard keeps snippets, not whole files you copied by accident.
:os-to-table
flowchart LR
  OS[Operating system]
  Main[Main process]
  Store[Zustand store]
  UI[React table]
  OS --> Main --> Store --> UI

Secrets and first screen

Database passwords go to the OS keychain when you save them. Uncheck save and they live in RAM for the session — not in a JSON file next to package.json.

Cold start always opens Ports. Inside a module, the last sub-screen is restored, so JSON → Postgres is not a reset.

What we did not build

No account. No “sync ports to our servers.” No round trip before the list shows. The fastest request is the one you never make.

Last: how this differs from Activity Monitor plus five other apps, and how you install it.