Torna agli aggiornamenti
New releaseSep 4, 2026

sonar v0.4.1

Strumento CLI per ispezionare e gestire i servizi in ascolto sulle porte di localhost

Condividi
██████    ███    ██████    ██    ██████
██           ██      ██  ██  ██      ██
██      ██   ██  ██  ██  ██  ██      ██
  ██  ██   ██  ██  ██  ██  ██  ████
    ██  ██       ██  ██  ██  ██  ██  ██
██████    ███    ██  ██  ██  ██  ██  ██

Know what's running on your machine.

Sonar mostra tutto ciò che è in ascolto su localhost e lo mette in ordine: ogni porta appartiene a un gruppo — normalmente il repository da cui è stato avviato — e all'interno di quel gruppo a un servizio con nome. Avvia i tuoi server di sviluppo con sonar start e l'intero progetto diventa un'unica cosa che puoi elencare come un albero, attendere, seguire e fermare con un singolo comando. Anche i container Docker, i progetti Compose e i processi avviati manualmente vengono rilevati, senza alcuna configurazione.

$ sonar list --tree
my-app  (3 ports, running)                        ~/code/my-app
├─ 5432  db          postgres:17                  http://localhost:5432
├─ 5173  frontend    vite (v5.4)                  http://localhost:5173
└─ 8000  api         uvicorn app:app              http://localhost:8000
ungrouped (1 port)
└─ 3000  next-server (v16.1.6)                    http://localhost:3000

Installazione

Homebrew (macOS / Linux)

brew install raskrebs/sonar/sonar

Homebrew 6 rifiuta le formule provenienti da tap di terze parti finché non ti fidi del tap una volta (Error: Refusing to load formula raskrebs/sonar/sonar from untrusted tap):

brew trust raskrebs/sonar

Script di installazione

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

Scarica l'ultimo binario in ~/.local/bin e lo aggiunge al tuo PATH se necessario. Riavvia il terminale o esegui source ~/.zshrc.

Su Windows (PowerShell):

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

Percorso di installazione personalizzato:

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

Installa una versione specifica:

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

Utilizzo di Go

go install github.com/raskrebs/sonar@latest

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

Sessanta secondi

Descrivi come viene eseguito il tuo progetto in un sonar.yaml nella radice del repository, al posto di un dev.sh:

name: my-app
services:
  - name: db
    cmd: docker compose up db
    port: 5432
  - name: api
    cmd: uv run uvicorn app:app --port ${port}
    port: auto
    depends_on: [db]
  - name: frontend
    cmd: npm run dev -- --port ${port} --strictPort
    port: auto
    depends_on: [api]
    env:
      VITE_API_URL: ${api.url}

Poi avvialo:

sonar start
  ✓ db        http://localhost:5432   pid 41022  ~/.config/sonar/logs/my-app/db.log
  ✓ api       http://localhost:21408  pid 41040  ~/.config/sonar/logs/my-app/api.log
  ✓ frontend  http://localhost:21409  pid 41077  ~/.config/sonar/logs/my-app/frontend.log

3 started
following the logs; Ctrl+C stops the 3 services started here
api      | INFO:     Uvicorn running on http://127.0.0.1:21408
frontend | VITE v5.4  ready in 312 ms

Sonar sceglie una porta libera per ogni servizio port: auto e comunica a ciascun servizio dove si trovano gli altri, così un secondo worktree viene eseguito accanto al primo senza che una singola porta entri in conflitto. sonar start -d fa lo stesso in background, e sonar down lo arresta e restituisce le porte. In un altro terminale:

sonar list --tree
my-app  (3 ports, running)                        ~/code/my-app
├─ 5432   db          postgres:17                 http://localhost:5432
├─ 21408  api         uvicorn app:app             http://localhost:21408
└─ 21409  frontend    vite (v5.4)                 http://localhost:21409

Nessun sonar.yaml? sonar start -- npm run dev esegue un singolo comando come servizio con nome, e sonar list e sonar kill funzionano su qualsiasi cosa sia in ascolto.

Gli esempi seguenti contrassegnati con # check vengono eseguiti su una build appena creata da scripts/readme-check.sh a ogni esecuzione della CI.

Comandi

sonar list

sonar list
sonar list --tree
sonar list --group my-app
sonar list --json
# check
sonar list --stats             # CPU, memory, threads, uptime, state
sonar list --health            # HTTP health checks
sonar list --filter docker     # only Docker ports
sonar list --sort name         # port | pid | name | type
sonar list -a                  # include desktop apps
sonar list -c port,process,group,cpu,mem
sonar list --host user@server  # scan a remote machine over SSH

Le colonne predefinite sono port, process, group, container, image, containerport, url, dove process mostra il nome che hai assegnato alla porta (sonar rename), poi il nome del servizio, poi ciò che è stato rilevato.

Colonne disponibili: port, process, pid, type, url, group, cpu, mem, threads, uptime, state, connections, health, latency, container, image, containerport, compose, project, user, bind, ip.

Le app desktop e i servizi di sistema che si trovano in ascolto — Figma, Discord, Spotify, ControlCenter, bundle .app di macOS, daemon in /System/Library/ — sono nascosti a meno che tu non passi -a.

sonar start

Avvia un progetto dal suo sonar.yaml:

sonar start                    # every service in the nearest sonar.yaml
sonar start api frontend       # only these (they still wait for their dependencies)
sonar start ../other-project   # the sonar.yaml in or above another directory
sonar start -d                 # in the background, like `sonar up`

In primo piano, sonar avvia i servizi tramite il daemon, segue i loro log con il nome del servizio davanti a ogni riga, e quando premi Ctrl+C ferma i servizi che ha avviato. Un servizio già in esecuzione viene lasciato in pace, e sonar ritorna da solo una volta che ogni servizio che ha avviato è terminato.

Gli argomenti prima di -- indicano una directory o dei servizi; tutto ciò che segue -- è un comando. Oppure esegui un comando come servizio con nome in un gruppo:

sonar start -- npm run dev
sonar start --group my-app --name frontend -- npm run dev
sonar start --port 5173 -- npm run dev        # expected port, before it binds
sonar start --detach --name api -- uv run uvicorn app:app
sonar start --list

Non deve essere passato nulla:

  • Group — --group, altrimenti il name nel sonar.yaml più vicino, altrimenti il nome della directory della radice git (un worktree diventa repo@worktree), altrimenti il nome della directory corrente.
  • Name — --name, altrimenti il servizio sonar.yaml il cui cmd corrisponde, altrimenti inferito dal comando (npm run dev → dev, uv run api → api, python -m uvicorn → uvicorn, ./dev.sh → dev.sh).
  • Port — --port è un suggerimento, non un binding: l'esecuzione appare come starting finché la porta non è effettivamente in ascolto, e il daemon la usa per associare il processo alla porta.

Il processo figlio eredita stdin, stdout, stderr, cwd e l'ambiente, più SONAR_GROUP, SONAR_NAME e SONAR_RUN_ID. Ottiene il proprio process group, così sonar kill abbatte l'intero albero — un dev server con i suoi watcher e worker. Ctrl+C viene inoltrato, e sonar esce con il codice di uscita del figlio.

Categorie