# コードをクラウドに出さずに、Web AI はどこまで使える？Local-first と GitHub-first の接続境界

> Canonical: https://vxi.me/ja/posts/local-first-vs-github-first-architecture/
> Locale: ja-jp
> Published: 2026-10-25
> Updated: 2026-10-25
> Markdown: https://vxi.me/ja/posts/local-first-vs-github-first-architecture.md

<figure class="local-first-github-first-hero not-prose" lang="ja-jp">
<picture><source media="(prefers-reduced-motion: reduce) and (max-width: 640px)" srcset="/images/posts/local-first-vs-github-first-architecture/local-first-github-first.mobile.still.ja-jp.svg" type="image/svg+xml"><source media="(prefers-reduced-motion: reduce)" srcset="/images/posts/local-first-vs-github-first-architecture/local-first-github-first.still.ja-jp.svg" type="image/svg+xml"><source media="(max-width: 640px)" srcset="/images/posts/local-first-vs-github-first-architecture/local-first-github-first.mobile.ja-jp.svg" type="image/svg+xml"><img src="/images/posts/local-first-vs-github-first-architecture/local-first-github-first.ja-jp.svg" alt="Local-first はローカル MCP 経由で件数と手動記録の状態だけを返す。GitHub-first はクラウド作業領域でホスト済みのソースを読み書きし、ブランチ、PR、CI、人の承認を経る。" width="1200" height="700" loading="eager" fetchpriority="high" decoding="async" style="display:block;width:100%;height:auto"></picture>
<figcaption>構成図：MCP の出力制限は Mac 全体の外部送信ゼロを証明しません。Web からのトンネル接続は実機 Mac で未検証です。</figcaption>
</figure>

商用プロジェクトのソースコードをクラウドモデルに送れない場合、Web 版 ChatGPT で何ができるのでしょうか。ローカルのプロジェクト状態を確認したり、制限された SSH チェックを依頼したりできるのでしょうか。逆にソースをホストしてよいプロジェクトなら、なぜローカル MCP を使う必要があるのでしょうか。

選ぶべきなのは特定のツールではありません。**ツールに何が見え、どこで処理が実行され、結果がどこへ戻るか**です。

要点は、Web アプリが Mac を自動的に読み取るわけではないということです。モデルにソースを渡さなければ、明示的に共有した要約や状態をもとに助言はできますが、見ていないコードを独立してレビューしたりデバッグしたりはできません。

