Skip to content

raskrebs/sonar

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

███████╗ ██████╗ ███╗   ██╗ █████╗ ██████╗
██╔════╝██╔═══██╗████╗  ██║██╔══██╗██╔══██╗
███████╗██║   ██║██╔██╗ ██║███████║██████╔╝
╚════██║██║   ██║██║╚██╗██║██╔══██║██╔══██╗
███████║╚██████╔╝██║ ╚████║██║  ██║██║  ██║
╚══════╝ ╚═════╝ ╚═╝  ╚═══╝╚═╝  ╚═╝╚═╝  ╚═╝

Know what's running on your machine.

I got tired of running lsof -iTCP -sTCP:LISTEN | grep ... every time a port was already taken, then spending another minute figuring out if it was a Docker container or some orphaned dev server from another worktree. So I built sonar.

It shows everything listening on localhost, with Docker container names, Compose projects, resource usage, and clickable URLs. You can kill processes, tail logs, shell into containers, and more — all by port number.

$ sonar list
PORT   PROCESS                      CONTAINER                    IMAGE             CPORT   URL
1780   proxy (traefik:3.0)          my-app-proxy-1               traefik:3.0       80      http://localhost:1780
3000   next-server (v16.1.6)                                                               http://localhost:3000
5432   db (postgres:17)             my-app-db-1                  postgres:17       5432    http://localhost:5432
6873   frontend (frontend:latest)   my-app-frontend-1            frontend:latest   5173    http://localhost:6873
9700   backend (backend:latest)     my-app-backend-1             backend:latest    8000    http://localhost:9700

5 ports (4 docker, 1 user)

Install

curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | bash

Downloads the latest binary to ~/.local/bin and adds it to your PATH if needed. Restart your terminal or source ~/.zshrc.

On Windows (PowerShell):

irm https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.ps1 | iex

Custom install location:

curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | SONAR_INSTALL_DIR=/usr/local/bin bash

Install a specific version:

curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | SONAR_VERSION=vX.Y.Z bash
$env:SONAR_VERSION="vX.Y.Z"; irm https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.ps1 | iex

Using Go

go install github.com/raskrebs/sonar@latest

Note: go install only installs the CLI. The menu bar tray app (sonar tray) is a native Swift binary and must be built separately — see Tray app below.

Shell completions (tab-complete port numbers):

sonar completion zsh > "${fpath[1]}/_sonar"   # zsh
sonar completion bash > /etc/bash_completion.d/sonar  # bash
sonar completion fish | source                 # fish

Usage

List ports

sonar list                     # show all ports
sonar list --stats             # include CPU, memory, state, uptime
sonar list --filter docker     # only Docker ports
sonar list --sort name         # sort by process name
sonar list --json              # JSON output
sonar list -a                  # include desktop apps
sonar list -c port,cpu,mem,uptime,state  # custom columns
sonar list --health            # run HTTP health checks
sonar list --host user@server  # scan a remote machine via SSH

By default, sonar hides desktop apps and system services that listen on TCP ports but aren't relevant to development — things like Figma, Discord, Spotify, ControlCenter, AirPlay, and other macOS .app bundles and /System/Library/ daemons. Use -a to include them.

Available columns: port, process, pid, type, url, cpu, mem, threads, uptime, state, connections, health, latency, container, image, containerport, compose, project, user, bind, ip

Inspect a port

sonar info 3000

Shows everything about a port: full command, user, bind address, CPU/memory/threads, uptime, health check result, and Docker details if applicable.

Kill processes

sonar kill 3000                            # SIGTERM
sonar kill 3000 -f                         # SIGKILL
sonar kill-all --filter docker             # stop all Docker containers
sonar kill-all --project my-app            # stop a Compose project
sonar kill-all --filter user -y            # skip confirmation

Docker containers are stopped with docker stop instead of sending signals.

View logs

sonar logs 3000

For Docker containers, runs docker logs -f. For native processes, discovers log files via lsof and tails them. Falls back to macOS log stream or Linux /proc/<pid>/fd.

Attach to a service

sonar attach 3000                          # shell into Docker container, or TCP connect
sonar attach 3000 --shell bash             # specific shell

Watch for changes

sonar watch                                # poll every 2s, show diffs
sonar watch --stats                        # live resource stats (like docker stats)
sonar watch -i 500ms                       # faster polling
sonar watch --notify                       # desktop notifications when ports go up/down
sonar watch --host user@server             # watch a remote machine

Dependency graph

sonar graph                                # show which services talk to each other
sonar graph --json                         # structured output
sonar graph --dot                          # Graphviz DOT format

Shows established connections between listening ports (e.g. your backend connecting to postgres).

Profiles

Save a set of expected ports for a project, then check if they're all up or tear them down:

sonar profile create my-app                # snapshot current ports
sonar profile list                         # list saved profiles
sonar profile show my-app                  # show profile details
sonar up my-app                            # check which expected ports are running
sonar down my-app                          # stop all ports in the profile

Wait for ports

sonar wait 5432                        # block until port is accepting connections
sonar wait 5432 3000 6379              # wait for multiple ports
sonar wait 5432 --timeout 30s         # fail after 30 seconds
sonar wait 5432 --http                # wait for HTTP 200, not just TCP open
sonar wait 5432 --http=/health        # check a specific endpoint
sonar wait 5432 -i 500ms              # custom polling interval
sonar wait 5432 -q                    # no output, just exit code (for scripts)

Useful for scripting around docker compose up -d or background services. The --http flag waits for an actual HTTP 200-399 response, not just a TCP socket, which catches services that accept connections before they're truly ready. Use --http=/health to check a specific endpoint. Exit codes: 0 (ready), 1 (timeout), 2 (interrupted).

docker compose up -d
sonar wait 5432 3000 --timeout 60s && npm run migrate && npm run test

Port mapping

sonar map 6873 3002

Proxies traffic so the service on port 6873 is also available on port 3002.

Find free ports

sonar next                                 # first next free port from 3000
sonar next 8000                            # first next free port from 8000
sonar next 3000-3100                       # first next free port in range
sonar next -n 3                            # 3 consecutive free ports
sonar next --json                          # JSON output

Other

sonar open 3000                            # open in browser
sonar tray                                 # menu bar app with live stats (macOS)
sonar --no-color                           # disable colors (also respects NO_COLOR env)

The --stats flag fetches per-process and per-container resource usage. For Docker containers, it uses the Docker Engine API for accurate per-container metrics. Without --stats, sonar returns instantly.

Tray app

The menu bar tray app (macOS only) is a native Swift binary that shows live port stats in your menu bar. If you installed sonar via the install script or a GitHub release, the tray binary (sonar-tray) is included automatically.

If you installed via go install, build it manually:

swiftc -O -o sonar-tray tray/SonarTray.swift -target arm64-apple-macos13

Then move sonar-tray somewhere on your $PATH and run:

sonar tray

Supported platforms

  • macOS (uses lsof)
  • Linux (uses ss)
  • Windows (uses netstat)

Contributors

Thanks to everyone who has contributed to sonar!