DEV Community

Laksopan Ravindran
Laksopan Ravindran

Posted on

I Built a Cross-Platform Port Intelligence Tool to Stop Accidental Process Kills During Local Dev

Every developer has seen this at 2 AM:

Error: listen EADDRINUSE: address already in use :::5173
Enter fullscreen mode Exit fullscreen mode

The usual workflow? Open a terminal, run netstat or lsof, copy the PID, run kill -9. Simple enough — until you grab the wrong PID and accidentally terminate a critical database daemon, a Docker proxy, or a core OS service. Suddenly your machine is freezing and you're wondering what just happened.

I got tired of that workflow and built PortIntel — a cross-platform port intelligence tool with embedded offline ML, a safety override engine, and a clean visual UI. Here is a deep dive into how it works.


What is PortIntel?

PortIntel is an offline-first, cross-platform port intelligence tool and safe process termination supervisor built with Tauri v2 (Rust) and React/TypeScript.

Unlike a generic port scanner, it embeds an offline Decision Tree ML classifier directly into the Rust binary that evaluates every active socket and tells you:

  1. Importance Category — Is this port running a system-critical service, a dev workload, or something unknown/suspicious?
  2. Termination Safety — Is it safe to kill this process, or will doing so crash your system?

GitHub: https://github.com/Laksopan23/PortIntel


The Architecture

PortIntel uses a clean decoupled architecture — a React frontend talking to a Tauri/Rust backend over IPC:

┌─────────────────────────────────────┐
│     React / TypeScript UI           │
│  (Vite + Tailwind CSS)              │
└───────────────┬─────────────────────┘
                │ Tauri IPC Commands
┌───────────────▼─────────────────────┐
│         Rust Backend (Tauri v2)     │
│                                     │
│  ┌─────────────────────────────┐    │
│  │  Socket Scanner             │    │
│  │  netstat/tasklist (Windows) │    │
│  │  lsof (macOS / Linux)       │    │
│  ├─────────────────────────────┤    │
│  │  ONNX ML Classifier         │    │
│  │  (tract-onnx, fully offline)│    │
│  ├─────────────────────────────┤    │
│  │  Safety Override Engine     │    │
│  │  (hard-coded kernel guards) │    │
│  ├─────────────────────────────┤    │
│  │  HTTP Daemon (tiny_http)    │◄───┼── Browser Extension / CLI
│  │  http://127.0.0.1:12200     │    │
│  └─────────────────────────────┘    │
└─────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

The ML Classifier — 100% Offline Inference

This is the core of PortIntel. Instead of a dumb blocklist, every active socket is evaluated by a Decision Tree Classifier trained in Python (scikit-learn) and compiled directly into the Rust binary using tract-onnx.

Feature Vector

For each active socket, a 4-dimensional feature vector is constructed:

x = [
  port_number,           // e.g. 5173, 5432, 80
  is_system_user,        // 0 or 1 (root/SYSTEM)
  process_category_index,// 0–18 (mapped from process name)
  operating_system       // 0 = macOS/Linux, 1 = Windows
]
Enter fullscreen mode Exit fullscreen mode

Two Output Models

Model 1 — Importance Classification:

Label Meaning
0 — CRITICAL System-level services (RPC, spooler, resolver)
1 — DEVELOPMENT Dev servers, local DBs, Node/Vite/Django
2 — UNKNOWN Unidentified, non-standard bindings

Model 2 — Termination Safety:

Label Meaning
0 — SAFE_TO_KILL Safe to terminate to free port resources
1 — DANGEROUS_TO_KILL Termination could destabilize the system

Training the Model

The model training pipeline is straightforward:

pip install numpy scikit-learn skl2onnx
python train_model.py
Enter fullscreen mode Exit fullscreen mode

This outputs two ONNX files directly into src-tauri/assets/:

  • port_classifier_importance.onnx
  • port_classifier_safety.onnx

These get compiled directly into the Tauri binary at build time — no external files, no cloud API, no network required.


The Safety Override Engine

Even if the ML model outputs SAFE_TO_KILL, a second hard-coded safety layer kicks in. The Rust backend checks every kill request against:

  • System PIDs (typically ≤ 100) — always blocked
  • Core executablessvchost.exe, lsass.exe, wininit.exe, services.exe, smss.exe, csrss.exe, winlogon.exe, spoolsv.exe, launchd, init
  • System/root users — sockets registered under system namespaces