Codex をローカルで実行しても推論までローカルとは限りません。Codex Cloud は Mac への接続ではありません。MCP トンネルはリクエストを転送する仕組みであり、それ自体がツール権限を制限するわけではありません。GitHub Private が制御するのはリポジトリへのアクセスで、リポジトリをローカルにすることではありません。ソースをクラウドモデルに渡せば、そのコンテキストはモデルの処理境界に入ります。以下では選択ガイドと、境界を示す2つの公開例 [VXI Local-First MCP](https://github.com/vxime/vxi-local-first-mcp)、[VXI SSH Ops Bridge](https://github.com/vxime/vxi-ssh-ops-bridge) を紹介します。前者はローカルプロジェクトの状態のみを共有し、後者は固定された読み取り専用 SSH 操作だけを許可します。

## 接続経路を比較する：作業領域はどこにあり、モデルに何が見えるか

| 経路 | 作業領域と実行場所 | クラウドモデルが見られるもの | 向いている用途 |
|---|---|---|---|
| デスクトップアプリの Codex Local environment + ローカル MCP | Mac 上のプロジェクト／worktree、ターミナル、MCP プロセス | 実際にモデルへ送られたコンテキスト次第。ローカル実行はローカル推論を意味しない | 権限の範囲でファイルを読み書きし、コマンドを実行し、diff を確認する。モデルのデータ境界を確認済みであることが前提 |
| Codex Cloud／Web のクラウドタスク | 選択した GitHub リポジトリを隔離されたクラウド作業領域に配置 | タスクから参照できるソースと作業領域のファイル | ソースのクラウド利用が許可されている場合のコード変更、チェック実行、ブランチや成果物の納品 |
| GitHub のクラウド Coding Agent | リポジトリと一時的なクラウド Agent 環境 | リポジトリのファイル、タスクのコンテキスト、実行中にアクセス可能な内容 | ブランチ、PR、チェックを使った共同作業 |
| ChatGPT Web + Secure MCP Tunnel + Local-First MCP | MCP はローカルで動き、ローカル端末が外向きトンネルを開始 | MCP が明示的に返す件数と状態列挙のみ | ソース読み取りや Shell 権限を与えずに限定的なプロジェクト情報を共有する |
| ChatGPT Web + Secure MCP Tunnel + SSH Ops Bridge | ローカル MCP ブリッジと SSH クライアントが設定済みホストに接続 | ターゲットの別名と、固定・フィルタ済みのヘルス結果 | 非本番環境に対する、許可リスト内の読み取り専用チェック |
| Web モデル + ローカル coding-agent relay（別途構築） | ローカルアダプターが Codex などのローカル Agent に処理を委譲 | 推論場所とアダプターが返す内容次第 | 将来の設計候補。ただしツール、出力、書き込み、タイムアウト、人の承認を別途設計する必要がある |

先に重要な制限を明記します。以下のトンネル手順は OpenAI の公式ドキュメントに基づきますが、作者の実機 Mac で ChatGPT Web とローカル MCP のエンドツーエンド接続はまだ検証されていません。ワンクリックで動くことが確認済みの手順ではなく、構成の参考として読んでください。

### 設定の前に経路を選ぶ

- **ソースをクラウドモデルに絶対に渡せない：** コードレベルの作業はローカル推論、または信頼できるローカルワークフローに残します。メタデータ限定 MCP で承認済みの状態は共有できますが、ソースを見られないクラウドモデルが独立してコードレビューすることはできません。
- **Web ChatGPT にローカル状態だけを見せたい：** Local-First MCP のような固定フィールド投影を使います。ソース読み取り権限も Shell 権限も不要です。
- **Web から固定の SSH ヘルスチェックを依頼したい：** SSH Ops Bridge のような名前付き操作を使い、ホスト識別情報、秘密鍵、ターゲット許可リストはローカルに保持します。
- **ソースのホストが許可され、AI にコードを読み書きさせたい：** GitHub-first、Codex Cloud、または承認済みクラウド Agent を選び、ブランチ、PR、commit、CI を検証可能な記録として残します。
- **Web AI からローカル Codex にコード作業を委譲したい：** 別のローカル Agent relay を構築してレビューする必要があります。メタデータ MCP と SSH ブリッジにはその機能はありません。
- **プロジェクトごとにデータ分類が違う：** プロジェクト単位で経路を選びます。ブログのリポジトリをホストできるからといって、商用ソースも同じ経路で送ってよいとは限りません。

他社の Web ツールについては、対応するリモート MCP またはローカル Agent の経路、認証方式、ローカル Agent の機能、モデルに渡る入力とツールの返却値を個別に確認してください。MCP に対応しているだけで、OpenAI Secure MCP Tunnel をそのまま使えるとは限りません。

公式資料：[Codex Local environments](https://developers.openai.com/codex/environments/local-environment)、[Codex Cloud environments](https://developers.openai.com/codex/environments/cloud-environments)、[Codex MCP](https://developers.openai.com/codex/extend/mcp)、[OpenAI Secure MCP Tunnel](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels)、[GitHub Copilot cloud agent](https://docs.github.com/en/copilot/concepts/agents/cloud-agent)。

## 3つのデータフロー

### A. Web AI がローカルプロジェクトの状態を読む

~~~text
ChatGPT Web
    |
OpenAI Secure MCP Tunnel endpoint
    ^ ローカルの tunnel-client が外向き HTTPS を開始
    |
ローカル vxi-local-first-mcp（stdio MCP）
    |
ローカルプロジェクトのディレクトリ：項目数のみを数え、ソース内容は読まない

返すもの：件数 + PASS / FAIL / UNKNOWN
返さないもの：ソース、パス、diff、ログ、コマンド
~~~

### B. Web AI が固定 SSH チェックを依頼する

~~~text
ChatGPT Web
    |
OpenAI Secure MCP Tunnel endpoint
    ^ ローカルの tunnel-client が外向き HTTPS を開始
    |
ローカル vxi-ssh-ops-bridge（stdio MCP）
    |
ローカル SSH クライアント + 秘密鍵 + pinned known_hosts
    |
非本番 SSH ターゲット：固定の読み取り専用スクリプト
    |
フィルタ済み health / service / storage の状態列挙
    |
Web アプリに返す
~~~

### C. GitHub-first のクラウド開発

~~~text
ホストが許可された GitHub リポジトリ
    |
Codex Cloud / GitHub cloud agent
    |
クラウド作業領域がソースを読み、編集し、チェックを実行
    |
branch + PR + commit + CI
    |
人によるレビューと承認
~~~

これは異なる運用モデルです。最初の2つは Web ツールが見られる情報や要求できる操作を制限します。3つ目は、承認済みのクラウド作業領域で AI がソースレベルの開発を行う経路です。

## Codex Local、Codex Cloud、MCP を混同しない

デスクトップアプリの Codex Local environment は、ローカルプロジェクトや worktree の準備手順、よく使う操作を設定します。統合ターミナルはローカルでコマンドを実行し、Git ツールで diff の確認、stage、commit、push、PR 作成ができます。ローカル Codex クライアントはローカル stdio MCP server も起動できます。これはローカル MCP host がローカル server を起動する構成であり、Web トンネルは必要ありません。

ただし「ローカル実行」は、ファイルやコマンドがどこで動くかを示すだけです。モデルがホスト型なら、分析に使うソースのコンテキストはクラウドに送られる可能性があります。ソースの外部送信を厳密に防ぐには、ローカル推論または検証済みの信頼できるローカル処理に加え、端末上の他のプロセスとネットワーク経路も別途監査する必要があります。

Codex Cloud は選択した GitHub リポジトリを隔離されたクラウド作業領域に置き、依存関係を準備してそこでタスクを実行します。GitHub のクラウド Agent も、クラウド環境でソースを読み、ブランチを変更し、チェックを実行し、PR を作成できます。これはクラウド境界を越えてよいプロジェクト向けであり、「ソースを Mac に残す」代替策ではありません。

### MCP host と MCP server の違い

- **デスクトップ ChatGPT、Codex CLI、IDE 拡張機能を MCP host として使う場合：** クライアントが対応する方法でローカル stdio server を起動できます。公式 CLI の形式は次のとおりです。

~~~bash
codex mcp add vxi-local-status \
  --env "VXI_WORKSPACE=/absolute/path/to/project" \
  -- /absolute/path/to/node /absolute/path/to/vxi-local-first-mcp/bin/vxi-local.mjs mcp

codex mcp list
~~~

SSH Ops Bridge では同じ形式を使い、VXI_OPS_CONFIG をローカルの ops.config.json のパスに設定し、server command を vxi-ssh-ops-bridge/bin/vxi-ops.mjs に向けます。ホスト名、アカウント、秘密鍵のパス、ops.config.json はローカルに保管し、実行時の秘密情報をチャットに貼ったり Git にコミットしたりしないでください。デスクトップアプリ、Codex CLI、対応する IDE 拡張機能は Codex host の MCP 設定を利用できますが、権限は各クライアントのワークスペース設定に依存します。

- **ChatGPT Web を呼び出し側にする場合：** Web アプリはローカルの ~/.codex/config.toml を読み取らず、ローカル Codex のコマンド一覧も自動継承しません。対応するリモート MCP 経路が必要です。Secure MCP Tunnel は、ローカルの tunnel client から OpenAI のホストされたエンドポイントへ外向きに接続し、リクエストをローカル stdio または HTTP MCP server に転送します。

## Web アプリからローカル MCP に接続し、SSH を依頼する

OpenAI の [Secure MCP Tunnel ドキュメント](https://developers.openai.com/api/docs/guides/secure-mcp-tunnels)では、プライベート MCP サービスに到達できるネットワーク内で tunnel-client を実行します。クライアントが外向き HTTPS を開始し、ホスト側エンドポイントからリクエストを受け取り、ローカル stdio または HTTP MCP server に転送し、同じトンネル経由でレスポンスを返します。Mac に公開インバウンドポートを開く必要はありません。

以下のパスと tunnel ID はプレースホルダーです。実行時の認証情報はローカル環境変数だけに置いてください。

1. OpenAI Platform でトンネルを作成または選択します。対象の ChatGPT workspace と Platform organization の関連付け、および必要な Tunnel 権限を確認します。
2. Platform のトンネル設定から最新の tunnel-client を取得します。現在の help/quickstart を確認し、MCP server ごとに別の profile を設定します。
3. トンネル設定の前に各 MCP server をオフラインでテストします。Local-First MCP の場合：

~~~bash
cd /path/to/vxi-local-first-mcp
node --version  # >= 22
npm test
npm run demo
~~~

テストに合格したら Local-First profile を設定します。

~~~bash
export CONTROL_PLANE_API_KEY="<runtime-key kept in the local terminal>"

tunnel-client init \
  --sample sample_mcp_stdio_local \
  --profile vxi-local-status \
  --tunnel-id "<your-tunnel-id>" \
  --mcp-command "/usr/bin/env VXI_WORKSPACE=/absolute/path/to/project /absolute/path/to/node /absolute/path/to/vxi-local-first-mcp/bin/vxi-local.mjs mcp"

tunnel-client doctor --profile vxi-local-status --explain
tunnel-client run --profile vxi-local-status
~~~

絶対パスを使うと、バックグラウンドプロセスの作業ディレクトリや PATH が対話型ターミナルと異なる問題を避けられます。

SSH Ops Bridge では、まず npm test と npm run demo を実行します。ops.config.example.json からローカルの ops.config.json を作り、mode を disabled から read_only に変更します。独立した手段で確認した非本番ターゲット、低権限アカウント、ローカル秘密鍵のパス、固定の known_hosts だけを設定します。README に従い、テストホストに読み取り専用スクリプトを /usr/local/bin/vxi-health-check として配置してから、別の profile を設定します。

~~~bash
tunnel-client init \
  --sample sample_mcp_stdio_local \
  --profile vxi-ssh-readonly \
  --tunnel-id "<your-ssh-tunnel-id>" \
  --mcp-command "/usr/bin/env VXI_OPS_CONFIG=/absolute/path/to/ops.config.json /absolute/path/to/node /absolute/path/to/vxi-ssh-ops-bridge/bin/vxi-ops.mjs mcp"

tunnel-client doctor --profile vxi-ssh-readonly --explain
tunnel-client run --profile vxi-ssh-readonly
~~~

Platform の画面やクライアントのバージョンは変わるため、実際のオプションはインストール済みクライアントの help を確認してください。

4. tunnel-client run を実行したままにします。ChatGPT の対応するカスタム MCP 入口で **Add custom MCP server → Tunnel** を選択し、利用可能なトンネルを選び、認証して権限の確認画面を読みます。トンネルが表示されない場合は、ローカル MCP を公開するのではなく、workspace/organization の関連付けと権限を確認します。
5. 最初に読み取り専用の vxi_project_status または vxi_ops_policy を呼び出し、ツールが見つかることを確認します。必要な場合だけ vxi_ssh_health を呼び出します。本番ホストでは試さず、SSH host key は別の経路で検証してください。

### SSH ブリッジがローカルで行うこと

ローカル管理者はホスト、ユーザー名、ポート、秘密鍵のパス、独立して検証した known_hosts を ops.config.json に保存します。MCP が受け付けるのは lab のようなローカル許可リストの別名だけで、モデルが生成したコマンド文字列ではありません。ブリッジは個人の SSH 設定を無視し、agent forwarding と対話型パスワード入力を無効化し、固定の /usr/local/bin/vxi-health-check を呼び出して結果を3つの状態列挙に絞ります。

Web アプリが秘密鍵を受け取り、直接サーバーにログインするわけではありません。依頼するのは固定された操作です。トンネルが転送を担い、ツール一覧、入力検証、ローカル設定、host key の固定、リモートスクリプトが権限境界を定義します。

MCP の後ろをコード編集可能なローカル Agent に置き換えるなら、ツール、入力、出力、ファイル書き込み、コマンド実行、タイムアウト、人の承認を別途レビューする必要があります。制限された SSH MCP の安全性を、書き込み可能な coding-agent relay にそのまま当てはめることはできません。

## 2つの公開リポジトリの役割

### VXI Local-First MCP：ローカルプロジェクトのメタデータだけを共有

[リポジトリを開く](https://github.com/vxime/vxi-local-first-mcp)

ローカル stdio MCP は2つの読み取り専用ツールを公開します。

- **vxi_project_status：** ファイル分類の件数、スキップしたシンボリックリンク数、手動記録された lint/test/build の状態（PASS / FAIL / UNKNOWN、初期値は UNKNOWN）。MCP はテストを実行しません。スキャンではドットディレクトリと .git、node_modules、dist などの一般的なビルド／キャッシュディレクトリを除外します。処理するディレクトリエントリは最大20,000件で、上限を超えると部分的な件数を返さずエラーになります。すべてのプロジェクトファイルを完全に列挙するものではありません。
- **vxi_security_contract：** 返却が許可されるフィールドと禁止されるフィールドを説明します。

スキャナーはソースファイルの内容を読まず、ディレクトリエントリを分類します。固定フィールドの返却には、ソース、パス、diff、ログ、環境変数、Shell インターフェースは含まれません。これはクラウドモデルに限定された状態を見せる仕組みであり、ソースを暗号化してアップロードするものではありません。

record はローカル CLI 操作であり、MCP ツールではなく、テストも実行しません。例：

~~~bash
node bin/vxi-local.mjs record --workspace /path/to/project --kind test --status PASS
~~~

kind は lint、test、build のいずれかで、状態は操作者が入力します。ソースや生ログをアップロードせず、Web モデルに大まかなローカルチェック状況を伝える用途に限られます。失敗原因を診断することも、commit に紐づいた署名済みテスト証明を提供することもありません。デバッグ時は完全なログをローカルで確認するか、必要最小限のエラー概要を人が選んで伏せ字処理してから共有します。

### VXI SSH Ops Bridge：固定された読み取り専用 SSH 操作のみ

[リポジトリを開く](https://github.com/vxime/vxi-ssh-ops-bridge)

ブリッジはデフォルトで無効で、vxi_ops_policy と vxi_ssh_health のみを公開します。後者はローカル許可リストの別名を受け取り、固定リモートスクリプトを実行し、結果を health、service、storage の状態列挙に絞ります。サンプルスクリプトの health: PASS が示すのは固定スクリプトが動いたことだけです。アプリ固有のチェックを導入・検証するまでは service と storage は UNKNOWN のままです。汎用 exec(command)、ファイル転送、デプロイ、再起動、任意ログのエクスポートは提供しません。

2つのリポジトリは独立しています。一方はローカルプロジェクトの状態を共有し、もう一方は固定の SSH チェックだけを許可します。どちらにもソース編集ツールはなく、互いを呼び出しません。

## テストが緑であることは何を証明するか

次の件数は別々のリポジトリとテスト層を指し、同じテストスイートを繰り返し数えたものではありません。

- **Local-First MCP：** main には単体テストが6件あります（[baseline CI](https://github.com/vxime/vxi-local-first-mcp/actions/runs/40167991313)）。PR #3 は新しいテストケースではなく Ubuntu/macOS のマトリクスを追加し、同じ6件が両 OS でそれぞれ6/6成功しました（[PR #3 CI](https://github.com/vxime/vxi-local-first-mcp/actions/runs/40170254165)）。
- **SSH Ops Bridge：** main には単体テストが7件あります（[baseline CI](https://github.com/vxime/vxi-ssh-ops-bridge/actions/runs/40167994082)）。PR #3 は7件を維持し、一度限りの GitHub-hosted Ubuntu Runner 上に OpenSSH localhost 統合ジョブを追加しました。単体テストとループバック SSH チェックは成功しています（[PR #3 CI](https://github.com/vxime/vxi-ssh-ops-bridge/actions/runs/40173329836)）。
- **SSH Ops Bridge PR #4：** 7件に加え、host/user が欠けている場合や文字列以外の場合を扱うテストケースを1件追加し、対応する文字列検証も追加しました。まだマージされていない Draft ブランチで単体テスト8/8とデモが成功しています（[PR #4 CI](https://github.com/vxime/vxi-ssh-ops-bridge/actions/runs/40173291133)）。

ループバックのテストフィクスチャでは実際の設計ミスも見つかりました。初期には Runner ユーザーと PAM 設定が一致せず、認証が失敗しました。その後、サーバー側の ForceCommand がクライアントの要求を上書きし、意図したコマンドが実行されていなくてもテストが成功したように見える偽陽性の可能性が判明しました。修正後、フィクスチャでは ForceCommand を設定せず、実際の SSH クライアントに生成済みの固定リモートスクリプトを実行させます。テストは直接呼び出しと MCP の結果を検証し、誤った pinned host key と任意の exec 要求を拒否します。

これらの結果は、リンク先の正確なソースバージョンに限られます。確認時点で3つのソース PR は Draft のまま未マージです。PR #3 のクロスプラットフォームマトリクスとループバックジョブ、PR #4 の入力検証修正は、まだ main に含まれていません。

## 結論：ツール名ではなくデータ境界で選ぶ

ソースをクラウドに置いてよいなら、GitHub-first では AI がコードを読み書きでき、ブランチ、PR、commit、CI が検証可能な開発記録になります。ソースをローカルに残す必要があるなら、Local-First MCP で Web モデルに状態を共有し、SSH Ops Bridge で固定の読み取り専用リモート操作を依頼できます。ソースレベルの開発には、ローカルの人間、ローカル推論、またはレビュー済みの別のローカルワークフローが必要です。

守るべき境界は「ローカルツールを使った」「MCP を接続した」というラベルではありません。各経路が実際に何をモデルへ渡し、モデルが何を要求でき、レスポンスがどこへ行くかです。

どちらのリポジトリもまだ最小プロトタイプです。作者の Mac で実際のトンネル接続は未検証であり、外部 SSH ホスト、端末全体のソース送信監査、本当にローカルでのモデル推論、同一タスクでの品質・遅延・トークン・費用比較も行っていません。
