lynx-devtool

lynx-devtool

當您需要與 Lynx DevTool 互動或偵錯 Lynx 應用程式、頁面或裝置時使用,特別是當任務提及用戶端或工作階段、CDP 或 App 指令、DOM/CSS 檢查、執行時期或主控台日誌、螢幕截圖、堆積快照、Page.reload 或 App.openPage、全域開關,或在 Android、iOS 或 Desktop 上檢查 ReactLynx 元件樹(`reactlynx tree`)、搜尋元件(`reactlynx find`)、檢查 props/state/hooks(`reactlynx component`)或修改 props/state/context(`reactlynx update-prop` / `update-state` / `update-context`)時。

25星標
8分支
更新於 2026/7/27
SKILL.md
唯讀
名稱
lynx-devtool
描述

當您需要與 Lynx DevTool 互動或偵錯 Lynx 應用程式、頁面或裝置時使用,特別是當任務提及用戶端或工作階段、CDP 或 App 指令、DOM/CSS 檢查、執行時期或主控台日誌、螢幕截圖、堆積快照、Page.reload 或 App.openPage、全域開關,或在 Android、iOS 或 Desktop 上檢查 ReactLynx 元件樹(`reactlynx tree`)、搜尋元件(`reactlynx find`)、檢查 props/state/hooks(`reactlynx component`)或修改 props/state/context(`reactlynx update-prop` / `update-state` / `update-context`)時。

DevTool 技能

此技能可讓您透過 Lynx DevTool CLI 與連線裝置(Android、iOS、Desktop)上執行的 Lynx 應用程式互動。

使用方式

CLI 位於此技能目錄下的 <path_to_the_skill>/scripts/index.mjs,您可以使用 node 執行。

程式化 API 位於 <path_to_the_skill>/scripts/connector.mjs。此進入點重新匯出 @lynx-js/devtool-connector@lynx-js/devtool-connector/transport@lynx-js/devtool-connector/streams 的所有內容,並提供與 CLI 預設值相符的 createDefaultTransports()createDefaultConnector() 輔助函式。

在技能目錄中,使用:

node <path_to_the_skill>/scripts/index.mjs <command>

注意: 所有指令輸出都是多行 JSON。您可以使用 jq 或 Node.js 處理資料。

作為函式庫使用

如果您想直接從 JavaScript 驅動 Lynx DevTool 而非透過 CLI 執行 shell 指令,請從 scripts/connector.mjs 匯入。

import {
  Connector,
  createDefaultConnector,
} from "<path_to_the_skill>/scripts/connector.mjs";

const connector = createDefaultConnector();
const clients = await connector.listClients();

console.log(clients);

如需更完整的程式化工作流程,請參閱函式庫使用參考程式化偵錯範例

如果您需要自訂傳輸層,也可以手動建構 connector:

import {
  AndroidTransport,
  Connector,
  DesktopTransport,
  iOSTransport,
} from "<path_to_the_skill>/scripts/connector.mjs";

const connector = new Connector([
  new AndroidTransport({ host: "127.0.0.1", port: 5037 }),
  new DesktopTransport(),
  new iOSTransport(),
]);

全域選項

  • -h, --help:顯示指令說明。

注意: 每個子指令都支援 --help 旗標(例如 node <path_to_the_skill>/scripts/index.mjs cdp --help)。使用此旗標可檢視所有可用引數及其說明的完整清單。

用戶端指定

接受 -c, --client <clientId> 的指令也接受 --client-name <name>
使用 --client-name 可透過套件/應用程式識別碼(AppProcessNamebundleIdbundleNameApp)從 list-clients 解析用戶端,例如:

node <path_to_the_skill>/scripts/index.mjs cdp --client-name com.example.app -m DOM.getDocument
node <path_to_the_skill>/scripts/index.mjs list-sessions --client-name com.lynx.uiapp

如果多個用戶端符合名稱,請使用 list-clients 並以 --client 傳入確切的用戶端 ID。

指令

1. 列出用戶端

列出所有可用的 Lynx 用戶端(已啟用 DevTool 的應用程式)。

node <path_to_the_skill>/scripts/index.mjs list-clients
2. 列出工作階段

列出所有活躍的偵錯工作階段。一個工作階段對應到一個特定的 Lynx 檢視或上下文。

node <path_to_the_skill>/scripts/index.mjs list-sessions
# 可選:依用戶端 ID 篩選
node <path_to_the_skill>/scripts/index.mjs list-sessions --client <clientId>
3. 傳送 CDP 指令

傳送 Chrome DevTools Protocol (CDP) 指令到特定工作階段。

