outport について
Outportは、プロジェクトやGit worktree間のポートとローカルホスト名を管理するコマンドラインツールです。割り当て結果や計算したURLを.envファイルに書き込み、.testホスト名のプロキシも設定できます。
主な機能
- 01決定的に競合しないポートを割り当て
- 02ポートと計算値を.envに書き込み
- 03サービスに.testホスト名を割り当て
- 04Git worktreeのインスタンスを自動識別
- 05JSON出力で状態を表示
活用シーン
- 01プロジェクトの開発サービスにポートを割り当て
- 02monorepoの複数の.envファイルで設定を同期
- 03複数のworktreeインスタンスを並行稼働
- 04サービスのポート、ヘルス、URLを確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ steveclarke/ outport --skill outportインストール後、Claude Code で/outportを入力して読み込まれたか確認します。
詳細
Outport — 開発ポートマネージャー
Outport は、開発サービスに決定的で競合しないポートを割り当て、.test ホスト名を設定し、すべてを .env ファイルに書き込みます。Rails、Nuxt、Django、Docker Compose など、すべてのフレームワークが .env を読み取るため、手動で設定しなくてもポートと URL をそのまま利用できます。
クイックリファレンス
# Project commands
outport init # Create outport.yml (interactive)
outport up # Allocate ports, assign hostnames, write .env
outport up --force # Clear and re-allocate all ports from scratch
outport down # Remove ports and clean .env files
# Inspect & diagnose
outport status # Show project status (ports, health, URLs)
outport status --computed # Include computed values
outport ports # Show ports with live process info (PID, memory, uptime)
outport ports --all # Full machine scan (Outport + non-Outport ports)
outport ports --down # Include ports with no running process
outport ports kill <svc> # Kill process by service name or port number
outport ports kill --orphans # Kill all orphaned dev processes
outport open # Open HTTP services in browser
outport open web # Open a specific service
outport open admin # Open a unique alias
outport open web:admin # Open a specific service alias
outport share # Tunnel HTTP services to public URLs
outport share web # Tunnel a specific service
outport qr # Show QR codes for mobile device access
outport qr --tunnel # Show QR codes with tunnel URLs
outport doctor # Check system health and project config
# System commands (machine-wide)
outport system start # Install DNS, CA, and start the daemon
outport system stop # Stop the daemon
outport system restart # Re-write plist and restart the daemon
outport system status # Show all registered projects
outport system status --check # Show with health checks (up/down)
outport system prune # Remove stale and duplicate registry entries
outport system uninstall # Remove DNS resolver, daemon, and CA
# Instance management
outport rename <old> <new> # Rename the current instance
outport promote # Promote the current instance to main
すべてのコマンドは、機械で読み取り可能な出力を得るための --json に対応しています。
新しいプロジェクトのセットアップ
1. outport.yml を作成する
対話形式でセットアップするには outport init を実行するか、手動で作成します。
name: my-project
services:
web:
env_var: PORT
postgres:
env_var: DB_PORT
redis:
env_var: REDIS_PORT
2. outport up を実行する
決定的なポート(プロジェクト名とサービス名からハッシュ化)を割り当て、.env に書き込みます。同じ入力には常に同じポートが割り当てられます。
3. プロジェクトで .env を読み込むように設定する
ほとんどのフレームワークは、標準で、または最小限の設定で .env を読み込みます。
- Docker Compose —
.envを自動で読み込みます。compose.ymlでは${DB_PORT:-5432}を使用します - Rails —
dotenv-railsgem を使うか、設定で環境変数を参照します。port: ENV.fetch("DB_PORT", 5432) - Nuxt — 標準で
.envを読み込みます。ランタイム設定の値はNUXT_*環境変数で上書きできます - Foreman —
.envを自動で読み込みます - Overmind —
.envを自動では読み込みません。起動スクリプトで読み込みます。if [ -f .env ]; then set -a; source .env; set +a; fi
4. outport.yml をコミットし、.env を gitignore に追加する
outport.yml はプロジェクト設定ファイルです。ワークツリーやチームメイトに設定を引き継ぐため、コミットしてください。.env には割り当てられたポートが含まれるため、gitignore に追加してください。チェックアウトごとに個別のファイルが使われます。
.test ドメイン(DNS プロキシ)
一度 outport system start を実行すると、サービスにわかりやすい .test ホスト名を利用できるようになります。セットアップ後は、https://myapp.test が http://localhost:24920 ではなく、アプリにルーティングされます。
仕組み
outport system start は、3 つのコンポーネントをインストールします(DNS と CA の信頼設定には sudo が必要です)。
- DNS リゾルバー — OS を設定し、
*.testの問い合わせをポート 15353 で動作するローカル DNS サーバーに送信します。このサーバーは、すべての*.test名を127.0.0.1に名前解決します。macOS では/etc/resolver/test、Linux では systemd-resolved のドロップイン設定を使用します。 - リバースプロキシ — デーモンがポート 80 と 443 で動作し、
Hostヘッダーに基づいてリクエストを適切なサービスのポートにルーティングします。また、outport upの実行時に自動で更新されます。WebSocket 接続も透過的にプロキシされます。macOS では launchd、Linux では systemd によって管理されます。 - ローカル CA — HTTPS 用の認証局を生成します。ポート 80 への HTTP リクエストは 307 で HTTPS にリダイレクトされます。
outport system start # Install DNS + CA + daemon (one-time, prompts for sudo)
outport system stop # Stop the daemon
outport system restart # Re-write plist and restart the daemon
outport system uninstall # Remove everything — reverse of start
.test ホスト名の設定
サービスに hostname を追加すると、そのサービスに .test URL を割り当てられます。
name: myapp
services:
web:
env_var: PORT
hostname: myapp.test # → https://myapp.test
postgres:
env_var: DB_PORT # no hostname: port allocation only
ホスト名のルール:
- プロジェクト名を含める必要があります(例:
myapp.test、app.myapp.test) - メインではないインスタンスには、インスタンスコードが自動的に追加されます(複数インスタンスを参照)
Cookie の分離
各インスタンスには独自の .test ホスト名が割り当てられるため、ブラウザーの Cookie とセッションは自動的に分離されます。シークレットウィンドウは必要ありません。
myapp [main] web → 24920 http://myapp.test
myapp [bkrm] web → 28104 http://myapp-bkrm.test
設定リファレンス
プロジェクトレベルのフィールド
| フィールド | 必須 | 説明 |
|---|---|---|
name | はい | プロジェクト識別子です。ポートの割り当てとホスト名の生成に使用します。 |
open | いいえ | outport open がデフォルトで開くサービス名のリストです。省略すると、ホスト名が設定されているすべてのサービスを開きます。 |
サービスのフィールド
| フィールド | 必須 | 説明 |
|---|---|---|
env_var | はい | .env に書き込む環境変数名です |
hostname | いいえ | このサービスの .test ホスト名です(例:myapp.test)。HTTP を有効にします。メインではないインスタンスには、インスタンスコードが追加されます。 |
aliases | いいえ | 名前付きの代替ホスト名です(ラベル → ホスト名のマップ)。各エイリアスは同じポートにルーティングされます。hostname が必要です。 |
subdomains | いいえ | ワイルドカードのサブドメインルーティング(*.myapp.test)を有効にします。すべてのサブドメインが同じポートにルーティングされます。hostname が必要です。 |
preferred_port | いいえ | 最初に試すポートです。すでに使用中の場合は、ハッシュベースの割り当てにフォールバックします |
env_file | いいえ | 書き込み先です。文字列または配列を指定します。デフォルトはプロジェクトルートの .env です |
複数の .env ファイルへの書き込み
モノレポでは、ポートを複数の .env ファイルに記述する必要があることがよくあります。env_file には配列を使用してください。
services:
rails:
env_var: RAILS_PORT
env_file:
- backend/.env
- frontend/.env # Frontend needs this to construct API URLs
計算値
アプリケーションに必要なのはポート番号だけではなく、URL も必要です。計算値はサービスマップから環境変数を計算し、完成した値を .env に書き込みます。
基本構文
computed:
API_URL:
value: "${rails.url:direct}/api/v1" # http://localhost:24920/api/v1
env_file: frontend/.env
CORS_ORIGINS:
value: "${web.url}" # http://myapp.test (or localhost:PORT)
env_file: backend/.env
${service_name.field}はサービスのフィールドを参照しますenv_fileは必須です(デフォルト値はありません。明示的に指定する必要があります)- 計算値の名前は、サービスの
env_var名と重複してはなりません
テンプレートフィールド
| テンプレート | 解決される値 | 用途 |
|---|---|---|
${rails.port} | 24920 | ポート番号そのもの |
${rails.hostname} | myapp.test(ホスト名が設定されていない場合は localhost) | ホスト名のみ |
${rails.url} | http://myapp.test | プロキシ経由でルーティングされる、ブラウザー向け URL(CORS、アセットホスト) |
${rails.url:direct} | http://localhost:24920 | プロキシを経由しない、サーバー間通信 |
${rails.env_var} | PORT | サービスの環境変数名 |
${rails.alias.NAME} | app.myapp.test | ラベルで指定するエイリアスのホスト名 |
${rails.alias_url.NAME} | https://app.myapp.test | ラベルで指定するエイリアスの URL |
url と url:direct の使い分け:
${service.url}— ブラウザーから送信される値に使用します(CORS オリジン、アセットホスト、OAuth リダイレクト URI)。設定されている場合は.testホスト名を使用します。${service.url:direct}— サーバー間通信に使用します(バックエンドが取得する API のベース URL、Node サーバーからの WebSocket 接続)。常にlocalhostを使用し、プロキシを経由しません。
スタンドアロン変数と Bash 形式のパラメーター展開
計算値では、インスタンスごとの設定に対応するスタンドアロン変数と Bash 形式のパラメーター展開を使用できます。
| 変数 | メインインスタンス | Worktree インスタンス(例:bxcf) |
|---|---|---|
${project_name} | myapp | myapp |
${instance} | (空文字列) | bxcf |
${instance:-default} | default | bxcf |
${instance:+replacement} | (空文字列) | replacement |
${instance:+-${instance}} | (空文字列) | -bxcf |
よく使われるパターン — Docker Compose のプロジェクト名:
computed:
COMPOSE_PROJECT_NAME:
value: "${project_name}${instance:+-${instance}}"
env_file: .env
これにより、メインインスタンスでは myapp、Worktree では myapp-bxcf が生成され、各インスタンスの Docker コンテナーが分離されます。
ファイルごとの値の上書き
同じ環境変数にファイルごとに異なる値が必要な場合(複数のアプリがフレームワークの規約を共有するモノレポでよくあります)は、env_file エントリーにオブジェクト構文を使用してください。
computed:
NUXT_API_BASE_URL:
env_file:
- file: frontend/apps/main/.env
value: "${rails.url:direct}/api/v1"
- file: frontend/apps/portal/.env
value: "${rails.url:direct}/portal/api/v1"
同じリスト内で、トップレベルの value を使用するプレーンな文字列エントリーとオブジェクトエントリーを組み合わせることができます。
実際のモノレポの例
Rails バックエンドと 2 つの Nuxt フロントエンドの構成です。バックエンドはフロントエンドの .test URL を CORS オリジンとして必要とします。フロントエンドはサーバー側の取得処理で Rails API の URL を必要とします。
name: myapp
services:
rails:
env_var: RAILS_PORT
hostname: myapp.test
env_file: backend/.env
frontend_main:
env_var: MAIN_PORT
hostname: app.myapp.test
env_file:
- frontend/apps/main/.env
- backend/.env # Backend needs this for CORS
frontend_portal:
env_var: PORTAL_PORT
hostname: portal.myapp.test
env_file:
- frontend/apps/portal/.env
- backend/.env # Backend needs this for CORS
computed:
# Server-to-server API URLs (bypass proxy — use direct localhost)
NUXT_API_BASE_URL:
env_file:
- file: frontend/apps/main/.env
value: "${rails.url:direct}/api/v1"
- file: frontend/apps/portal/.env
value: "${rails.url:direct}/portal/api/v1"
# Backend CORS (browser-facing — use .test hostnames)
CORE_CORS_ORIGINS:
value: "${frontend_main.url},${frontend_portal.url}"
env_file: backend/.env
# Backend asset host (browser-facing)
SHRINE_ASSET_HOST:
value: "${rails.url}"
env_file: backend/.env
outport up の実行後は、すべてのサービスに正しいポートと URL が設定されます。ハードコードされた値は残りません。
フレームワークの環境変数規約
計算値を設定する際は、フレームワークが環境変数を設定にどう対応付けるかを把握することが重要です。
| フレームワーク | 規約 | 例 |
|---|---|---|
| Nuxt | NUXT_ プレフィックスを runtimeConfig に対応付けます | NUXT_API_BASE_URL は runtimeConfig.apiBaseUrl を上書きします |
| Rails (AnyWayConfig) | PREFIX_ATTR を設定クラスに対応付けます | CORE_CORS_ORIGINS は CoreConfig.cors_origins を上書きします |
| Rails (Shrine) | AnyWayConfig と同じパターンです | SHRINE_ASSET_HOST は ShrineConfig.asset_host を上書きします |
| Django | 通常は os.environ を直接読み取ります | settings.py が期待する名前で変数を指定します |
| Docker Compose | .env を自動的に読み取ります | compose.yml 内の ${DB_PORT:-5432} |
計算値機能は、こうしたフレームワークの規約に合った環境変数を書き込む場合に最も効果を発揮します。フレームワークが値をそのまま読み取るため、設定コードを変更する必要はありません。
.env ファイル形式
Outport は、管理対象の変数を各 .env ファイルの末尾にフェンス付きブロックとして書き込みます。
# Your own variables — Outport never touches these
SECRET_KEY=abc123
RAILS_ENV=development
# --- begin outport.dev ---
DB_PORT=21536
RAILS_PORT=24920
NUXT_API_BASE_URL=http://localhost:24920/api/v1
# --- end outport.dev ---
outport up を実行するたびに、フェンス付きブロックは最新の値に置き換えられます。outport.yml から削除された変数はブロックからも削除されます。ブロック外の内容はすべて保持されます。
複数のインスタンス
Outport は Git のワークツリーを自動的に検出します。各ワークツリーには固有のポートと専用の .test ホスト名が割り当てられるため、設定は不要です。
# Main checkout
$ outport up
my-app [main]
rails RAILS_PORT → 24920 http://my-app.test
web MAIN_PORT → 21349
# Worktree — different ports, different hostname, zero conflicts
$ cd ../my-app-feature && outport up
Registered as my-app-bkrm. Use 'outport rename bkrm <name>' to rename.
my-app [bkrm]
rails RAILS_PORT → 20192 http://my-app-bkrm.test
web MAIN_PORT → 21133
計算値はインスタンスごとに再計算されます。CORS オリジン、API URL、その他すべての計算値には、そのインスタンスのポートとホスト名が自動的に使われます。2 つの完全なインスタンスを、ポートやホスト名の競合、手動設定なしで同時に実行できます。
次のコマンドでインスタンスを管理します。
outport rename bkrm my-feature # Rename an instance
outport promote # Promote current instance to main
セットアップスクリプトとの統合
プロジェクトのセットアップフローでは、.env ファイルを作成した後、サービスを起動する前の早い段階で outport up を実行します。Outport を使わない開発者の妨げにならないよう、任意の処理にしてください。
# In bin/setup or similar
if command -v outport > /dev/null 2>&1; then
outport up
else
echo "Outport not found — using default ports"
echo "Install: brew install steveclarke/tap/outport"
fi
よくあるタスク
別のプロジェクトとポートが競合する
両方のプロジェクトで outport up を実行します。Outport のレジストリにより、登録済みのすべてのプロジェクト間で競合が発生しないようになります。
古い割り当てのポートが残っている
outport up --force を実行して、割り当てをクリアして再割り当てします。
使用を終えたプロジェクトのポートを解放する
outport down を実行してレジストリから削除し、すべてのポートを解放します。
既存のプロジェクトに新しいサービスを追加する
outport.yml に追加して、outport up を実行します。既存の割り当ては保持され、新しいサービスにのみポートが割り当てられます。
エージェントがプロジェクトの URL を確認する必要がある
outport status --json を実行すると、ポート、ヘルス状態、URL を含む構造化出力を取得できます。
サービスが想定と異なるポートに移動した
outport system status を実行して、すべての割り当てを確認します。別のプロジェクトが使用したいポートを保持している場合は、まずそのプロジェクトで outport down を実行し、次に自分のプロジェクトで outport up --force を実行します。
スマートフォンから開発サービスにアクセスする
outport qr を実行すると、各 HTTP サービスの LAN URL を含む QR コードが表示されます。同じ Wi-Fi に接続したスマートフォンでスキャンすると、アプリを開けます。outport share の実行中に outport qr --tunnel を使うと、代わりに公開トンネル URL の QR コードを取得できます。QR コードは outport.test のダッシュボードでも確認できます。
ネットワーク外の人とサービスを共有する
outport share を実行すると、すべての HTTP サービスを Cloudflare の公開 URL にトンネリングできます。cloudflared が必要です(brew install cloudflared)。停止するには Ctrl+C を押します。
正しく動作しない
outport doctor を実行して、DNS、デーモン、証明書、レジストリ、プロジェクト設定を確認します。各チェックでは合否と修正方法が表示されます。
.test ドメインが解決されない
outport doctor を実行して原因を調べます。よくある原因として、デーモンが実行されていない(outport system start)か、DNS リゾルバーが存在しない(outport system start)ことが挙げられます。
バグと機能リクエスト
バグの報告や新機能のリクエストは、https://github.com/steveclarke/outport/issues からお寄せください。