0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「ポート3000が空かない」を二度と言わないためにVSCode拡張を作った

0
Last updated at Posted at 2026-02-21

「ポート3000が空かない」を二度と言わないためにVSCode拡張を作った

スクリーンショット 2026-02-21 11.23.41.png

きっかけ

開発中、npm run dev しようとしたら「port 3000 is already in use」。

ターミナルで lsof -i :3000 して、PID調べて、kill -9 して……。これ、週に何回やってるんだろう。Windowsだと netstat -ano | findstr :3000 からの taskkill /F /PID xxxx で、もっとだるい。

別にコマンド打てばいいんだけど、毎回覚えてないし、毎回ググるのがしんどい。

「VSCodeから全部できたらよくない?」と思って作った。

作ったもの

Port Manager — VSCode拡張機能。

やれることはシンプルで、

  • 使用中のポート一覧をサイドバーに表示
  • ポート番号やプロセス名で検索
  • ワンクリックでプロセスKILL(確認ダイアログあり)
  • 複数選択して一括KILL
  • 指定範囲の空きポート確認

Mac、Windows、Linux全部動く。依存パッケージなし。

サイドバーの様子

左のアクティビティバーにアイコンが追加されて、開くとこんな感じ。

スクリーンショット 2026-02-21 11.28.19.png

VSCodeのテーマに自動で合わせてくれるので、ダーク・ライトどっちでも違和感ない。

コマンドパレットからも使える

Cmd+Shift+P(WindowsならCtrl+Shift+P)で3つのコマンドが出る。

コマンド 何ができる
Port Manager: Show Listening Ports QuickPickで一覧 → 選んでKILL
Port Manager: Check Port Availability 番号入れるだけで空き判定
Port Manager: Kill Port カンマ区切りで複数KILLもOK

サイドバー開くまでもないときはこっちが速い。3000 って打つだけで「使ってるのはnodeだよ、殺す?」って聞いてくれる。

中身の話

OS判定でコマンドを分岐

ポートの取得方法がOSごとに全然違うので、os.platform() で分岐してる。

const PLATFORM = os.platform();

function getListeningPorts() {
  if (PLATFORM === "darwin" || PLATFORM === "linux") return getPortsUnix();
  if (PLATFORM === "win32") return getPortsWindows();
  return [];
}

Mac/Linuxは lsof -iTCP -sTCP:LISTEN -nP でパースして、Windowsは netstat -ano + tasklist の合わせ技。lsof が使えないLinux環境では ss -tlnp にフォールバックするようにした。

KILLもOS分岐

function killByPid(pid) {
  if (PLATFORM === "win32") {
    execSync(`taskkill /F /PID ${pid}`, { timeout: 5000 });
  } else {
    execSync(`kill -9 ${pid}`, { timeout: 5000 });
  }
}

やってること自体は単純なんだけど、これをGUIのボタンでポチッとやれるのが楽。

Webview は1ファイルで完結

サイドバーの表示はWebview APIを使っていて、HTMLを1ファイルにまとめてる。CSSは var(--vscode-editor-background) みたいなVSCodeのCSS変数を使えば、テーマ追従が勝手に効く。外部ライブラリは何も使ってない。

:root {
  --bg: var(--vscode-editor-background);
  --fg: var(--vscode-editor-foreground);
  --accent: #00E676;
  --danger: #FF5252;
}

Reactとか入れるほどの画面じゃないし、素のHTML/JS/CSSで十分だった。

インストール方法

マーケットプレースで「Port Manager」で検索するか、コマンドラインなら:

code --install-extension port-manager-saiki.port-manager-saiki

自分でVSCode拡張を公開するまでの流れ

ついでに、初めてマーケットプレースに公開してみたのでメモ。

1. Azure DevOps でPATを取得

https://dev.azure.com にMicrosoftアカウントでログインして、右上のアイコンから「Personal access tokens」→「New Token」。

ここで絶対に気をつけるポイントがひとつあって、Organizationの欄で**「All accessible organizations」を選ぶこと**。特定のorganizationを選ぶと公開時にエラーで詰む。

Scopesは「Custom defined」→「Show all scopes」→「Marketplace」の「Manage」にチェック。

2. Publisherを作成

https://marketplace.visualstudio.com/manage でPublisherを作る。ここで設定したIDを package.json"publisher" に書く。

3. パッケージング & 公開

npm install -g @vscode/vsce
cd my-extension
vsce login <publisher-id>    # PATを入力
vsce package                 # .vsix生成(テスト用)
vsce publish                 # 公開

ファイル構成はこれだけ:

├── package.json
├── extension.js
├── README.md
├── CHANGELOG.md
├── LICENSE
├── .vscodeignore
└── images/icon.png

TypeScriptでビルドとか、webpackでバンドルとか、そういうの一切なし。extension.js 1ファイルでいけた。

ハマったところ

portal.azure.comdev.azure.com は別物

Azureを普段使ってると portal.azure.com に行きがちだけど、マーケットプレースの認証は dev.azure.com。全く別のサービス。リダイレクトされて「あれ?ポートの設定画面に来たんだけど??」ってなった。

Webview内の状態管理

Webviewはタブを切り替えると破棄されるので、acquireVsCodeApi() で取得したAPIを使ってpostMessageでやり取りする。Reactの感覚で状態を持つとハマる。

Windowsのnetstat出力のパース

Macの lsof は行儀のいい出力をしてくれるけど、Windowsの netstat はスペース区切りが微妙にブレるので split(/\s+/) でゴリ押し。tasklist と突き合わせてPID→プロセス名の変換もしてる。

まとめ

VSCode拡張、思ったより簡単だった。特にWebview APIが強力で、HTMLが書ければそれなりのUIが作れる。公開もvsceコマンド3つで終わる。

「こういうちょっとした面倒」を自動化する拡張を作るの、自分用ツールとしてもいいし、公開して誰かの役に立てばもっといい。

ソースコードはGitHubに上げてるので、気になる人は見てみてください。

👉 GitHub - port-manager-saiki/vscode-port-manager


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?