# 程式碼不上雲，網頁端 AI 能參與到哪一步？Local-first 與 GitHub-first 的接入邊界

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

<figure class="local-first-github-first-hero not-prose" lang="zh-tw">
<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.zh-tw.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.zh-tw.svg" type="image/svg+xml"><source media="(max-width: 640px)" srcset="/images/posts/local-first-vs-github-first-architecture/local-first-github-first.mobile.zh-tw.svg" type="image/svg+xml"><img src="/images/posts/local-first-vs-github-first-architecture/local-first-github-first.zh-tw.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 零外傳；網頁端隧道互通尚未在真實 Mac 驗證。</figcaption>
</figure>

如果商業專案的原始碼不能傳給雲端模型，我還能用網頁版 ChatGPT 做什麼？它能查看本機專案狀態，或請求一次受控的 SSH 檢查嗎？如果原始碼允許託管，又為什麼還要使用本機 MCP？

真正要選的不是某個工具，而是**工具能看到什麼、工作在哪裡執行，以及結果最後去了哪裡**。

簡單說：網頁端不會自動讀取你的 Mac。如果不把原始碼提供給模型，它只能依據你明確分享的摘要或狀態提出建議，不能獨立檢查或除錯自己沒看過的程式碼。

本機執行 Codex，不代表推論也在本機；Codex Cloud 不是連到你的 Mac；MCP 隧道負責轉送請求，本身不會限制工具權限。GitHub Private 控制的是儲存庫存取權，不會讓雲端儲存庫變成在地檔案。如果把原始碼交給雲端模型，相關上下文就進入模型的處理範圍。本文會先提供選擇方法，再用兩個公開範例說明邊界：[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／網頁端雲端任務 | 選定的 GitHub 儲存庫進入隔離的雲端工作區 | 任務可讀取工作區中的原始碼與檔案 | 專案允許進入 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 用戶端連到已設定的主機 | 目標別名與固定、過濾後的健康狀態 | 對非正式環境請求一項允許清單中的唯讀檢查 |
| 網頁模型 + 本機 coding-agent relay（需另建） | 本機轉接器委派給 Codex 或其他本機 coding agent | 取決於推論位置及轉接器回傳的內容 | 未來可行的架構，但必須另外設計工具、輸出、寫入、逾時與人工核准控制 |

先說明一個重要限制：下文的隧道設定依據 OpenAI 官方文件整理，但作者尚未在自己的真實 Mac 上完成 ChatGPT Web 到本機 MCP 的端到端測試。因此，這是設定參考，不是已驗證的一鍵教學。

### 先選路徑，再設定工具

- **原始碼絕不能傳給雲端模型：** 程式碼層級的工作應留在本機推論或其他可信的本機流程。唯讀中繼資料的 MCP 可以分享核准的狀態，但看不到原始碼的雲端模型無法獨立審查它。
- **只需要讓網頁版 ChatGPT 查看本機狀態：** 使用 Local-First MCP 這類固定欄位投影；它不需要原始碼讀取或 Shell 權限。
- **只需要由網頁請求固定的 SSH 健康檢查：** 使用 SSH Ops Bridge 這類命名操作，將主機身分、私鑰和目標允許清單留在本機。
- **原始碼允許託管，而且希望 AI 讀寫程式碼：** 使用 GitHub-first、Codex Cloud 或其他經核准的雲端 Agent，讓分支、PR、commit 和 CI 留下可複核紀錄。
- **希望網頁 AI 委派工作給本機 Codex：** 必須另外建置並審查本機 Agent relay。中繼資料 MCP 和 SSH 橋接器都不具備這項能力。
- **不同專案有不同資料分級：** 每個專案分別選擇路徑。允許博客儲存庫上雲，不代表商業原始碼也能使用相同的資料路徑。

其他廠商的網頁工具必須逐一核對：確認支援的遠端 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)。

## 先看三條資料流

### A. 網頁 AI 讀取本機專案狀態

~~~text
ChatGPT Web
    |
OpenAI Secure MCP Tunnel endpoint
    ^ 本機 tunnel-client 主動建立對外 HTTPS
    |
本機 vxi-local-first-mcp（stdio MCP）
    |
本機專案目錄：只統計檔案項目，不讀取原始碼內容

回傳：計數 + PASS / FAIL / UNKNOWN
不回傳：原始碼、路徑、diff、日誌、命令
~~~

### B. 網頁 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 狀態列舉
    |
回到網頁端
~~~

### C. GitHub-first 雲端開發

~~~text
已核准託管的 GitHub 儲存庫
    |
Codex Cloud / GitHub 雲端 Agent
    |
雲端工作區讀取原始碼、修改檔案並執行檢查
    |
分支 + PR + commit + CI
    |
人工審查與核准
~~~

這是不同的工作模式。前兩條限制網頁工具能看到或能請求什麼；第三條則允許 AI 在已核准的雲端工作區進行完整的原始碼層級開發。

## 不要混淆 Codex 本機、Codex Cloud 和 MCP

