localhost:

Kill leftover dev servers

Find and stop dev servers left running by a closed terminal, Claude Code or Cursor: list every listening port, kill the whole process tree, and keep it clean.

List everything listening on a TCP port, then stop what shouldn’t be there. On macOS and Linux:

lsof -nP -iTCP -sTCP:LISTEN               # every listener, with its PID
ps -o pid,ppid,pgid,command -p <PID>      # what it is, and its process group
kill -- -<PGID>                           # stop the whole group, not just one process

On Linux, ss -ltnp lists the listeners too. On Windows:

netstat -ano | findstr LISTENING
tasklist /FI "PID eq <PID>"
taskkill /PID <PID> /T /F                 :: /T takes its child processes with it

Why do dev servers keep running after I close the terminal?

Closing a terminal tab hangs up its shell, and the shell passes that on to the jobs it started. Some don’t get the message, or ignore it:

  • Background jobs: anything started with &, nohup or disown, or by a tool that detaches on purpose.
  • Children of the process you stopped. npm run dev starts node, which may start a compiler or a worker. Stop only npm, especially with kill -9, and the children carry on, adopted by the system.
  • Coding agents. Claude Code, Cursor and other agents run commands in their own shells. A dev server never exits, so an agent runs it in the background, and it stays there after the chat unless the agent stops it.

The symptoms are the same each time: a port that is already in use, a laptop fan that won’t settle, or an old version of your app answering in the browser.

How do I find every leftover dev server?

Look for listeners, not process names: a dev server that matters holds a port. lsof -nP -iTCP -sTCP:LISTEN on macOS, ss -ltnp on Linux and netstat -ano | findstr LISTENING on Windows list them all, with PIDs. To see which project one belongs to, check its working directory: lsof -a -d cwd -p <PID> on macOS, ls -l /proc/<PID>/cwd on Linux.

Matching by name (pkill -f vite, taskkill /IM node.exe /F) is quick, but it also stops the editor extension, language server or other project that happens to run the same program.

How do I kill the whole process tree?

On macOS and Linux, a command started from a shell usually gets its own process group, and kill -- -<PGID> signals every process in it. ps -o pgid= -p <PID> prints the group. Send SIGTERM first; wait a few seconds; only then SIGKILL (kill -9 -- -<PGID>).

On Windows, taskkill /PID <PID> /T stops the process and everything it started. Add /F to force it.

How does localhost stop dev servers for good?

localhost runs each of your Services from one window, so the server you want is never in a tab you forgot.

  • Stop ends the whole tree. localhost sends SIGINT (Ctrl-C) to the Service’s process group, SIGTERM after 5 seconds and SIGKILL after 3 more. On Windows it sends Ctrl-Break, then ends the Job Object that holds every process the Service started. The Service shows Stopping until the last one has ended, and the log says when it had to force it.
  • The Ports view finds the rest. Ports (⌘0, or Ctrl+0) lists every listener and whose it is: one of your Services, a process running inside one of your Projects’ folders, or nothing localhost knows. A dev server you started in a terminal shows under its Project, by its working directory. Select it and press ⌘. (Ctrl+.) to stop it; localhost asks first for anything it didn’t start, and won’t stop itself, system services or Docker’s backend.
  • Nothing outlives localhost unseen. Closing the window keeps your Services running, shown in the menu bar or tray. Quitting asks first, then stops all of them. If localhost ever crashes, the next launch finds what was left running and asks whether to stop it.
  • Agents clean up too. Services a coding agent starts through localhost mcp stop when the agent disconnects, unless the app is open, where you see them.

More on states and stopping: Services and states.

FAQ

How do I kill every Node.js process?

pkill node on macOS and Linux, taskkill /IM node.exe /F on Windows. It stops every Node.js process, including your editor’s tools and other projects, so stopping by port or PID is safer.

What is the difference between SIGTERM and SIGKILL?

SIGTERM asks a process to exit and lets it clean up; SIGKILL ends it at once and can’t be caught. Send SIGTERM first. localhost sends SIGINT, then SIGTERM after 5 seconds, then SIGKILL after 3 more.

Does localhost stop processes it didn’t start?

Only when you ask, from the Ports view, and it asks first. It never takes them over as Services, and won’t stop itself, launchd jobs, Windows services or Docker’s backend.

What happens to my dev servers if localhost crashes?

localhost records each running Service on disk. At the next launch it lists the ones still running and offers to stop them (the default) or leave them. They are never taken back as Running.

Edit this page on GitHub

Install localhost for macOS

Two quick steps, usually under a minute.

  1. Drag it to Applications

    Open localhost-0.3.0.dmg and drag localhost to Applications.

    Download localhost-0.3.0.dmg

    Or install it with Homebrew, which also puts the localhost command in your terminal:

    brew install --cask marcellosso/tap/localhost

    Or download it from Terminal, which macOS doesn’t block, so you can skip step 2:

    curl -fLO https://github.com/marcellosso/localhost/releases/download/v0.3.0/localhost-0.3.0.dmg && open localhost-0.3.0.dmg
  2. Open it the first time

    localhost isn’t notarized by Apple yet, so macOS blocks the first launch once:

    1. Click Done in the warning.
    2. Open System Settings › Privacy & Security and scroll to Security.
    3. Click Open Anyway, and confirm with your password or Touch ID.

    Or run this in Terminal, then open localhost:

    xattr -dr com.apple.quarantine /Applications/localhost.app

macOS 15 or later · Apple silicon or Intel

  1. Run the installer

    Open localhost_0.3.0_x64-setup.exe. It installs for your user only, no administrator rights needed.

    Download localhost_0.3.0_x64-setup.exe
  2. Get past SmartScreen

    The installer isn’t signed by a known publisher yet, so Windows says “Windows protected your PC”:

    1. Click More info.
    2. Check that the file is localhost_0.3.0_x64-setup.exe.
    3. Click Run anyway.

Windows 10 or 11 · x64 · WSL 2 for Projects in WSL

  1. Download your package

  2. Install it

    From the folder you downloaded it to:

    sudo apt install ./localhost-app_0.3.0_amd64.deb
    sudo dnf install ./localhost-app-0.3.0-1.x86_64.rpm
    chmod +x localhost-app_0.3.0_amd64.AppImage && ./localhost-app_0.3.0_amd64.AppImage

    Secrets need a Secret Service (GNOME Keyring, KWallet). On stock GNOME the tray icon needs the AppIndicator extension.

x86_64 · Ubuntu 22.04+ · Debian 12+ · Fedora

On another system?Install guide →