請注意 Lynx 僅支援部分標準 CDP 指令。
LynxView 注意:當目標工作階段是 LynxView 時,您必須在傳送 CDP 指令前閱讀支援的 CDP 方法
WebView 注意:當目標工作階段是 WebView(例如 type: "web" 或 HTTP/HTTPS URL)時,請使用標準 Chrome DevTools Protocol 文件來查詢 CDP 方法名稱、參數和啟用前提。本地的 references/cdp 頁面著重於 LynxView 支援和 Lynx 專屬擴充,在 WebView 目標上可能會回傳 method not found

node <path_to_the_skill>/scripts/index.mjs cdp -m <method> [options] [params]
  • -m, --method <method>:CDP 方法名稱(例如 DOM.getDocumentRuntime.evaluate)。
  • -c, --client <clientId>:(可選)用戶端 ID。若省略,則使用第一個可用的用戶端。
  • --client-name <name>:(可選)從 list-clients 解析的套件/應用程式名稱。
  • -s, --session <sessionId>:(可選)工作階段 ID。若省略,則使用最新的工作階段(具有最大工作階段 ID)。
  • --thread <thread>:(可選)目標 VM 執行緒,backgroundmain。預設為 background
  • [params]:(可選)指令參數的 JSON 字串。

使用 --thread main 時,僅支援 Debugger.*Runtime.*HeapProfiler.*Profiler.* 方法。

範例:

# 取得文件根節點
node <path_to_the_skill>/scripts/index.mjs cdp -m DOM.getDocument

# 執行 JavaScript
node <path_to_the_skill>/scripts/index.mjs cdp -m Runtime.evaluate '{"expression": "2 + 2"}'

# 在主執行緒 VM 上執行 JavaScript
node <path_to_the_skill>/scripts/index.mjs cdp --thread main -m Runtime.evaluate '{"expression": "2 + 2"}'
4. 傳送 App 指令

傳送 App 層級的指令。

node <path_to_the_skill>/scripts/index.mjs app -m <method> [options] [params]
  • -m, --method <method>:App 方法名稱(例如 App.openPage)。
  • -c, --client <clientId>:(可選)用戶端 ID。
  • --client-name <name>:(可選)從 list-clients 解析的套件/應用程式名稱。
  • [params]:(可選)參數的 JSON 字串。

必須在傳送 App 指令前閱讀支援的 App 方法

5. 開啟 URL

在 Lynx 應用程式中開啟特定 URL。

node <path_to_the_skill>/scripts/index.mjs open <url> [options]
  • <url>:要開啟的 URL。
  • -c, --client <clientId>:(可選)用戶端 ID。

範例:

node <path_to_the_skill>/scripts/index.mjs open "lynx://example/page"
6. 檢查

輸出用戶端/工作階段的檢查器 URL。

node <path_to_the_skill>/scripts/index.mjs inspect [options]
  • -c, --client <clientId>:(可選)用戶端 ID。
  • -s, --session <sessionId>:(可選)工作階段 ID。
  • --port <port>:(可選)Daemon 連接埠。預設為 21783
7. 取得主控台

從裝置擷取主控台日誌。

node <path_to_the_skill>/scripts/index.mjs get-console [options]
  • -c, --client <clientId>:(可選)用戶端 ID。
  • -s, --session <sessionId>:(可選)工作階段 ID。
  • --offset <number>:跳過 N 則訊息。
  • --limit <number>:限制訊息數量。
  • --include-stack-traces:包含非錯誤訊息的堆疊追蹤。
  • --level <levels>:篩選日誌層級(例如 error,warning)。
  • --thread <thread...>:目標 VM 執行緒:backgroundmain。若省略,預設會收集兩個執行緒。
8. 取得原始碼

列出所有已解析的腳本。這有助於尋找腳本 ID 以用於其他指令(例如 Debugger.getScriptSource)。此指令會自動擷取所有目前已載入的腳本。

node <path_to_the_skill>/scripts/index.mjs get-sources [options]
  • -c, --client <clientId>:(可選)用戶端 ID。
  • -s, --session <sessionId>:(可選)工作階段 ID。
9. 擷取螢幕截圖

擷取目前頁面的螢幕截圖。

node <path_to_the_skill>/scripts/index.mjs take-screenshot [options]
  • -c, --client <clientId>:(可選)用戶端 ID。
  • -s, --session <sessionId>:(可選)工作階段 ID。
  • --fullscreen:(可選)以 fullscreen 模式擷取螢幕截圖。若未提供,預設為 lynxview 模式。
  • -o, --output <path>:(可選)輸出檔案路徑。
10. 擷取堆積快照