桌面應用中的 Codex Local environment 可設定本機專案或 worktree 的準備步驟與常用動作。整合終端機在本機執行命令，Git 工具可以檢查 diff、暫存、提交、推送與建立 PR。本機 Codex 用戶端也能啟動本機 stdio MCP server；這是本機 MCP host 啟動本機 server，不需要網頁隧道。

但「本機執行」只說明檔案和命令在哪裡運作。如果模型是託管模型，分析時使用的原始碼上下文仍可能被傳到雲端。要嚴格避免原始碼外傳，需要本機推論或經驗證的可信本機流程，並另外稽核裝置上的其他程序與網路路徑。

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 作為呼叫端：** 網頁端不會讀取本機 ~/.codex/config.toml，也不會自動繼承本機 Codex 的命令清單。它需要受支援的遠端 MCP 路徑。Secure MCP Tunnel 讓本機 tunnel client 對外連到 OpenAI 託管端點，再將請求轉送給本機 stdio 或 HTTP MCP server。

## 如何把網頁端接到本機 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**，選擇可用隧道、完成驗證並檢查權限提示。如果找不到隧道，先檢查 workspace/organization 關聯和權限，不要因此把本機 MCP 改成公開服務。
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，並把回應收斂成三個狀態列舉。

網頁端不會拿著你的私鑰直接登入伺服器；它請求的是一項固定操作。隧道負責傳輸，而工具清單、輸入驗證、本機設定、host key 綁定和遠端腳本共同決定權限邊界。

如果 MCP 後面換成能修改程式碼的本機 Agent，就必須重新審查其工具、輸入、輸出、檔案寫入、命令執行、逾時和人工核准。受限 SSH MCP 的安全結論不能自動套用到可寫入程式碼的 relay。

## 兩個公開儲存庫各自負責什麼

### VXI Local-First MCP：只分享本機專案中繼資料

[開啟儲存庫](https://github.com/vxime/vxi-local-first-mcp)

本機 stdio MCP 提供兩個唯讀工具：

- **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，狀態由操作者手動填寫。這只適合在不分享原始碼或原始日誌的前提下，提供粗略的本機檢查上下文。它不能診斷失敗，也不是綁定 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)、檔案傳輸、部署、重啟或任意日誌匯出。

兩個儲存庫彼此獨立：一個分享本機專案狀態，另一個只允許一項固定 SSH 檢查。兩者都沒有原始碼編輯工具，也不會互相呼叫。

## 測試通過究竟證明什麼？

以下數字來自不同儲存庫和測試層級，不是同一套測試被重複計數：

- **Local-First MCP：** main 有 6 個單元測試（[基線 CI](https://github.com/vxime/vxi-local-first-mcp/actions/runs/40167991313)）。PR #3 新增的是 Ubuntu/macOS 矩陣，不是測試案例；同樣六項測試在兩個作業系統上各自 6/6 通過（[PR #3 CI](https://github.com/vxime/vxi-local-first-mcp/actions/runs/40170254165)）。
- **SSH Ops Bridge：** main 有 7 個單元測試（[基線 CI](https://github.com/vxime/vxi-ssh-ops-bridge/actions/runs/40167994082)）。PR #3 保留七項單元測試，另加一次性 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：** 在七項基礎上新增一個測試案例，涵蓋缺少或型別錯誤的 host/user 值，並加入相應的字串驗證。這個仍未合併的 Draft 分支有 8/8 單元測試與 Demo 通過（[PR #4 CI](https://github.com/vxime/vxi-ssh-ops-bridge/actions/runs/40173291133)）。

回環測試曾揭露真實的測試設計問題：最初 Runner 使用者與 PAM 設定不符，導致驗證失敗。後來又發現伺服器端 ForceCommand 會覆蓋用戶端請求，可能在預期命令其實沒有執行時產生假陽性。修正後，測試環境不再設定 ForceCommand，讓真正的 SSH 用戶端執行產生的固定遠端腳本。測試同時檢查直接呼叫與 MCP 結果，並拒絕錯誤的 pinned host key 和任意 exec 請求。

這些結果只適用於各連結所指的精確原始碼版本。核對當下，三個原始碼 PR 仍是 Draft、尚未合併；PR #3 的跨平台矩陣與回環工作，以及 PR #4 的輸入驗證修正，都還不在 main 中。

## 結論：依資料邊界選擇，而不是看工具名稱

如果原始碼允許進入雲端，GitHub-first 能讓 AI 直接讀寫程式碼，並透過分支、PR、commit 和 CI 留下可複核的工程證據。如果原始碼必須留在本機，Local-First MCP 可以向網頁模型提供狀態，SSH Ops Bridge 則能提供一項固定的唯讀遠端操作；原始碼層級的開發仍需要本機人工、本機推論或其他經審查的本機流程。

真正需要守住的不是「使用本機工具」或「接上 MCP」這兩個標籤，而是每條路徑實際把什麼交給模型、模型能請求哪些操作，以及回應最後去了哪裡。

這兩個儲存庫目前仍是最小原型。作者尚未在自己的 Mac 上驗證即時隧道互通；本輪也沒有測試外部 SSH 主機、執行整台裝置的原始碼外傳稽核、驗證真正的本機模型推論，或對同一任務比較品質、延遲、Token 使用量與費用。
