portless について
portlessは、ローカルWebアプリに変動するポート番号の代わりに、名前付きの安定した.localhost URLを割り当てる開発スキルです。プロキシ設定、モノレポ、Git worktree、フレームワークのポート処理を扱います。
主な機能
- 01名前付き.localhost URL
- 02HTTPSリバースプロキシ
- 03モノレポのパッケージ検出
- 04Git worktreeごとのURL割り当て
- 05フレームワーク向けポート引数の注入
活用シーン
- 01複数のローカルアプリをポート競合なく実行
- 02アプリ名でモノレポのサービスをルーティング
- 03Git worktreeごとに異なるURLを維持
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vercel-labs/ portless --skill portlessインストール後、Claude Code で/portlessを入力して読み込まれたか確認します。
詳細
Portless
ポート番号を、安定した名前付きの .localhost URL に置き換えます。人にもエージェントにも使えます。
Portless を使う理由
- ポートの競合:2 つのプロジェクトが同じポートをデフォルトで使うと
EADDRINUSEが発生します - ポート番号を覚える必要がある:3001 と 8080 のどちらで動いているアプリでしょうか?
- 更新すると別のアプリが表示される:サーバーを 1 つ停止し、同じポートで別のサーバーを起動すると、古いタブに別のコンテンツが表示されます
- モノレポでは問題が倍増:リポジトリ内の各サービスで、すべての問題が拡大します
- エージェントが間違ったポートをテストする:AI エージェントは間違ったポートを推測したり、ハードコードしたりします
- Cookie/ストレージの競合:
localhost上の Cookie がアプリ間で混在し、ポートが変わると localStorage が失われます - 設定内のポート番号のハードコード:CORS の許可リスト、OAuth のリダイレクト、
.envファイルは、ポートが変わると動作しなくなります - チームメイトとの URL の共有:「どのポートで動いているの?」という質問が Slack で飛び交います
- ブラウザーの履歴が役に立たない:
localhost:3000の履歴には、関係のないプロジェクトが混在します
インストール
グローバルにインストールするか(推奨)、プロジェクトの開発依存関係としてインストールします。単発の実行に npx や pnpm dlx は使用しないでください。
# Global (available everywhere)
npm install -g portless
# Or per-project dev dependency
npm install -D portless
プロジェクトごとにインストールした場合は、package.json のスクリプト経由で実行するか、npx portless を使います(パッケージがローカルにあるため、npx が何かをダウンロードすることはありません)。
クイックスタート
# Install globally (or add -D to a project)
npm install -g portless
# Run your app (auto-starts the HTTPS proxy on port 443)
portless run next dev
# -> https://<project>.localhost
# Or with an explicit name
portless myapp next dev
# -> https://myapp.localhost
アプリを実行すると、プロキシが自動的に起動します。portless proxy start で明示的に起動することもできます。自動起動では、直近のプロキシ実行時の設定(ポート、TLS、TLD)が再利用されるため、再起動や再起動後にデフォルト設定へ暗黙的に戻ることはありません。明示的に指定した環境変数は常に優先されます。
非対話型の環境(TTY がない、または CI=1)では、portless はプロンプトを表示する代わりに、内容がわかるエラーメッセージを出して終了します。turborepo などのタスクランナーでは、事前にプロキシを起動してください。
統合パターン
設定不要(推奨)
portless はそのまま使えます。package.json の "dev" スクリプトをプロキシ経由で実行し、パッケージ名、git ルート、またはディレクトリからアプリ名を推測します。
portless # -> runs "dev" script, https://<project>.localhost
pnpm dev # -> works without portless, plain "next dev"
デフォルト設定(名前、スクリプト、ポート)を上書きするには、任意で portless.json を使用します。
{ "name": "myapp" }
portless # -> runs "dev" script, https://myapp.localhost
モノレポ
リポジトリのルートに portless.json を 1 つ配置します。Portless は pnpm-workspace.yaml、または package.json の "workspaces" フィールド(npm、yarn、bun)からパッケージを検出します。
{
"apps": {
"apps/web": { "name": "myapp" },
"apps/api": { "name": "api.myapp" }
}
}
portless # from repo root: start all packages with a "dev" script
cd apps/web && portless # start just one package
portless --script start # run "start" instead of "dev"
apps マップは任意で、名前の上書きにのみ使用します。記載されていないパッケージは、名前を推測して自動検出されます。
apps マップがない場合、ホスト名は <package>.<project>.localhost となります。プロジェクト名には、最もよく使われている npm スコープが使用されます(例:@myorg/web と @myorg/api の場合は myorg)。該当するスコープがない場合は、ワークスペースのルートディレクトリ名が使われます。パッケージの短い名前がプロジェクト名と一致する場合は、<project>.localhost が使われます。
Turborepo
turborepo プロジェクトでは、実際のコマンドを別のスクリプトに置き、dev スクリプトとして portless を使います。
{
"scripts": { "dev": "portless", "dev:app": "next dev" },
"portless": { "name": "myapp", "script": "dev:app" }
}
pnpm dev は turbo を実行し、turbo は各パッケージで portless を実行します。Portless はパッケージマネージャーを検出し、プロキシ経由で pnpm run dev:app を実行します。
portless がワークスペースのルートから実行され、turbo.json または turbo.jsonc が読み取り可能な場合は、既存の Turbo 統合を使ってタスクの順序を維持します。直接起動する場合は、ルートの portless 設定で "turbo": false を指定してください。
package.json スクリプト
スクリプト内で portless を直接使うこともできます。
{
"scripts": {
"dev": "portless run next dev"
}
}
アプリを実行すると、プロキシが自動的に起動します。または、portless proxy start で明示的に起動できます。
サブドメインを使う複数アプリ構成
portless myapp next dev # https://myapp.localhost
portless api.myapp pnpm start # https://api.myapp.localhost
portless docs.myapp next dev # https://docs.myapp.localhost
デフォルトでは、明示的に登録されたサブドメインのみがルーティングされます(厳密モード)。プロキシを --wildcard 付きで起動すると、登録済みのルートに属する任意のサブドメインを、そのアプリへのフォールバックとして使えます(例:tenant1.myapp.localhost は myapp アプリにルーティングされます)。完全一致がワイルドカードより常に優先されます。ホストに対して複数の登録済みルートが親にあたる場合は、最も具体的なルートが優先されます(admin.api.myapp.localhost は myapp ではなく api.myapp にルーティングされます)。
Git worktrees
portless run は Git worktree を自動的に検出します。リンクされた worktree では、ブランチ名がサブドメインのプレフィックスとして付加されるため、各 worktree に固有の URL が割り当てられます。
# Main worktree (no prefix)
portless run next dev # -> https://myapp.localhost
# Linked worktree on branch "fix-ui"
portless run next dev # -> https://fix-ui.myapp.localhost
設定を変更する必要はありません。package.json に一度 portless run を追加すれば、すべての worktree で動作します。
portless をバイパスする
PORTLESS=0 を設定すると、プロキシを介さずにコマンドを直接実行できます。
PORTLESS=0 pnpm dev # Bypasses proxy, uses default port
プロキシ経由のコマンドを Ctrl+C で停止すると、portless はそのプロセスツリーが終了するまで待機します。2 回目の Ctrl+C を押すと、もう一度割り込みを転送し、残った子孫プロセスは短い猶予期間の後に終了します。
動作の仕組み
portless proxy startは、バックグラウンドデーモンとしてポート 443 で HTTPS リバースプロキシを起動します。macOS/Linux では自動的に sudo で昇格し、sudo が利用できない場合はポート 1355 にフォールバックします。平文 HTTP をポート 80 で使用するには、--no-tlsを使います。-p/--portまたはPORTLESS_PORT環境変数で設定できます。アプリを実行すると、プロキシも自動的に起動します。portless <name> <cmd>は、PORT環境変数を介して空いているランダムなポート(4000-4999)を割り当て、アプリをプロキシに登録します。- ブラウザーが
https://<name>.localhostにアクセスすると、プロキシがアプリに割り当てられたポートへ転送します。
LAN モード以外では、プロキシと HTTP リダイレクト用リスナーは、IPv4 および IPv6 のループバックアドレス 127.0.0.1 と ::1 にのみバインドされます。LAN、VPN、その他のネットワークインターフェース経由の接続は受け付けません。
portless 自体がエラーを返す場合(不明なホストに対する 404、誤った宛先へのリクエストに対する 421、アプリに到達できない場合の 502、リクエストループに対する 508)、レスポンス本文は Accept ヘッダーによって異なります。ブラウザー(text/html)には HTML ページが返されます。curl、fetch、その他のクライアントには、{"error":"bad_gateway","upstream":"myapp.localhost","message":"..."} のような JSON が返されます。error の値は not_found、misdirected_request、bad_gateway、loop_detected のいずれかです。HTML を解析するのではなく、この JSON を解析してください。アプリ自体からのレスポンスは変更されずに転送されます。たとえば、DNS ブロックリストが 127.0.0.1 を指すサイトなど、portless の TLD 以外のホスト名には、アプリ一覧ではなく 421 Misdirected Request が返されます。
.localhost ドメインは、Chrome、Firefox、Edge ではネイティブに 127.0.0.1 に解決されます。Safari はシステムの DNS リゾルバーに依存するため、すべての設定で .localhost サブドメインを処理できるとは限りません。必要に応じて、portless hosts sync を実行して /etc/hosts にエントリーを追加してください。
portless proxy start --tld localhost --tld test を使うと、1 つのプロキシから複数の TLD で同じアプリ名を提供できます。PORTLESS_URL では、最初に設定された TLD が使われます。設定された TLD が重複する場合(例:example.com と dev.example.com)、設定順にかかわらず、ホスト名は最も長い TLD から照合されます。PORTLESS_TLD では、PORTLESS_TLD=localhost,test のように、同じカンマ区切りのリスト形式を使用できます。
TLD には dev.example.com のような複数セグメントの DNS 名を指定できるため、ローカル URL を本番環境の構成に合わせられます(myapp.dev.example.com)。各ラベルは DNS の規則に従います。小文字、数字、途中に置くハイフンが使用でき、1 ラベルあたり 63 文字、全体で 253 文字までです。.localhost のリダイレクト URI を拒否する厳格な OAuth プロバイダーでも、https://myapp.dev.example.com/api/auth/callback/google のような実ドメインであれば受け入れられます。
ほとんどのフレームワーク(Next.js、Express、Nuxt など)は、PORT 環境変数を自動的に認識します。PORT を無視するフレームワーク(Vite、VitePlus、VitePress、Astro、React Router、Angular、Expo、React Native、Wrangler)では、portless が適切な --port フラグを自動挿入し、必要に応じて一致する --host CLI フラグ(Wrangler では --ip)も挿入します。挿入は、コマンドがフレームワークまたは既知のランナーで始まるパッケージスクリプト("dev": "vite"、"dev": "bunx vite")まで及びます。フラグが付与されるのはフレームワークのサーバーコマンド(dev、serve、preview、start、単独の vite、または vite [root])のみです。vite build、vite optimize、vp test、astro check のようなサーバーを起動しないコマンドはフラグを受け付けないため、そのまま実行されます。Expo の接続モード(--localhost、--lan、--tunnel)は維持され、割り当てられたポートも引き続き挿入されます。portless が分類できないスクリプトもそのまま実行されます。たとえば、フラグの文法を追跡していない CLI でサブコマンドより前にフラグがある場合(vp --mode dev build)です。フラグを追加しても機能しないスクリプトも、portless はそのまま実行します。該当するのは、複合コマンド(&&、|、;)、末尾の # コメント、独自の -- オプション終端子、環境変数プレフィックス(NODE_ENV=production vite)、別のスクリプトへの委譲("dev": "npm run dev:vite")、スクリプト名より前にランナーのフラグがある場合(bun run --bun dev)です。これらでは独自のポートが維持されるため、スクリプト内で設定してください。
状態ディレクトリ
Portless は状態(ルート、PID ファイル、ポートファイル)を ~/.portless に保存します。プロキシを sudo で実行した場合も、呼び出し元ユーザーのホームディレクトリが使われるため、権限のないアプリとプロキシでルート登録を共有できます。PORTLESS_STATE_DIR 環境変数で変更できます。
環境変数
| 変数 | 説明 |
|---|---|
PORTLESS_PORT | プロキシのデフォルトポートを上書きします(デフォルト:HTTPS では 443、HTTPS なしでは 80) |
PORTLESS_APP_PORT | アプリに固定ポートを使用します(自動割り当てをスキップ) |
PORTLESS_HTTPS | デフォルトで HTTPS が有効です。0 に設定すると無効になります(--no-tls と同じ) |
PORTLESS_LAN | 1 に設定すると、常に LAN モードを有効にします(LAN IP を自動検出) |
PORTLESS_LAN_IP | LAN モードで特定の LAN IP を固定します |
PORTLESS_TLD | 1 つ以上の TLD を使用します。単一セグメントまたは複数セグメントに対応します(例:localhost、dev.example.com) |
PORTLESS_WILDCARD | 1 に設定すると、未登録のサブドメインを親ドメインにフォールバックさせます |
PORTLESS_SYNC_HOSTS | 0 に設定すると、/etc/hosts の自動同期を無効にします(デフォルトで有効) |
PORTLESS_TAILSCALE | 1 に設定すると、Tailscale ネットワーク上でアプリを共有します(--tailscale と同じ) |
PORTLESS_FUNNEL | 1 に設定すると、Tailscale Funnel 経由でアプリを公開共有します(--funnel と同じ) |
PORTLESS_NGROK | 1 に設定すると、ngrok 経由でアプリを公開共有します(--ngrok と同じ) |
PORTLESS_CLOUDFLARE | 1 に設定すると、Cloudflare 経由でアプリを公開共有します(--cloudflare と同じ) |
PORTLESS_STATE_DIR | 状態ディレクトリを上書きします |
PORTLESS=0 | プロキシをバイパスし、コマンドを直接実行します |
HTTP/2 + HTTPS
HTTP/2 による HTTPS はデフォルトで有効です(ファイル数の多い開発サーバーでページの読み込みが高速になります)。WebSocket は HTTP/1.1(Upgrade)と HTTP/2(RFC 8441 extended CONNECT)の両方で動作するため、開発サーバーの HMR はプロキシ経由で機能します。初回実行時にローカル CA が生成され、システムの信頼ストアに追加されます。その後は確認もブラウザーの警告も表示されません。
portless proxy start --cert ./c.pem --key ./k.pem # Use custom certs
portless proxy start --no-tls # Disable HTTPS (plain HTTP)
portless trust # Add CA to trust store later
Linux では、portless trust は Debian/Ubuntu、Arch、Fedora/RHEL/CentOS、openSUSE に対応しています(update-ca-certificates または update-ca-trust を使用)。Windows では、certutil を使って CA をシステムの信頼ストアに追加します。WSL では、Linux の信頼ストアと Windows の現在のユーザーの Root ストアの両方を更新するため、Windows のブラウザーで portless の HTTPS 証明書が信頼されます。WSL2 ホスト上の Linux コンテナーでは、Linux の信頼ストアのみが使用されます。
LAN モード
portless proxy start --lan
portless proxy start --lan --https
portless proxy start --lan --ip 192.168.1.42
--lan を指定すると、プロキシが IPv4 と IPv6 の未指定アドレスである 0.0.0.0 と :: に明示的にバインドされ、mDNS 経由で <name>.local ホスト名がアドバタイズされるため、同じ Wi-Fi 上のデバイスからアプリにアクセスできます。Portless は LAN IP を自動検出し、ネットワークの変更にも自動で追従しますが、--ip <address> または PORTLESS_LAN_IP 環境変数を使って特定のアドレスを固定できます。毎回プロキシの起動時に LAN モードをデフォルトにするには、PORTLESS_LAN=1 を設定します。
Portless は proxy.lan を通じて LAN モードを記憶するため、LAN プロキシを停止して再起動しても、LAN モードは維持されます。すべてのプロキシ設定(ポート、TLS、TLD、LAN)は保存され、明示的なフラグまたは環境変数で上書きされない限り、自動起動時に再利用されます。1回の起動で .localhost モードに戻すには、PORTLESS_LAN=0 を使用します。異なる明示的な LAN/TLS/TLD 設定でプロキシがすでに実行中の場合、portless は警告を表示し、先に停止するよう求めます。
LAN モードは、portless が起動するシステムの mDNS ヘルパーに依存します。macOS には dns-sd が含まれていますが、Linux では avahi-utils の avahi-publish-address を使用します(sudo apt install avahi-utils またはお使いのディストリビューションのツールを使ってインストールしてください)。
-
Next.js:
.localホスト名をallowedDevOriginsに追加します。// next.config.js module.exports = { allowedDevOrigins: ["myapp.local", "*.myapp.local"], }; -
Expo / React Native:portless は常に
--portを挿入します。React Native には--host 127.0.0.1も設定されます。Expo には LAN モード以外では--host localhostが設定されますが、LAN モードでは portless は--hostやHOSTを強制せず、Metro のデフォルトの LAN ホスト動作をそのまま使用します。
Tailscale 共有
--tailscale を使って Tailscale ネットワーク上のチームメイトと開発サーバーを共有するか、--funnel を使ってパブリックインターネットに公開します。
portless myapp --tailscale next dev
# -> https://myapp.localhost (local)
# -> https://devbox.yourteam.ts.net (tailnet)
portless myapp --funnel next dev
# -> https://myapp.localhost (local)
# -> https://devbox.yourteam.ts.net (public internet)
--tailscale または --funnel で HTTPS URL を登録する前に、Tailscale HTTPS 証明書を有効にする必要があります。--funnel でパブリック URL を登録するには、tailnet とノードの両方で Funnel も有効にする必要があります。いずれかの設定が不足している場合、portless は子プロセスを起動する前に終了します。
各 --tailscale アプリは、それぞれ専用の Tailscale HTTPS ポート(443、次に 8443、8444 など)でルートマウントされるため、フレームワークの basePath 設定は不要です。すべてのアプリをデフォルトで共有するには、PORTLESS_TAILSCALE=1 を設定します。portless list にはローカル URL と tailnet URL の両方が表示されます。アプリの終了時に Tailscale serve の登録はクリーンアップされます。Tailscale HTTPS 証明書を有効にした状態で、tailscale CLI をインストールして接続しておく必要があります。
ngrok 共有
--ngrok を使って開発サーバーをパブリックインターネットに公開します。
portless myapp --ngrok next dev
# -> https://myapp.localhost (local)
# -> https://abc123.ngrok.app (public internet)
portless がアプリを実行する際に ngrok をデフォルトで有効にするには、PORTLESS_NGROK=1 を設定します。portless list にはローカル URL と ngrok URL の両方が表示されます。アプリの終了時に ngrok トンネルはクリーンアップされます。ngrok CLI をインストールし、ngrok config add-authtoken <token> で認証しておく必要があります。
Cloudflare 共有
portless myapp --cloudflare next dev
# -> https://<random>.trycloudflare.com (public internet)
--cloudflare は Cloudflare のクイックトンネルを開きます。Cloudflare アカウントは不要です。デフォルトで有効にするには、PORTLESS_CLOUDFLARE=1 を設定します。アプリには PORTLESS_CLOUDFLARE_URL が設定され、portless list には cloudflare: の行が表示されます。アプリの終了時にトンネルは停止します。--ngrok、--tailscale、--funnel と組み合わせることができます。クイックトンネルは Server-Sent Events をサポートせず、同時に処理中のリクエストは最大 200 件で、実行のたびに新しい URL が割り当てられます。cloudflared CLI が PATH 上に必要です(https://developers.cloudflare.com/tunnel/downloads/)。
OS 起動サービス
再起動後にプロキシを自動的に起動したい場合は、サービスコマンドを使用してください。
portless service install
portless service install --lan
portless service install --wildcard
PORTLESS_STATE_DIR=~/.portless-lan PORTLESS_LAN=1 portless service install
portless service status
portless service uninstall
インストールオプションまたは PORTLESS_* 環境変数が指定されていない場合、サービスは portless のデフォルト設定を使用します。HTTPS はポート 443 で、名前には .localhost を使用します。service install では、--port、--no-tls、--lan、--ip、--tld、--wildcard、--cert、--key などのプロキシオプションを指定できます。サービスの状態とログの書き込み先を選択するには、--state-dir <path> または PORTLESS_STATE_DIR=<path> を使用してください。
選択したサービス設定は launchd、systemd、または Task Scheduler に書き込まれ、再起動後も再利用されます。portless service status を実行すると、インストール済みのポート、HTTPS モード、TLD、LAN モード、ワイルドカードモード、状態ディレクトリが表示されます。macOS と Linux では、起動時にポート 443 をバインドできるよう、root 所有のサービスをインストールします。Windows では、SYSTEM として実行される Task Scheduler の起動タスクをインストールします。インストールと削除には、管理者権限が必要になる場合があります。portless clean を実行すると、サービスは自動的に削除されます。
CLI リファレンス
| コマンド | 説明 |
|---|---|
portless | プロキシ経由で開発スクリプトを実行します |
portless | モノレポのルートから、すべてのワークスペースパッケージを実行します |
portless --script <name> | 特定の package.json スクリプトを実行します(デフォルト:dev) |
portless run [cmd] [args...] | プロジェクトから名前を推測し、プロキシ経由で実行します(自動起動) |
portless run --name <name> <cmd> | 推測されたベース名を上書きします(ワークツリーのプレフィックスは適用されます) |
portless <name> <cmd> [args...] | https://<name>.localhost でアプリを実行します(プロキシを自動起動) |
portless get <name> | サービスの URL を表示します(サービス間の接続設定用) |
portless get <name> --no-worktree | ワークツリーのプレフィックスなしで URL を表示します |
portless list | アクティブなルートと稼働時間を表示します |
portless doctor | プロキシ、ルート、DNS、CA の信頼設定、LAN の前提条件を確認します |
portless trust | ローカル CA をシステムの信頼ストアに追加します(HTTPS 用) |
portless clean | 状態、CA の信頼エントリー、/etc/hosts のブロックを削除します |
portless prune | 孤立した開発サーバーグループを終了します。run も起動時に実行します |
portless prune --force | SIGTERM の代わりに SIGKILL で孤立プロセスを終了します |
portless proxy start | HTTPS プロキシをデーモンとして起動します(ポート 443、自動で昇格) |
portless proxy start --no-tls | HTTPS なしで起動します(ポート 80 のプレーンな HTTP) |
portless proxy start --lan | LAN モードで起動します(mDNS の .local、LAN IP の変更に自動追従) |
portless proxy start -p <number> | 指定したポートでプロキシを起動します |
portless proxy start --tld test | .localhost の代わりに .test を使用します |
portless proxy start --tld localhost --tld test | 1 つのプロキシで両方の TLD を提供します |
portless proxy start --tld dev.example.com | 本番環境と同等の URL に複数セグメントの TLD を使用します |
portless proxy start --foreground | プロキシをフォアグラウンドで起動します(デバッグ用) |
portless proxy start --wildcard | 未登録のサブドメインを親ルートにフォールバックさせます |
portless proxy stop | プロキシを停止します |
portless service install | OS の起動時に HTTPS プロキシを起動します |
portless service install --lan | LAN モードでサービスを起動します |
portless service install --wildcard | 起動サービスでワイルドカードルーティングを永続化します |
portless service status | サービスとプロキシの状態を表示します |
portless service uninstall | 起動サービスを削除します |
portless alias <name> <port> | 静的ルートを登録します(Docker コンテナなどに使用) |
portless alias <name> <port> --force | 既存のルートを上書きします |
portless alias --remove <name> | 静的ルートを削除します |
portless hosts sync | ルートを /etc/hosts と同期します(Safari の問題を修正) |
portless hosts clean | /etc/hosts から portless のエントリーを削除します |
portless <name> --app-port <n> <cmd> | 自動割り当ての代わりに、アプリで固定ポートを使用します |
portless <name> --tailscale <cmd> | Tailscale ネットワーク(テールネット)上でアプリを共有します |
portless <name> --funnel <cmd> | Tailscale Funnel 経由でアプリをインターネット上に公開します |
portless <name> --ngrok <cmd> | ngrok 経由でアプリをインターネット上に公開します |
portless <name> --cloudflare <cmd> | Cloudflare クイックトンネル経由でアプリをインターネット上に公開します |
portless <name> --force <cmd> | 既存のプロセスを終了し、そのルートを引き継ぎます |
portless --name <name> <cmd> | <name> をアプリ名として強制指定します(サブコマンドの振り分けを回避) |
portless <name> -- <cmd> [args...] | フラグの解析を停止します。-- の後はすべて子プロセスに渡されます |
portless --help / -h | ヘルプを表示します |
portless run --help | サブコマンドのヘルプを表示します(alias、hosts、clean も同様) |
portless --version / -v | バージョンを表示します |
予約済みの名前: run、get、alias、hosts、list、doctor、trust、clean、prune、proxy、service、mcp はサブコマンドのため、アプリ名として直接使用できません。名前を推測させるには portless run <cmd> を使用するか、portless --name <name> <cmd> を使用して、予約済みの名前を含む任意の名前を指定してください。 |
MCP サーバー
portless mcp [--tools <profiles>] は、stdio MCP サーバーを起動します。既定では core が使用され、ルート一覧、URL の検索、静的エイリアスの管理、プロファイルの検出を利用できます。必要に応じて、proxy、diagnostics、all のプロファイルをカンマ区切りで追加してください。default は core の別名で、full は all の別名です。tools_profiles ツールには、利用可能なプロファイルが一覧表示されます。共通のツール引数は cwd、extraArgs、timeoutMs です。不正な引数(未知の型または誤った型)や、有効になっていないツールの呼び出しには、修正方法を説明する isError: true のツール結果が返されるため、モデルは呼び出しを修正できます。未知の引数がある場合は、そのツール固有の引数が一覧表示されます。MCP は開発サーバーを実行しません。シェルで portless run <cmd> を実行して起動してください。
{ "mcpServers": { "portless": { "command": "portless", "args": ["mcp"] } } }
portless.json
省略可能な設定ファイルです。Portless はカレントディレクトリ内でこのファイルを探します。
| フィールド | 型 | 既定値 | 説明 |
|---|---|---|---|
name | 文字列 | package.json から推測 | アプリのベース名(ワークツリーのプレフィックスは引き続き適用されます) |
script | 文字列 | "dev" | 実行する package.json スクリプトの名前 |
appPort | 数値 | 自動割り当て | 子プロセスに固定で割り当てるポート |
proxy | 真偽値 | 自動検出 | プロキシ経由でルーティングするかどうか(タスクの場合は false) |
apps | オブジェクト | ワークスペースのパッケージに対する相対パスをキーとした上書き設定 | |
turbo | 真偽値 | true | turborepo の代わりに直接起動する場合は false に設定 |
各 apps エントリーは、同じ形式(name、script、appPort、proxy)です。apps がある場合、トップレベルのフィールドは単一アプリモードでのみ適用されます。
package.json の "portless" キー
個別の portless.json の代わりに、package.json に "portless" キーを追加できます。文字列を指定すると、名前を設定する簡略表記になります。
{ "portless": "myapp" }
オブジェクトでは、アプリごとのすべてのフィールド(name、script、appPort、proxy)を設定できます。
{ "portless": { "name": "myapp", "script": "dev:app" } }
優先順位(より近い設定が優先):CLI フラグ > package.json の "portless" キー > portless.json のアプリエントリー > 既定値。
トラブルシューティング
診断の実行
ローカルルーティングや HTTPS の動作に問題がある場合は、まず portless doctor を実行してください。このコマンドは読み取り専用で、Node.js、状態ディレクトリのアクセス許可、プロキシの稼働状況、ルートエントリー、ホスト名の解決、ローカル CA の信頼設定、LAN モードの前提条件を確認します。
プロキシが起動していない
portless <name> <cmd> でアプリを実行すると、プロキシは自動的に起動します。起動しない場合(例:ポートの競合)は、手動で起動してください。
portless proxy start
ポートがすでに使用されている
別のプロセスがプロキシのポートを使用しています。先にそのプロセスを停止するか、別のポートを使用してください。
portless proxy start -p 8080
PORT を尊重しないフレームワーク
Portless は、PORT 環境変数を無視するフレームワークに対して、適切な --port フラグを自動的に挿入し、必要に応じて対応する --host フラグも挿入します。対象は Vite、VitePlus(vp)、VitePress、Astro、React Router、Angular、Expo、React Native、Wrangler(--host の代わりに --ip を使用)です。SvelteKit は内部で Vite を使用するため、自動的に処理されます。挿入は、コマンドがフレームワーク名または既知のランナー名で始まるパッケージスクリプトを通じて行われ、フレームワークのサーバーコマンド(dev、serve、preview、start、または単独の vite)に限られます。vite build、vite optimize、vp test など、サーバーを起動しないコマンドはフラグを受け付けないため、そのまま変更されません。また、Portless が分類できない呼び出し(vp --mode dev build)も対象外です。複合コマンド(&&、|、;)、末尾の # コメント、独自の -- オプション終端子、環境変数の接頭辞(NODE_ENV=production vite)、別スクリプトへの委譲、スクリプト名より前にあるランナーフラグ(bun run --bun dev)が含まれる場合も挿入はスキップされます。これらの場合はそれぞれ独自のポートが使用されるため、アプリは 502 を返します。スクリプト内でポートを設定してください。
PORT を読み取らないその他のフレームワークでは、ポートを手動で渡してください。
- Webpack Dev Server:
--port $PORTを使用します - カスタムサーバー:
process.env.PORTを読み取り、そのポートでリッスンします
権限エラー
デフォルトのポート(HTTP は 80、HTTPS は 443)の使用には、macOS と Linux では sudo が必要です。必要に応じて Portless が自動的に sudo で昇格します。sudo を利用できない場合は、ポート 1355 にフォールバックします(sudo は不要です)。Windows では昇格は不要です。
portless proxy start --https # Auto-elevates with sudo for port 443
portless proxy start -p 1355 --https # No sudo needed (URLs include :1355)
portless proxy stop # Stop (use sudo if started with sudo)
Safari で .localhost URL が見つからない
Safari は .localhost サブドメインの解決にシステム DNS リゾルバーを使用するため、一部の macOS 構成では解決できない場合があります。Chrome、Firefox、Edge には組み込みの処理機能があります。
修正方法:
portless hosts sync # Reconcile current routes with /etc/hosts
portless hosts clean # Remove entries later
デフォルトでは、ルートのホスト名を /etc/hosts に自動同期します。無効にするには PORTLESS_SYNC_HOSTS=0 を設定します。ルートのホスト名が解決できない場合は、登録したコマンドが警告を表示し、portless hosts sync を案内します。
手動同期では、portless が管理するエントリーを現在のルートと照合し、ルートがない場合は古いエントリーを削除します。書き込みの前に、hosts ファイルの初回読み取りが正常に完了している必要があり、書き込み後は各書き込みを検証します。読み取りまたは検証に失敗すると、通常の同期エラー処理が行われます。
--https でブラウザーに証明書の警告が表示される
ローカル CA がまだ信頼されていない可能性があります。次を実行してください。
portless trust
これにより、portless のローカル CA がシステムの信頼ストアに追加されます。その後、ブラウザーを再起動してください。
マシンから portless を削除する
portless clean
必要に応じてプロキシを停止し、信頼ストアから portless CA を削除し(portless が追加した場合)、状態ディレクトリ内の既知のファイルを削除して、portless の /etc/hosts ブロックを削除します。macOS/Linux では sudo が必要な場合があります。信頼ストアからの削除に失敗した場合、portless は CA 証明書とキーを保持するため、後で portless clean を実行して安全に再試行できます。
プロキシループ(508 Loop Detected)
開発サーバーが別の portless アプリにリクエストをプロキシする場合(例:Vite が /api を api.myapp.localhost にプロキシする場合)、プロキシで Host ヘッダーを書き換える必要があります。書き換えないと、portless がリクエストを元のアプリにルーティングし、無限ループが発生します。
修正方法:プロキシ設定(Vite、webpack-dev-server など)で changeOrigin: true を設定します。
// vite.config.ts
proxy: {
"/api": {
target: "https://api.myapp.localhost",
changeOrigin: true,
ws: true,
},
}
Portless は、Node.js が portless CA を信頼できるよう、子プロセスに NODE_EXTRA_CA_CERTS を自動的に設定します。portless の外部で別の Node.js プロセスを実行する場合は、CA を手動で指定してください:NODE_EXTRA_CA_CERTS=~/.portless/ca.pem。または、プレーン HTTP を使用するには --no-tls を指定してください。
Tailscale が動作しない
--tailscale または --funnel が失敗する場合:
tailscale status # Check if connected
tailscale up # Connect to your tailnet
Tailscale CLI がインストールされ、PATH に含まれている必要があります(https://tailscale.com/download)。
ngrok が動作しない
--ngrok が失敗する場合:
ngrok version # Check if installed
ngrok config add-authtoken <token> # Configure authentication
ngrok CLI がインストールされ、PATH に含まれている必要があります(https://ngrok.com/download)。
必要条件
- Node.js 24 以降
- macOS、Linux、または Windows
openssl(--httpsでの証明書生成に使用。macOS とほとんどの Linux ディストリビューションに付属しています。Windows では、winget install -e --id ShiningLight.OpenSSL.Devでインストールするか、Git for Windows に同梱されているものを使用してください)tailscaleCLI(任意。--tailscaleと--funnelで使用)ngrokCLI(任意。--ngrokで使用)cloudflaredCLI(任意。--cloudflareで使用)