If any of these match, the Kill button is disabled in the UI entirely. Instead, the user sees a contextual advisory suggesting safer alternatives (gracefully stopping a service, pausing a Docker container, etc.).

This dual-layer approach — ML + hard overrides — ensures PortIntel never causes a BSOD or system freeze.


Key Features

Comprehensive Socket Scanning

Real-time detection of active TCP/UDP bindings on all platforms:

  • Windows: netstat + tasklist
  • macOS/Linux: lsof

Project-Centric Workload Grouping

Ports are automatically categorized into logical groups:

Category Examples
Web Dev Vite (:5173), Next.js (:3000), React DevServer
Databases PostgreSQL (:5432), MySQL (:3306), Redis (:6379)
Docker Container proxies, daemon sockets
System Daemons RPC, spooler, Bonjour, DNS resolver
Utilities Language servers, build tools

Offline Diagnostic Advisor Panel

Every port has a detail-rich inspector showing:

  • Socket context and process category
  • ML-based security assessment
  • OS-native command alternatives to stop the process safely

Background HTTP API Daemon

When running, PortIntel spins up a micro HTTP server at http://127.0.0.1:12200 — enabling browser extensions, CLI tools, and custom dashboards to query live port data.

Available endpoints:

# Get all active ports
GET /ports

# Analyze a specific socket
POST /analyze
{ "port": 3000, "processName": "node", "isSystem": false }

# Kill a process (subject to safety checks)
POST /kill
{ "pid": 14201 }
Enter fullscreen mode Exit fullscreen mode

Example /analyze response:

{
  "category": "Dev Server",
  "importance": "DEVELOPMENT",
  "safety": "SAFE_TO_KILL",
  "reasoning": "User development environment or application server. Safe to terminate to free up port resources."
}
Enter fullscreen mode Exit fullscreen mode

Dynamic Theme Engine

Built with a fully responsive glassmorphic UI supporting Light, Dark, and System theme switching using Tailwind CSS's selector strategy with smooth CSS transitions.


Tech Stack

Layer Technology
UI Framework React 18, TypeScript, Vite
Styling Tailwind CSS, Lucide Icons
Desktop Shell Tauri v2 (Rust)
ML Inference tract-onnx (compiled into binary)
Model Training Python 3.10+, scikit-learn, skl2onnx
HTTP Daemon tiny_http, serde_json

Getting Started

# 1. Clone the repo
git clone https://github.com/Laksopan23/PortIntel.git
cd PortIntel

# 2. Install dependencies
npm install

# 3. (Optional) Retrain the ML models
pip install numpy scikit-learn skl2onnx
python train_model.py

# 4. Run in development mode
npm run tauri dev

# 5. Build a production installer
npm run tauri build
Enter fullscreen mode Exit fullscreen mode

Prerequisites: Node.js v18+, Rust (via rustup), Python 3.10+ (only for model retraining)


What I Learned Building This

A few things that made this project genuinely interesting to build:

Embedding ML in Rust — Converting a scikit-learn model to ONNX and loading it inside a Rust binary with tract-onnx was a surprisingly smooth pipeline. The model adds zero startup latency and runs inference in microseconds.

Tauri IPC patterns — Designing a clean command interface between the React frontend and Rust backend forced me to think carefully about data contracts and error surfaces.

Cross-platform syscalls — Handling the difference between netstat/tasklist on Windows and lsof on Unix inside a single Rust codebase required careful output parsing and OS detection logic.

CSS theming without FOUC — Building a robust light/dark/system switcher in Tailwind that avoids a flash-of-unstyled-content required some careful class injection timing in the Tauri shell.


Try It Out

The project is fully open source. If you have hit the EADDRINUSE wall one too many times, give it a try:

👉 https://github.com/Laksopan23/PortIntel

If you find it useful, a ⭐ on GitHub goes a long way. And if you have ideas for improvements — cross-platform installers, a VS Code extension, better process grouping heuristics — PRs and issues are very welcome.

Drop a comment below with how you currently handle port conflicts. I am curious what workflows other developers have.





Top comments (0)