
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`)時。
當您需要與 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 可透過套件/應用程式識別碼(AppProcessName、bundleId、bundleName 或 App)從 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.getDocument、Runtime.evaluate)。-c, --client <clientId>:(可選)用戶端 ID。若省略,則使用第一個可用的用戶端。--client-name <name>:(可選)從list-clients解析的套件/應用程式名稱。-s, --session <sessionId>:(可選)工作階段 ID。若省略,則使用最新的工作階段(具有最大工作階段 ID)。--thread <thread>:(可選)目標 VM 執行緒,background或main。預設為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 執行緒:background或main。若省略,預設會收集兩個執行緒。
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 執行緒,background或main。預設為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>:(可選)start和end的用戶端 ID。-o, --output <path>:(可選)end的輸出檔案或目錄路徑。預設為~/.lynx-devtool/files/lynxrecorder/recording-<clientId>-<timestamp>.json。
工作流程:
- 執行
recorder start。如果它啟用了enable_debug_mode,請重新啟動應用程式並再次執行recorder start。 - 使用者開啟並與 Lynx 頁面互動。
- 執行
recorder end --output <file.json>以停止並儲存。 - 將絕對檔案路徑回報給使用者。
重要: 若要產生可重播的檔案,請在 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.body和preactDevtoolsCtx.Node修正(針對lynx-family/preact-devtools的 PR #2 + PR #5)。若無這些修正,refresh通道將回傳零個operation_v2框架,且 CLI 會列印「stale preact-devtools」診斷訊息。
當樹狀結構回傳為空時,CLI 會以代碼 1 結束,並在 stderr 上寫入三種針對性診斷訊息之一:
saw 0 frames:PreactDevtools通道上沒有任何回應。應用程式很可能缺少@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 呼叫所需標籤的建議方式。





