前言¶
在手機上跑 DSH(DeepSeek Harness)時,Agent 想裝個 App、看一段日誌、截一張屏,通常是兩條路:把它們接到一臺插着數據線的電腦上走 adb,或者退而求其次用無障礙服務一點點點屏幕。前者需要額外的機器和局域網,後者只能模擬點擊,拿不到真正的 shell。
jminn0/dsh-go-plugin-adb 走的是第三條路:插件的 adb 客戶端和 adbd 都在同一臺手機裏,Agent 連的是迴環地址 127.0.0.1:5555。不需要 root,不需要電腦,配對一次之後關掉 WiFi、開飛行模式也不影響。下面介紹它的連接方式、安裝步驟、一次性配對流程和六個工具的實際能力。
這是什麼¶
由 JMINN0 維護的 DSH 插件,歸類在工作流方向。它能給 Agent 提供一個真實的 adb shell,用來在這臺手機自身上執行 pm、am、logcat、dumpsys、screencap 等命令,權限是 uid 2000。
版本 2026.1105.1908(年.月日.時.分格式)。驗證環境是 nubia REDMAGIC NX809J / Android 16 (SDK 36) / adb 34.0.4 / DSH 0.2.2-rc.1。README 標註穩定性 10/10、工具定義 6/6。它是純 ESM 的 JS 插件,沒有構建步驟,也沒有 npm install。
關鍵點:端口還是 5555,只是地址換成了迴環¶
這一點值得先說清,因爲容易和常規 adb 用法混淆。端口沒有變,仍然是 5555;變的是「連哪個地址」——常規做法連局域網 IP,這個插件連 127.0.0.1,流量走回環網卡。
帶來的結果:
- 關 WiFi、開飛行模式都不會斷;
- 不依賴路由器,也不需要手機和別的設備在同一局域網;
- 同一局域網內的其他機器理論上也能連到這個端口,不過仍需持有本機的 adb 私鑰才能進入。
adb tcpip 之後 adbd 監聽的是整個網絡棧,本機連回環因此可行。但這一步會重啓 adbd,把 Shizuku 之類的其它客戶端一起踢掉,所以插件自己不執行它(詳見下文配對部分)。
前提條件和安裝¶
DSH Go 跑在手機內部的 proot Ubuntu 裏,插件相關的命令也都在這裏執行,不在電腦上執行。先確認幾件事:
- 一部開了開發者選項的 Android 手機;
- 無線調試可用(用於一次性配對);
- 首次配對時手機要連着 WiFi——配對走局域網,之後就不再需要了;
- proot 環境裏能裝上 adb 客戶端:
apt-get update && apt-get install -y android-tools-adb
裝完驗證:
adb version
# Android Debug Bridge version 1.0.41
需要注意:DSH Go 升級運行時鏡像時,apt 裝的東西會全部丟失,adb 需要重裝一次。
包從哪來¶
這個包目前沒有發佈到 npm registry,只存在於 GitHub 倉庫。dsh plugin add 支持本地目錄和包名兩種目標,這裏要用本地目錄:
git clone https://github.com/JMINN0/dsh-go-plugin-adb.git
cd dsh-go-plugin-adb
dsh plugin --profile web add .
add 後面的 . 表示當前目錄,必須先進入倉庫目錄再執行,否則會報找不到包。
--profile web 不能省。DSH 可以有多套 profile,手機本機引擎加載的那套叫 web;裝到默認 profile,手機 App 不會加載這個插件。
裝完要重啓引擎¶
安裝只改配置,不重載代碼。在 App 裏走:設置 → 引擎 → 重啓引擎。
重啓後工具列表裏會多出 6 個 adb_*。不重啓就看不到工具,這是最容易漏的一條。
驗證裝好了¶
# ① 配置裏有沒有這個 bundle
python3 -c "
import json
d=json.load(open('$HOME/.dsh/profiles/web/package.json'))
print([b for b in d['dsh']['profile']['bundles'] if 'adb' in b])"
# 期望輸出:['dsh-go-plugin-adb']
# ② 引擎有沒有加載失敗
grep -i "apply failed" ~/.dsh/dsh-app/diagnostics.md 2>/dev/null | grep adb || echo "沒有加載錯誤 ✅"
這兩步只證明配置對了,不證明工具能用。最後一關是在 DSH Go 對話裏直接說:
用 adb_devices 看看現在連着哪些設備
期望返回:
127.0.0.1:5555 device
看到這行纔算真的裝好了。如果 Agent 回覆「沒有這個工具」,回到重啓引擎那一步;如果返回「連不上,已試過端口」,回到下面的配對流程。
一次性配對¶
這是 adb 的標準流程,不是插件特有的。順序很重要,跳步會報 no devices/emulators found。
-
手機上:開發者選項 → 無線調試 → 使用配對碼配對設備。屏幕會顯示配對用的 IP:端口(例如
192.168.1.100:37123)和 6 位配對碼。注意「無線調試」主頁面還有一個「IP 地址和端口」(例如192.168.1.100:41000),那個端口每次開無線調試都會變,和配對端口不是同一個。 -
用配對端口配對:
adb pair 192.168.1.100:37123
# 提示 Enter pairing code: 時輸入 6 位碼
# 成功顯示 Successfully paired to ...
- 連上無線調試端口:
adb connect 192.168.1.100:41000
adb -s 192.168.1.100:41000 shell id
# uid=2000(shell) ...
- 最後連回環,這是插件默認走的路:
adb connect 127.0.0.1:5555
adb -s 127.0.0.1:5555 shell id
配對成功後密鑰存在 ~/.android/adbkey,之後不用再配對,重裝 adb 也不會丟。
不要用 adb tcpip 5555 去固定端口¶
早期文檔教過這一步,現在明確不要做。README 裏記錄的實測結果是:執行 adb tcpip 5555 之前 adbd、shizuku_server、GKD 用戶服務都存在,執行 8 秒之後 adbd 的 PID 變了(重啓了),Shizuku 和 GKD 的服務進程都沒了。原因是 adb tcpip 會重啓 adbd,而 adbd 是多個客戶端共享的資源——Shizuku 在 adb 模式下本身就是 adbd 的一個客戶端,重啓等於把別人踢下線。
對照組是 adb kill-server + start-server,這兩個操作不會動 adbd。插件自己的 ensure() 裏也永遠不調 tcpip,只「搭車」:用當前可用的連接,或者掃迴環端口找出 adbd 現在掛在哪個端口上。
手機重啓後怎麼恢復¶
adb tcpip 的設置不持久,重啓就丟,但不需要再執行它:
- 手機上確認「無線調試」開着;
- 插件會自己掃端口找回連接(掃
127.0.0.1:30000-50000,約 6 秒); - 掃不到的話,讀出無線調試頁面上「IP 地址和端口」那個號,手動
adb connect <IP>:<端口>。
adb_reconnect 工具也能強制重建連接,手機重啓後或 adb_devices 顯示 offline 時用它。
六個工具¶
六個工具都是給 Agent 調用的,正常對話時由 Agent 自己決定調用哪個,也可以直接點名。
adb_devices¶
列出當前連接的設備,無參數。
adb_devices
→ 127.0.0.1:5555 device
adb_shell¶
執行任意 shell 命令,最常用的一個。command 支持管道、重定向、&&、$();timeoutMs 可設超時,默認 60000 毫秒,範圍 1000–600000。
adb_shell { command: "getprop ro.build.version.release" } → 16
adb_shell { command: "pm list packages | grep tencent" }
adb_shell { command: "dumpsys battery | grep -E 'level|status'" }
實際邊界:
- 輸出上限 32MB,超出返回失敗但前 32MB 仍在;
- 輸出按 UTF-8 解碼,直接
cat圖片這類二進制內容會損壞,要看二進制得用od/base64繞一下; - 不支持 stdin,
top、vi這類交互式命令用不了; - 命令退出碼非 0 不算工具失敗,輸出照常返回,附帶退出碼說明;
- 每次調用多一次連接探測,約 50ms,換來斷線自愈。
adb_install¶
安裝 APK。
| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
path |
string | 是 | 設備上的絕對路徑,如 /sdcard/app.apk |
reinstall |
boolean | 加 -r 保留數據,默認 true |
|
downgrade |
boolean | 加 -d 允許降級,默認 false |
adb_install { path: "/sdcard/Download/app.apk" }
→ { text: "安裝成功:<路徑>" }
path 用的是設備側路徑,不是 proot 裏的路徑;proot 裏的文件要先 push 到設備上。簽名不一致時會失敗,要麼先卸載舊包(數據會丟),要麼用同一密鑰重新簽名。
adb_logcat¶
讀日誌尾部,不會留長駐進程。lines 默認 200,最大 20000;filter 支持正則,走 grep -E。
adb_logcat { filter: "FATAL", lines: 100 }
adb_logcat { filter: "AndroidRuntime|FATAL|ANR", lines: 200 }
匹配不到時返回「(最近 N 行裏沒有匹配 "X" 的內容)」,這是正常結果不是錯誤。
adb_screencap¶
截圖並保存。兩個參數都可選,adb_screencap {} 也合法。
| 參數 | 類型 | 說明 |
|---|---|---|
outPath |
string | 設備側路徑,默認 /sdcard/dsh-screencap.png |
localPath |
string | 同時拉回到 proot 的本地路徑,如 /tmp/shot.png |
adb_screencap {}
adb_screencap { outPath: "/sdcard/a.png", localPath: "/tmp/a.png" }
→ { text: "截圖已保存:/sdcard/a.png" }
截的是主屏。要截虛擬屏上的內容,用另一個插件 dsh-go-plugin-screen,不是這個。
adb_reconnect¶
強制重建連接:殺本地 adb server、重啓、把無線調試端口遷移到 5555、驗證 uid 2000。無參數。
能做什麼,不能做什麼¶
README 裏列的已實測能力包括:
pm list packages / pm path / pm install / pm uninstall
am start / am force-stop / am broadcast
logcat / dumpsys / getprop / settings
screencap / input / cmd window / cmd notification
cmd package 的 uninstall / clear 會卸包清數據,其餘子命令(如 list packages)只是查詢。
不能做的幾件事:讀不了 /data/data(SELinux 擋着 uid 2000);沒有 stdin,交互式命令用不了;二進制輸出會按 UTF-8 解碼而損壞;超時之後設備側的命令可能還在跑,取消工具不會殺遠端進程。
適用場景與注意事項¶
適合:已經在手機內部 proot 裏跑 DSH Go、希望 Agent 直接操作本機、又不想依賴外部電腦或局域網的場景。社區目錄頁把分類歸在工作流。
用之前要看的幾點:
- 插件以當前 dsh 進程的權限運行,
adb_shell沒有攔截、沒有白名單、沒有二次確認,能卸包、刪文件、重啓、改設置。安裝前應先讀一遍源碼。 - 許可證是 MIT。GitHub 倉庫星標爲 0,倉庫創建於 2026-11-04,屬於很新的項目。
- 驗證只有單機型:Android 16、adb 34.0.4、nubia REDMAGIC NX809J。其他 Android 版本、其他廠商 adbd、其他 adb 版本都未驗證。
- 目前沒有發佈到 npm registry,只能從 GitHub 裝。
- 安裝只改配置,必須手動重啓引擎,否則工具不會出現。
下面是目錄頁和源碼地址:
- 目錄頁:https://www.skillhub.cn/plugins/JMINN0/dsh-go-plugin-adb
- GitHub:https://github.com/JMINN0/dsh-go-plugin-adb