從目前的 Lynx 工作階段擷取 QuickJS 堆積快照,並儲存為 .heapsnapshot 檔案。

node <path_to_the_skill>/scripts/index.mjs take-heap-snapshot [options]
  • -c, --client <clientId>:(可選)用戶端 ID。
  • -s, --session <sessionId>:(可選)工作階段 ID。
  • --thread <thread>:(可選)目標 VM 執行緒,backgroundmain。預設為 background
  • -o, --output <path>:(可選)輸出檔案路徑。預設為作業系統暫存目錄。
11. 全域開關

管理 DevTool 全域開關。

# 列出所有支援的金鑰及其目前值
node <path_to_the_skill>/scripts/index.mjs global-switch list [options]

# 取得單一金鑰
node <path_to_the_skill>/scripts/index.mjs global-switch get --key <globalKey> [options]

# 設定單一金鑰
node <path_to_the_skill>/scripts/index.mjs global-switch set --key <globalKey> --status <on|off> [options]
  • -c, --client <clientId>:(可選)用戶端 ID。

global-switch list 選項:

  • --fail-fast:在第一次金鑰讀取失敗時中止。

global-switch get 選項:

  • --key <globalKey>:全域開關金鑰。(必填)

global-switch set 選項:

  • --key <globalKey>:全域開關金鑰。(必填)
  • --status <on|off>:目標開關狀態。(必填)

如需完整金鑰清單和範例,請參閱全域開關參考

12. 查詢全域記憶體使用量

透過全域 Memory.* CDP 領域查詢 Lynx 全域記憶體使用量。使用通用的 cdp 指令,並以工作階段 ID -1 將請求傳送至全域 DevTool 處理器。

# 取得跨活躍實例的全域 Lynx 記憶體使用量
node <path_to_the_skill>/scripts/index.mjs cdp -s -1 -m Memory.getAllMemoryUsage
node <path_to_the_skill>/scripts/index.mjs cdp -s -1 -m Memory.getAllMemoryUsage '{"timeoutMs":50000}'
  • -c, --client <clientId>:(可選)用戶端 ID。
  • -s, --session <sessionId>:CDP 工作階段 ID。除非有平台特定的原因需要覆寫,否則請使用 -1 作為全域 DevTool 處理器。
  • params.timeoutMs(可選):非負數的超時時間(毫秒)。最大值為 300000

當 DevTool MCP 伺服器可用時,建議優先使用 Memory_getAllMemoryUsage MCP 工具來取得相同的原始負載,而非透過 CLI 執行 shell 指令。

13. 錄製

透過 TestBench(基於 CDP)錄製 Lynx 頁面互動。擷取所有動作(範本載入、觸控事件、JS 模組呼叫、資料更新)並產生 JSON 重播檔案。

# 開始錄製(在開啟目標頁面之前)
node <path_to_the_skill>/scripts/index.mjs recorder start [options]

# 停止錄製並儲存重播檔案
node <path_to_the_skill>/scripts/index.mjs recorder end [options]
  • -c, --client <clientId>:(可選)startend 的用戶端 ID。
  • -o, --output <path>:(可選)end 的輸出檔案或目錄路徑。預設為 ~/.lynx-devtool/files/lynxrecorder/recording-<clientId>-<timestamp>.json

工作流程:

  1. 執行 recorder start。如果它啟用了 enable_debug_mode,請重新啟動應用程式並再次執行 recorder start
  2. 使用者開啟並與 Lynx 頁面互動。
  3. 執行 recorder end --output <file.json> 以停止並儲存。
  4. 將絕對檔案路徑回報給使用者。

重要: 若要產生可重播的檔案,請在 recorder start 之後開啟或重新載入目標頁面,以便錄製內容包含 loadTemplate

更多詳細資訊請參閱錄製參考

14. ReactLynx 元件樹

列印執行中 ReactLynx 頁面的元件樹,從 @lynx-js/preact-devtools 解碼。CLI 會開啟 Lynx.onVMEvent 串流,傳送 Preact DevTools init+refresh 握手,並將產生的 operation_v2 負載呈現為 ASCII 樹狀圖。

node <path_to_the_skill>/scripts/index.mjs reactlynx tree [options]
  • -c, --client <clientId>:(可選)用戶端 ID。
  • -s, --session <sessionId>:(可選)工作階段 ID。
  • --depth <n>:(可選)要列印的最大樹狀深度。預設:無限制。
  • --show-shells:包含 ReactLynx 插入的合成 Fragment / Root / Anonymous 包裝器。預設為隱藏。
  • --json:輸出 { labels, roots, nodes } 而非 ASCII;當腳本會消費樹狀結構時使用此選項。

