
sonar v0.4.1
Ferramenta CLI para inspecionar e gerenciar serviços escutando em portas localhost
██████ ███ ██████ ██ ██████
██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ██
██ ██ ██ ██ ██ ██ ██ ████
██ ██ ██ ██ ██ ██ ██ ██
██████ ███ ██ ██ ██ ██ ██ ██
Saiba o que está sendo executado na sua máquina.
O Sonar mostra tudo o que está escutando em localhost e organiza em ordem: cada porta
pertence a um grupo — normalmente o repositório de onde foi iniciado — e
dentro desse grupo a um serviço nomeado. Inicie seus servidores de desenvolvimento com
sonar start e o projeto inteiro se torna uma coisa só que você pode listar como uma árvore,
aguardar, acompanhar e parar com um único comando. Contêineres Docker, projetos Compose
e processos iniciados manualmente também são detectados, sem nenhuma
configuração.
$ 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
Instalação
Homebrew (macOS / Linux)
brew install raskrebs/sonar/sonar
Homebrew 6 recusa fórmulas de taps de terceiros até que você confie no tap uma vez
(Error: Refusing to load formula raskrebs/sonar/sonar from untrusted tap):
brew trust raskrebs/sonar
Script de instalação
curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | bash
Baixa o binário mais recente para ~/.local/bin e adiciona-o ao seu PATH, se necessário. Reinicie o terminal ou execute source ~/.zshrc.
No Windows (PowerShell):
irm https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.ps1 | iex
Local de instalação personalizado:
curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | SONAR_INSTALL_DIR=/usr/local/bin bash
Instale uma versão específica:
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
Usando 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
Sessenta segundos
Descreva como o seu projeto é executado em um sonar.yaml na raiz do repositório,
em vez de um 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}
Em seguida, inicie-o:
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
O Sonar escolhe uma porta livre para cada serviço port: auto e informa a cada serviço onde os outros estão, para que um segundo worktree seja executado ao lado do primeiro sem que uma única porta entre em conflito. sonar start -d faz o mesmo em segundo plano, e sonar down o interrompe e devolve as portas. Em outro terminal:
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
Sem sonar.yaml? sonar start -- npm run dev executa um comando como um serviço nomeado, e sonar list e sonar kill funcionam em qualquer coisa que esteja escutando.
Os exemplos abaixo marcados com # check são executados contra uma build nova por
scripts/readme-check.sh em cada execução de CI.
Comandos
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
As colunas padrão são port, process, group, container, image,
containerport, url, onde process mostra o nome que você deu à porta
(sonar rename), depois o nome do serviço, depois o que foi detectado.
Colunas disponíveis: port, process, pid, type, url, group, cpu,
mem, threads, uptime, state, connections, health, latency,
container, image, containerport, compose, project, user, bind,
ip.
Aplicativos de desktop e serviços de sistema que por acaso estejam escutando — Figma, Discord,
Spotify, ControlCenter, pacotes .app do macOS, daemons em /System/Library/ — são
ocultados a menos que você passe -a.
sonar start
Inicia um projeto a partir do seu 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`
Em primeiro plano, o sonar inicia os serviços através do daemon, acompanha os seus logs com o nome do serviço à frente de cada linha, e quando prime Ctrl+C para os serviços que iniciou. Um serviço que já estava em execução é deixado em paz, e o sonar regressa por si próprio assim que todos os serviços que iniciou tiverem terminado.
Os argumentos antes de -- nomeiam um diretório ou serviços; tudo depois de -- é um
comando. Ou execute um comando como um serviço nomeado num grupo:
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
Nada precisa ser passado:
- Group —
--group, senão onamenosonar.yamlmais próximo, senão o nome do diretório raiz do git (um worktree se tornarepo@worktree), senão o nome do diretório atual. - Name —
--name, senão o serviçosonar.yamlcujocmdcorresponde, senão inferido a partir do comando (npm run dev→dev,uv run api→api,python -m uvicorn→uvicorn,./dev.sh→dev.sh). - Port —
--porté uma dica, não um vínculo: a execução aparece comostartingaté que a porta esteja realmente escutando, e o daemon a usa para corresponder o processo à porta.
O processo filho herda stdin, stdout, stderr, cwd e environment, além de
SONAR_GROUP, SONAR_NAME e SONAR_RUN_ID. Ele recebe seu próprio process group,
então sonar kill derruba toda a árvore — um dev server com seus watchers e
workers. Ctrl+C é encaminhado, e o sonar sai com o exit code do processo filho.