Sonar
Overview
Sonar owns localhost. Every long-lived process — dev servers, APIs, databases,
workers — goes through sonar start so it is attributed to a project, a git
worktree and this agent session, its logs are captured, and it can be found and
stopped later. Backgrounding a server yourself makes it invisible and orphaned.
When to use
- A task needs a dev server, API, database, or any process that keeps running.
- A command failed with
address already in use, EADDRINUSE, or
port is already allocated.
- You need a port for a new service and do not know which are free.
- The task is finished and something you started is still listening.
Session attribution
Sonar attributes processes with SONAR_SESSION (<tool>:<id>). If the Claude
Code hooks are installed it is already set. If it is unset and
CLAUDE_SESSION_ID is available, set it once before starting anything:
export SONAR_SESSION=claude-code:$CLAUDE_SESSION_ID
The rules
- Start servers through sonar. Run dev servers, APIs and databases as
sonar start -- <command>. Sonar infers the project from the git root,
attributes the process to this session, captures logs, and makes cleanup
possible later. Never background a server with & or nohup.
- Wait before testing. After starting,
sonar wait <port> --timeout 60s
(or --http /health) before curl, tests, or browser checks. Do not sleep.
- Pick ports with sonar. For a new server,
sonar claim returns ports
reserved for this project and worktree, so parallel agents in other
worktrees do not collide. Use sonar next only for throwaway ports.
- "Address already in use" playbook.
sonar info <port> first. If it is
this session's own earlier run, sonar kill --session $SONAR_SESSION or
sonar kill <port>. If it belongs to another session, worktree, or a human,
do not kill it — claim a different port and tell the user. If it is a Docker
container, say so; sonar kill stops containers safely.
- Clean up. When the task ends,
sonar kill -g <group> for what this
session started, or sonar kill --session $SONAR_SESSION. Prefer
--dry-run when unsure.
- Look before killing.
sonar list shows groups, sessions, and who
started what. Never kill -9 a PID found by grepping lsof.
Quick reference
| Goal |
Command |
| Start a server |
sonar start -- npm run dev |
| Start it in a group |
sonar start -g web -- npm run dev |
| Wait for it |
sonar wait 3000 --timeout 60s |
| Wait for a health path |
sonar wait 3000 --http /health |
| See everything listening |
sonar list |
| Who owns a port |
sonar info 3000 |
| Reserve ports for this worktree |
sonar claim |
| One throwaway free port |
sonar next |
| Read a server's output |
sonar logs 3000 |
| Stop one port |
sonar kill 3000 |
| Stop this session's servers |
sonar kill --session $SONAR_SESSION |
| Preview a kill |
sonar kill 3000 --dry-run |
Common mistakes
npm run dev & — the process is orphaned, its logs are lost, and nothing can
clean it up. Use sonar start -- npm run dev.
sleep 5 && curl localhost:3000 — flaky. Use sonar wait 3000.
lsof -ti:3000 | xargs kill -9 — kills whatever happens to be there,
including a colleague's or another agent's server. Use sonar info 3000,
then sonar kill 3000.
- Hard-coding port 3000 in a worktree while three other agents want it. Use
sonar claim.
1---2name: sonar3description: Managing localhost ports and dev servers: starting services, freeing ports, picking free ports, cleaning up. Use whenever a task starts a server, hits 'address already in use', or needs to know what is running.4---5<!-- managed by sonar; version 1 -->67# Sonar89## Overview1011Sonar owns localhost. Every long-lived process — dev servers, APIs, databases,12workers — goes through `sonar start` so it is attributed to a project, a git13worktree and this agent session, its logs are captured, and it can be found and14stopped later. Backgrounding a server yourself makes it invisible and orphaned.1516## When to use1718- A task needs a dev server, API, database, or any process that keeps running.19- A command failed with `address already in use`, `EADDRINUSE`, or20 `port is already allocated`.21- You need a port for a new service and do not know which are free.22- The task is finished and something you started is still listening.2324## Session attribution2526Sonar attributes processes with `SONAR_SESSION` (`<tool>:<id>`). If the Claude27Code hooks are installed it is already set. If it is unset and28`CLAUDE_SESSION_ID` is available, set it once before starting anything:2930```bash31export SONAR_SESSION=claude-code:$CLAUDE_SESSION_ID32```3334## The rules35361. **Start servers through sonar.** Run dev servers, APIs and databases as37 `sonar start -- <command>`. Sonar infers the project from the git root,38 attributes the process to this session, captures logs, and makes cleanup39 possible later. Never background a server with `&` or `nohup`.402. **Wait before testing.** After starting, `sonar wait <port> --timeout 60s`41 (or `--http /health`) before curl, tests, or browser checks. Do not sleep.423. **Pick ports with sonar.** For a new server, `sonar claim` returns ports43 reserved for this project and worktree, so parallel agents in other44 worktrees do not collide. Use `sonar next` only for throwaway ports.454. **"Address already in use" playbook.** `sonar info <port>` first. If it is46 this session's own earlier run, `sonar kill --session $SONAR_SESSION` or47 `sonar kill <port>`. If it belongs to another session, worktree, or a human,48 do not kill it — claim a different port and tell the user. If it is a Docker49 container, say so; `sonar kill` stops containers safely.505. **Clean up.** When the task ends, `sonar kill -g <group>` for what this51 session started, or `sonar kill --session $SONAR_SESSION`. Prefer52 `--dry-run` when unsure.536. **Look before killing.** `sonar list` shows groups, sessions, and who54 started what. Never `kill -9` a PID found by grepping `lsof`.5556## Quick reference5758| Goal | Command |59|---|---|60| Start a server | `sonar start -- npm run dev` |61| Start it in a group | `sonar start -g web -- npm run dev` |62| Wait for it | `sonar wait 3000 --timeout 60s` |63| Wait for a health path | `sonar wait 3000 --http /health` |64| See everything listening | `sonar list` |65| Who owns a port | `sonar info 3000` |66| Reserve ports for this worktree | `sonar claim` |67| One throwaway free port | `sonar next` |68| Read a server's output | `sonar logs 3000` |69| Stop one port | `sonar kill 3000` |70| Stop this session's servers | `sonar kill --session $SONAR_SESSION` |71| Preview a kill | `sonar kill 3000 --dry-run` |7273## Common mistakes7475- `npm run dev &` — the process is orphaned, its logs are lost, and nothing can76 clean it up. Use `sonar start -- npm run dev`.77- `sleep 5 && curl localhost:3000` — flaky. Use `sonar wait 3000`.78- `lsof -ti:3000 | xargs kill -9` — kills whatever happens to be there,79 including a colleague's or another agent's server. Use `sonar info 3000`,80 then `sonar kill 3000`.81- Hard-coding port 3000 in a worktree while three other agents want it. Use82 `sonar claim`.