Sheet 3 of 6 · Portus · Exploded assembly
Portus
macOS menu-bar port monitor
Specification
- Role
- Fullstack Developer
- Stack
- Tauri v2, SvelteKit, Rust, TypeScript, sysinfo, bollard
- Repos
- public · v0.2 beta .dmg on GitHub
- Drawn by
- Praffi Ramadhani
- Date
- 2026-06-07
- Status
- paused
- Sheet
- 3 / 6
Overview
Portus is a native macOS menu-bar app for seeing and stopping whatever is listening on your machine. Click the menu-bar icon and a popover lists every TCP listener with its port, process name, PID, CPU, memory, and where it came from. One click kills any of them.
The product is small on purpose. It answers one recurring question without making you drop into a terminal to run lsof and kill by hand.
The problem
“Port 3000 is taken. Again. By what?”
Local development collides with itself. A dev server is already bound to a port, a container forgot to shut down, an old process is orphaned but still holding a socket. Finding the culprit means remembering the right lsof incantation, reading PID columns, and then killing the process by hand, every time.
Starting things again has the same friction. Each dev server lives in its own terminal tab, and its logs scroll away there. Portus puts both in one popover.
A1 · Part 1 of 5
the popover
Open it, read what is listening, and click to kill. The popover is SvelteKit, with a light and a dark theme in Settings.
What it shows
- Every TCP listener: port, process name, PID, CPU, memory, and an origin label (
docker,system,from IDE,from Terminal, ororphan?). - A project-first Ports list: listeners that belong to a saved project come first, and the rest fold into IDE, Terminal, and System groups.
- Deduplicated rows, so dual-stack and
SO_REUSEPORTprocesses collapse into one stable entry instead of appearing several times.
9 running
No project ports yet
- :3000 web from IDE 18420
- Cursor Helper from IDE 5 ports 23437 :57921:57922:57923:57926:57929
- :8080 api from Terminal 18704
- :5432 postgres system 612
- :3000 web from IDE ~/code/portus-web·18420·2.4%·148 MB
- Cursor Helper from IDE 5 ports /·23437·0.2%·130 MB :57921:57922:57923:57926:57929
- :8080 api from Terminal ~/code/portus-api·18704·0.8%·92 MB
- :5432 postgres system /opt/homebrew/var/postgresql@16·612·0.1%·76 MB
- portus-redis :6379 redis:7-alpine·Up 2 hours
- portus-postgres :5433 postgres:16-alpine·Up 2 hours (healthy)
- docs-preview :9000 nginx:1.27-alpine·Exited (0) 3 hours ago
A2 – A3 · Parts 2 to 3
Tauri v2 shell
Portus is a Tauri v2 app. A Rust core does the system inspection and a SvelteKit frontend renders the popover. The Rust side uses the listeners and sysinfo crates to enumerate sockets and read per-process CPU and memory.
tauri-specta generates typed bindings, so the frontend and backend share one contract instead of hand-written glue.
- A2 Tauri v2 shell tauri-specta typed bindings
- A3 the Rust core listeners · sysinfo crates
A4 – A5 · Parts 4 to 5
saved tasks
Open a folder and Portus suggests tasks from its package.json scripts and Compose services. Save the ones you use, then start and stop them from the menu bar.
Saved tasks run through a login shell inside a pseudo-terminal, each in its own process group, with the project’s environment loaded. LogPeek streams a task’s output or a Docker container’s logs, with ANSI escape codes stripped.
Docker containers are listed next to ports through the bollard crate. Docker support is read-only: containers show up with their ports and logs, but starting and stopping them is not built.
- A4 saved tasks login shell in a PTY, one process group each
- A5 Docker via bollard · read-only
Key technical decisions
-
Tauri over Electron.
It keeps the binary small and the popover native. Distribution is the trade-off. The build is ad-hoc signed but not notarized, so the first launch requires approving it in System Settings.
-
The popover paints its own background.
v0.1 drew the popover with macOS vibrancy. I removed it in v0.2. Vibrancy follows the system appearance and cannot be reliably overridden, so a light popover could not stay light on a dark-mode Mac. The popover now paints its own solid background for the theme picked in Settings.
-
Nothing is left holding a port.
Stopping a task signals its whole process group, and quitting Portus stops every task it started. Saved projects are written atomically, and a corrupt file is backed up instead of overwritten.
Current status
Paused at v0.2 beta.
v0.2 beta was released in July 2026 as an Apple Silicon .dmg on GitHub. Docker support is read-only.