Port already in use? Find the dev server your agent left
On this page
  1. Why agents leave servers behind
  2. Step 1: find what holds the port
  3. Step 2: check it is yours before you stop it
  4. Step 3: stop it
  5. Stop it happening again
  6. Give each agent its own port
  7. Let Claude Code own the server
  8. Tell the agent to clean up
  9. Where Joxo fits
  10. Frequently asked questions
  11. How do I find which process is using a port on a Mac?
  12. Is it safe to kill whatever is on port 3000?
  13. Why does my dev server keep running after Claude Code exits?
  14. Try it with your team

Blog / claude code

Port already in use? Find the dev server your agent left

Coding agents start dev servers and forget them. Find what holds the port, check it is yours, stop it, and give each agent its own port.

You start your app and get EADDRINUSE: address already in use :::3000, or your agent tells you "something is already running on that port" and quietly moves to 3001. Nine times out of ten the culprit is a dev server an agent started earlier and never stopped. The fix takes three commands: find what holds the port, check it is really yours, stop it. Then give each agent its own port so it stops happening.

Why agents leave servers behind#

An agent starts npm run dev so it can check its work in a browser or with curl. Then one of these happens:

  • The session ends while the server runs. You close the terminal, the run hits its turn limit, or the agent crashes. If the server was started with nohup, & or setsid, it is no longer tied to the session and keeps running, now owned by the system (its parent process ID becomes 1).
  • A second agent starts its own copy. Two agents in two folders of the same project both reach for port 3000. The second one either fails or picks another port and tells nobody.
  • The agent moves on. It checked the page, got its answer and went to the next step, with the server still up.

Each leftover server holds a port and some memory. A week of this and you have a dozen of them.

Step 1: find what holds the port#

On macOS (and Linux, if lsof is installed):

bash
lsof -nP -iTCP:3000 -sTCP:LISTEN
COMMAND   PID    USER   FD   TYPE  DEVICE  SIZE/OFF NODE NAME
node     1633 you      16u  IPv4  0x505b…      0t0  TCP *:3000 (LISTEN)
Python  21777 you       4u  IPv6  0xf7ee…      0t0  TCP *:3000 (LISTEN)

Look closely: there can be two listeners on one port, one on IPv4 and one on IPv6. That is how a second server "starts fine" on a port that is already taken, and why your browser sometimes reaches the old one.

On Linux without lsof, ss comes with almost every distribution:

bash
ss -ltnp 'sport = :3000'
State  Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0      511                *:3000            *:*    users:(("node",pid=418,fd=18))

Step 2: check it is yours before you stop it#

Don't kill a process ID just because it holds a port you want. It might be another project's server, a database, or a teammate's agent on a shared machine. Look at the full command and how long it has been running:

bash
ps -o pid,ppid,etime,command -p 21777

The command column shows the folder or script, and etime shows how long it has been up. A ppid of 1 means its parent is gone: the session that started it ended, and nothing will ever stop it but you.

To list every leftover of one kind (here, Python's built-in web server) whose parent has gone, ask pgrep for the ones whose parent is process 1:

bash
ps -o pid,etime,command -p "$(pgrep -d, -P 1 -f http.server)"

When we ran that on a busy development Mac, it found one server that had been up for seven days.

Step 3: stop it#

Stop the one process you checked, by its ID:

bash
kill 21777

Give it a second, then run the lsof or ss line again: it should print nothing. If the process ignores kill, kill -9 21777 forces it.

Avoid the popular one-liner kill $(lsof -ti tcp:3000). When two processes share the port, it stops both, including the one you didn't mean to touch. On Linux, fuser -k 3000/tcp does the same thing with the same risk; use it only on a machine where everything on that port is yours.

Stop it happening again#

Give each agent its own port#

When several agents work on one project, each in its own git worktree, derive the port from the folder so two agents never collide and the same folder always gets the same port:

bash
PORT=$(( 3000 + $(pwd | cksum | cut -d' ' -f1) % 1000 ))
echo "$PORT"

Most Node frameworks read PORT from the environment, so PORT=$PORT npm run dev is enough. Put the line in your project's CLAUDE.md or AGENTS.md with the rule "start the dev server on this port, never on 3000", and every agent follows it. (The same file is a good place for what each worktree needs to run.)

Let Claude Code own the server#

In Claude Code, a server that the agent starts as a background task is tracked: press Ctrl+B while a command runs (twice inside tmux), or just ask Claude to run the server in the background. /tasks lists what is running, and you can stop a task from there. When Claude Code exits, it stops its background tasks, and on macOS and Linux that includes processes that detached from the task's shell.

What it can't track is a server the agent hid on purpose with nohup … & or disown. Add one more rule to CLAUDE.md: "Run dev servers as background tasks, never with nohup or &."

Tell the agent to clean up#

A last line in the same file closes the loop: "Before you finish, stop any server you started and say which port it used." That costs nothing and makes a leftover server something the agent reports instead of something you discover.

Where Joxo fits#

Leftover servers pile up fastest when several agents run at once and you can't see them all. Joxo shows every agent session on your computer in one list, with what each one is doing, so a forgotten session (and what it started) is easy to spot and stop. Setup is one line pasted into your agent. If your agents keep running into each other's files as well as ports, see stop agents editing the same files.

Frequently asked questions#

How do I find which process is using a port on a Mac?#

Run lsof -nP -iTCP:3000 -sTCP:LISTEN (with your port number). It prints the command, process ID and user of everything listening on that port, including separate IPv4 and IPv6 listeners.

Is it safe to kill whatever is on port 3000?#

Only after you check it. Run ps -o pid,ppid,etime,command -p <pid> and make sure the command is your project's server. On a shared or busy machine, another project or a database may be using the same port.

Why does my dev server keep running after Claude Code exits?#

Claude Code stops the background tasks it tracks when it exits. A server started with nohup, & or disown was detached on purpose, so nothing stops it. Ask the agent to run servers as background tasks instead.