輸出使用 @cN [type] Name 參考(來自 agent-react-devtools 的慣例)。標籤是對可見根節點進行前序 DFS 並在每次呼叫時重設,因此在單一指令內是穩定的,但不會跨執行:

@c1 [fn] App
├─ @c2 [fn] Header
│  └─ @c3 [fn] Logo
└─ @c4 [fn] Body

需求:

  • 頁面必須是執行 @lynx-js/preact-devtools開發建置(正式版建置會移除 setupReactLynx())。成功初始化會在裝置主控台記錄 [PREACT DEVTOOLS] Devtools initialized successfully
  • @lynx-js/preact-devtools 必須包含 document.bodypreactDevtoolsCtx.Node 修正(針對 lynx-family/preact-devtools 的 PR #2 + PR #5)。若無這些修正,refresh 通道將回傳零個 operation_v2 框架,且 CLI 會列印「stale preact-devtools」診斷訊息。

當樹狀結構回傳為空時,CLI 會以代碼 1 結束,並在 stderr 上寫入三種針對性診斷訊息之一:

  • saw 0 framesPreactDevtools 通道上沒有任何回應。應用程式很可能缺少 @lynx-js/preact-devtools、是正式版建置、尚未完成 setupReactLynx(),或者您選錯了 --session
  • saw N frames but no operation_v2:掛鉤已載入,但其 refresh 處理器有錯誤。請將 @lynx-js/preact-devtools 升級至包含 PR #2 和 #5 的建置。
  • tree is empty:每個節點在提交之間都已卸載——很少見,請使用 DEBUG(如下)重新執行以查看原始信封。

如需深入偵錯,請設定 DEBUG=devtool-mcp-server:reactlynx 以在 stderr 上記錄每個 PreactDevtools 框架(類型 + 負載大小),同時保持 stdout(樹狀結構 / JSON)乾淨:

DEBUG='devtool-mcp-server:reactlynx' node <path_to_the_skill>/scripts/index.mjs reactlynx tree
15. ReactLynx 元件檢查

檢查單一 ReactLynx 元件(props / state / hooks / context / signals),方法是傳送 Preact DevTools inspect 信封並讀回 inspect-result

node <path_to_the_skill>/scripts/index.mjs reactlynx component <ref> [options]
  • <ref>:可以是 reactlynx tree / reactlynx find 產生的標籤 @cN,或數值 vnode id。
    • 使用 @cN 時,CLI 會先執行一次額外的 init+refresh+tree 往返以解析標籤。如果(且僅當)標籤是在顯示 shell 的情況下產生,請傳入 --show-shells
    • 使用數值 id(例如 3856353762)時,會跳過快照——總共一次往返。
  • -c, --client <clientId>-s, --session <sessionId>:(可選)標準指定旗標。
  • --show-shells:解析 @cN 時,以與 reactlynx tree --show-shells 相同的方式計算合成 Fragment / Root / Anonymous 包裝器。
  • --json:以 JSON 格式列印原始 InspectData 負載。預設輸出為精簡的 ASCII 摘要。

範例輸出:

@c5 (id=3856353783) [fn] TUXIntroViewListCell key=1. HMR
  source: src/TUXIntroViewListCell.tsx:42:3
  props:
    {
      "title": "1. HMR",
      "icon": { "type": "vnode", "name": "TUXIcon" }
    }
16. ReactLynx 元件搜尋

尋找名稱符合子字串或正規表示式的所有元件。輸出順序與 reactlynx tree 完全相同(前序 DFS),因此 @cN 標籤可與其他子指令往返使用。

node <path_to_the_skill>/scripts/index.mjs reactlynx find <pattern> [options]
  • <pattern>:子字串(預設,不區分大小寫)或搭配 --regex 的 JavaScript 正規表示式。
  • -c, --client <clientId>-s, --session <sessionId>:(可選)標準指定旗標。
  • --regex:將 <pattern> 視為 JavaScript 正規表示式(例如 --regex '^Toast(List)?$')。
  • --show-shells:包含合成 Fragment / Root / Anonymous 包裝器。
  • --limit <n>:要列印的最大相符項目數。預設為 50
  • --json:輸出 [{ label, id, name, type, key, ancestors: [{label, name}] }, ...] 以供腳本後處理。

範例輸出:

@c8 [fn] TUXCenterToastActivator
  in @c1 TUXApp > @c2 Provider > @c3 App
@c10 [fn] TUXTopToastActivator
  in @c1 TUXApp > @c2 Provider > @c3 App

當樹狀結構太大而無法視覺掃描時,reactlynx find 是發現後續 reactlynx component @cN 呼叫所需標籤的建議方式。