Skip to content

VS Code extension

The portcheck extension shows what's using your ports and frees them safely, without leaving the editor. It works in VS Code and in editors that use Open VSX (VSCodium, Cursor, Windsurf).

npm run dev fails with EADDRINUSE; the extension names the process holding port 3000, stops it and re-runs the command

Install

In VS Code, open Extensions and search portcheck, or install Portcheck - Port in Use Fixer from the VS Code Marketplace. In VSCodium, Cursor and Windsurf, it's on Open VSX. portcheck is built in.

Every portcheck release has a portcheck-vscode-<version>.vsix with portcheck built in for macOS, Linux and Windows (x64 and arm64); the extension uses the right one for the machine it runs on, including remote machines, WSL and containers. Download it and install it:

code --install-extension portcheck-vscode-0.5.0.vsix

or use Extensions → … → Install from VSIX….

The extension needs VS Code 1.98 or later. The .vsix has build provenance: gh attestation verify <file> --repo roystondwork-dev/portcheck.

"Port in use" errors: one-click fixes

When a command in the integrated terminal fails because its port is taken, the extension tells you who holds it and offers to fix it:

$ python3 -m http.server 3000
OSError: [Errno 48] Address already in use

 ⚠ Port 3000 is already in use by Python (pid 41852).                    [Fix…]

  Port 3000 is in use: what should portcheck do?
  ↻ Stop Python (pid 41852) and re-run     python3 -m http.server 3000
  ■ Stop Python (pid 41852)                started by zsh (41848) ← Code (28865)
  → Re-run on free port 3001               python3 -m http.server 3001
  ⧉ Copy free port 3001
  ⓘ Show details
  • Stop … and re-run stops the holder (portcheck's safety guards apply) and runs your command again in the same terminal.
  • Re-run on free port runs your command on the next free port. The port is replaced where the command names it (--port 3000, :3000, runserver 8000), otherwise the tool's port flag is added (vite --port 3001, rails server -p 3001), otherwise PORT=3001 is set, which most Node frameworks read. The command is shown before you choose it.
  • For a port held by a container or WSL distro, the fix is the right docker stop / wsl command, and for a hidden owner the elevated portcheck kill; neither stops a proxy.

The error itself is also a link (Ctrl/Cmd+click) that opens the same menu, and portcheck: Fix a Busy Port… opens it for any port.

The extension recognises the messages of Node.js (EADDRINUSE), Vite, Next.js, Create React App, Angular, Bun, Deno, Go, Rust, Python (uvicorn, Flask, Django, http.server), Ruby (Puma, WEBrick), Spring Boot, .NET, PHP, nginx, Redis, PostgreSQL and Docker. When a message doesn't name the port (Python's [Errno 48] Address already in use, Django's That port is already in use), the port comes from the command (runserver 8000) or the tool's default (Django 8000). If yours isn't recognised, please open an issue with the line.

Shell integration

Noticing errors as they're printed, and re-running commands, use VS Code's shell integration, which is on by default for bash, zsh, fish and PowerShell. Without it, errors are still links, and fixes that re-run a command are not offered. The extension needs VS Code 1.98 or later.

Project ports (.portcheck.yaml)

If the workspace has a .portcheck.yaml, the extension runs portcheck doctor on it and keeps it up to date as you edit the file:

  • The status bar shows ✓ ports, or ⚠ 1/4 ports when a check fails; hover for every check, click to fix one (stop what holds a port the project needs).
  • Problems shows each failed check on its entry in the file, and mistakes in the file (an unknown key, a bad port) on their line.
  • In Listening ports, the project's ports come first, with a star and their name.
  • With the YAML extension installed, the file gets completion and validation from the JSON Schema, bundled with the extension.

Listening ports view

The portcheck icon in the activity bar opens Listening ports: one row per listening port and owner.

Row Meaning
:3000 node (process icon) a process you can stop
:8080 docker:web (package icon) a port published by a Docker/Podman container, or forwarded from a WSL distro (wsl:Ubuntu/node)
:22 (owner hidden) (lock icon) the owner belongs to another user and is hidden without elevated privileges
:3000 node (star), web · tcp · … a port your project's .portcheck.yaml names

UDP ports are hidden by default, since most are system services (mDNS, AirDrop); the filter button in the view's title bar shows them.

Hover a row for details: the process, who started it (npm (4200) ← zsh (900)), the command line, the user, and for containers the image and the command that stops it.

The view refreshes every 5 seconds while it's visible (setting portcheck.refreshInterval; 0 refreshes only on demand) and has a refresh button.

Stopping a process

Use the stop button on a row, or portcheck: Stop What's Using a Port… from the command palette.

  • For a process, you're asked first, and the dialog shows who started it. Stop asks it to exit and forces it only if needed; Force Kill skips the graceful step. portcheck's safety guards apply: it refuses system processes and never stops VS Code itself.
  • For a container or WSL port, the extension never stops the proxy, because that would affect every container or the whole distro. It shows the right command (docker stop web, wsl -d Ubuntu --exec kill 1234) and can run it in a terminal or copy it.
  • For a hidden owner, it offers the elevated command (sudo portcheck kill 22) to run in a terminal.

Commands

Command What it does
portcheck: Check a Port… whether a port is free, and who holds it if not (with a Stop It action)
portcheck: Find a Free Port… the first free port in a range (default 3000-9999); Copy or Insert it at the cursor
portcheck: Stop What's Using a Port… as above, by port number
portcheck: Fix a Busy Port… the fix menu above, for any port
portcheck: Check Project Ports (.portcheck.yaml) re-runs doctor and offers fixes (also the status bar item)
portcheck: Show/Hide UDP Ports toggles portcheck.showUdp
portcheck: Refresh reloads the view
portcheck: Show Log the extension's log, useful when reporting issues

Remote development

The extension runs where your code runs. In Remote-SSH, WSL and Dev Containers it lists and stops ports on the remote machine, distro or container, not on your laptop.

Settings

Setting Default Meaning
portcheck.path (empty) path to the portcheck binary; empty uses the bundled one, then portcheck on your PATH
portcheck.refreshInterval 5 seconds between refreshes while the view is visible; 0 = manual
portcheck.showUdp false show UDP ports in the view
portcheck.terminal.notify true notify when a terminal command fails because its port is in use (errors are links either way)

How it works

The extension is a thin client: every action runs the portcheck CLI with --json (versioned schema) and shows the result. Process attribution, containers, WSL and the safety guards all come from the same code as the CLI. See ADR-0004.

Building from source

Requires Go 1.26+ and Node.js 22+.

git clone https://github.com/roystondwork-dev/portcheck.git && cd portcheck
make build                         # builds bin/portcheck
cd extensions/vscode
npm ci
npx vsce package --no-dependencies # creates portcheck-<version>.vsix
code --install-extension portcheck-*.vsix

Then set portcheck.path to the absolute path of bin/portcheck (or put it on your PATH).