证据快照复核于 2026-09-03GitHub 数据核对日期: 2026-08-21
来源已审查独立 Skill编码与审查终端 UI Profile

mobius-electron-debug

远程调试 Mobius 的 Electron 壳层改动:替换 app.asar、重启 Windows 应用并用截图检查效果。

快速了解

它能做什么

远程调试 Mobius 的 Electron 壳层改动:替换 app.asar、重启 Windows 应用并用截图检查效果。

本站提供的是中文说明,不代表该项目或 Plugin 自身提供中文界面;语言支持请以上游文档为准。

能力
编码与审查调试测试工作流自动化

选择前先看

该技能为 Mobius 桌面端提供可重复的远程调试闭环,覆盖 Electron 主进程、preload、标题栏、窗口控制以及打进 app.asar 的渲染层改动。它说明何时必须重新打包、如何安全传输新归档文件、如何用独立脚本避免应用退出后桥接中断导致流程中止,以及如何通过截图反馈验证结果。

适合谁

能够构建 Mobius 桌面端,并可访问已通过 aimux 连接的 Windows 设备的 Mobius 贡献者。

常见任务

  • 在远程 Windows 设备上测试 Electron 主进程、preload、标题栏或窗口控制代码改动。
  • 仅替换重新构建的 app.asar,避免传输完整 Windows 安装包。
  • 通过截图采集、下载和查看来排查桌面壳层的视觉改动。
  • 利用保留的原始或上一版 app.asar 备份,从失败的迭代中回退。

权限与数据

需要通过 aimux 控制远程 Windows 设备,并将构建产物和脚本传到其临时目录。

权限
  • 创建 aimux 会话并向远程 Windows 设备发送命令。
  • 停止和启动 Mobius Desktop 进程。
  • 复制、备份和替换远程应用目录中的 app.asar。
  • 采集并下载远程设备截图。
数据处理
  • 会在本地环境和远程设备之间传输重新构建的 app.asar、PowerShell 脚本、进程状态和截图。
  • 除非自行清理,远程端会保留 app.asar 备份文件和临时产物。
外部服务
  • 连接远程 Windows 设备的 aimux bridge。
凭据
  • 需要具备 aimux 远端访问权限;证书或认证的具体要求未在证据中说明。

局限

  • 仅适用于 Mobius Electron 桌面端以及通过 aimux 连接的 Windows 设备。
  • 停止应用会主动断开当前 bridge;需等待自动重连,旧会话失效时应使用新会话名。
  • 打包、类型检查、远程连接和截图检查仍可能分别失败。
  • 技能记录的是某个未签名、高 DPI Windows 环境下的 titleBarOverlay 问题,并非对所有 Electron 环境的保证。

DSHub 已核对

  • 固定版本的技能文档已描述重新打包、远程替换 app.asar、重启、重新连接和截图验证的流程。
  • 源提交和完整技能文档已通过硬性采集检查。

DSHub 未核对

  • DSHub 未安装、执行或在远程 Windows 设备上验证该流程。
  • 提供的证据未声明 Harness 版本范围。

固定版本安装

主要操作

这个独立 Skill没有 DSH Plugin 安装操作,请根据源码文档使用真实交付方式。

访问源码项目

维护者原文

Skill 使用说明

查看 commit 1eb8750 对应的 SKILL.md
维护者编写的上游内容原文于 2026/8/30skills/mobius-electron-debug/SKILL.md 获取,正文和仓库相对媒体固定到 commit 1eb8750d2d90,内容哈希为 b8f6bf27c81e。以下是未经 DSHub 翻译的上游原文,语言可能与当前页面不同;第三方托管的 badge 可能独立更新。

name: mobius-electron-debug description: Iterate on the Mobius desktop (Electron) client on a remote Windows machine via aimux — hot-swap app.asar through the bridge, restart the exe, and verify with a screenshot feedback loop. Use when changing Electron-shell code (main process / preload / title bar / window controls) that requires repackaging.

Mobius 桌面端 (Electron) 远程调试循环

改桌面端 Electron 壳代码(主进程 / preload / 标题栏 / 窗口控制等)后,必须重打包 + 替换真机 app.asar 才生效。本 skill 总结如何在 aimux 反向连接的 Windows 真机上,做「改代码 → 重打包 → 热替换 asar → 重启 exe → 截图验证 → 据反馈再改」的闭环迭代,无需用户手动操作。

本文所有路径里的 <remote> = aimux bridge remote 名(Windows 主机);<version> = 桌面端版本号(见 mobius/desktop/package.jsonversion)。真机工作目录示例 C:\tmp\mobius-desktop-<version>-win-x64

0. 先判断:这次改动要不要重打包?

改动位置 进 app.asar? 生效方式
mobius/desktop/electron/**(main.ts / preload.ts / lib/*) ✅ 进 asar 必须重打包 + 替换真机 asar + 重启 exe
mobius/desktop/src/**(登录页 login.ts / styles.css / index.html) ✅ 进 asar(renderer) 同上
mobius/frontend/src/**(远程工作台前端 shell.tsx / App.tsx 等) ❌ 不进 asar(服务器托管) python3 start.py --only-update-frontend 部署后,exe 重启或硬刷新即生效
python-runtime / Electron 版本 / electron-builder.yml 整包重打 + 重装

关键:壳改动(main/preload/登录页)在 asar 里,远程前端改动在服务器。两者都要让 exe 重新加载——壳改动靠替换 asar + 重启 exe,前端改动靠重启 exe(loadURL 会拉最新前端 hash)。

1. 核心约束:aimux bridge 依赖 exe 运行

桌面端的 aimux supervisor 是 exe 的子进程。这意味着:

  • kill exe = 断 bridge = 你的 aimux session 立即失联
  • 但 exe 重启后 supervisor 会自动 reverse-connect,bridge 几秒内重连,可重新 aimux new 建会话。
  • 因此替换 asar 必须用 detached 脚本(独立进程),让它在 bridge 断开后仍能完成 kill → 替换 → 重启。不能在当前 session 里同步 kill exe(会把自己掐断,替换/重启就没人执行了)。

2. 完整调试循环(一次迭代 ≈ 3–4 分钟)

步骤 1:改代码 + 本地类型检查

cd mobius/desktop && npx tsc --noEmit          # 壳类型检查(exit 0 才继续)
cd mobius/frontend && npm run build            # 前端改动时验证 vite build 通过

步骤 2:重打包壳(只打 win-x64,跳过菜单同步省时间)

python3 build.py --build-electron --targets win-x64 --skip-menu-sync
# 产物:mobius/desktop/release/win-unpacked/resources/app.asar  (约 48KB!)
#       mobius/desktop/release/Mobius Desktop-<version>-win-x64.zip

关键优化:标题栏/窗口控制这类壳改动全部编译进 app.asar(仅几十 KB)。只需替换真机的 app.asar,不用推 180MB 整个目录。asar 不含 python runtime(python 是 extraResources,单独在 resources/python/)。

步骤 3:建 aimux 会话 + 备份原版 asar + 推新 asar 到临时目录

export PATH="$HOME/.local/bin:$PATH"
BASE='C:\tmp\mobius-desktop-<version>-win-x64'

aimux new --remote <remote> --profile powershell --name sw --reuse
# 首次:把真机自带的原始 app.asar 另存为 .orig(永久回滚点,只存一次)
aimux send-keys "<remote>/sw" -- "if (!(Test-Path '$BASE\resources\app.asar.orig')) { Copy-Item '$BASE\resources\app.asar' '$BASE\resources\app.asar.orig' -Force; 'ORIG_SAVED' } else { 'ORIG_EXISTS' }" Enter
sleep 2

# 推新 asar 到临时目录(不直接覆盖运行中的 app.asar!)
aimux send_files <remote> 'C:\tmp\new-asar' 'mobius/desktop/release/win-unpacked/resources/app.asar'

不要直接 send_files 覆盖 resources\app.asar:运行中的 Electron 可能锁文件,且覆盖到一半会损坏。永远先推到临时目录,再用脚本原子替换。

步骤 4:detached 脚本原子替换 + 重启 exe

swap-asar.ps1(见 §3)推到真机并 detached 执行:

aimux send_files <remote> 'C:\tmp\new-asar' '/tmp/swap-asar.ps1'
# detached 启动:Start-Process 起独立 powershell 进程,当前 session 命令立即返回
aimux send-keys "<remote>/sw" -- 'Start-Process powershell -WindowStyle Hidden -ArgumentList "-NoProfile","-ExecutionPolicy","Bypass","-File","C:\tmp\new-asar\swap-asar.ps1"; echo LAUNCHED' Enter

脚本时序:sleep 2(让当前 session 命令返回)→ 备份当前 asar → Stop-Process 杀 exe(bridge 断)→ 替换 asar → Start-Process 重启 exe → 写完成标记。

步骤 5:等 bridge 重连 + 建新会话

sleep 20                                                       # 等 exe 重启 + supervisor 反连
aimux remote ls | grep <remote>                                # 确认 connected
aimux new --remote <remote> --profile powershell --name chk    # 用新会话名(见 §5 坑)

步骤 6:验证 asar 已替换 + exe 在跑

aimux send-keys "<remote>/chk" -- \
  "Write-Output ('asar=' + (Get-Item '$BASE\resources\app.asar').Length)" Enter \
  '$p = @(Get-Process "Mobius Desktop" -ErrorAction SilentlyContinue); Write-Output ("proc=" + $p.Count)' Enter \
  "Write-Output ('done=' + (Get-Content C:\tmp\new-asar\swap-done.txt -ErrorAction SilentlyContinue))" Enter
sleep 3
aimux capture "<remote>/chk" --lines 20 | sed 's/\x1b\[[0-9;]*[mGKHJ]//g' | tail -10

期望:asar= = 新 asar 字节数、proc=4(Electron 多进程:main + GPU + renderer + utility)、done=DONE_HHMMSS

步骤 7:截图验证(见 §4 详述)→ 据反馈回到步骤 1


3. 关键脚本(推到真机 C:\tmp\new-asar\ 下)

swap-asar.ps1 —— 原子替换 + 重启

Start-Sleep -Seconds 2
$base = 'C:\tmp\mobius-desktop-<version>-win-x64'
# 备份当前 asar(每次覆盖 .bak;原版永久存在 .orig)
try { Copy-Item "$base\resources\app.asar" "$base\resources\app.asar.bak" -Force -ErrorAction SilentlyContinue } catch {}
# 杀 exe(会断 aimux bridge;supervisor 重启后自动重连)
Get-Process -Name 'Mobius Desktop' -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 3
# 替换 asar
Copy-Item 'C:\tmp\new-asar\app.asar' "$base\resources\app.asar" -Force
Start-Sleep -Seconds 1
# 重启 exe(加载新 asar;supervisor 起 bridge 重连)
Start-Process -FilePath "$base\Mobius Desktop.exe" -WorkingDirectory $base
# 完成标记
'DONE_' + (Get-Date -Format 'HHmmss') | Out-File 'C:\tmp\new-asar\swap-done.txt'

screenshot.ps1 —— 激活窗口 + 截全屏

Add-Type -AssemblyName System.Windows.Forms,System.Drawing
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
  [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr h);
  [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr h, int n);
}
"@
# 把 Mobius 窗口拉到前台(截图前必须,否则截到的是别的窗口)
$procs = Get-Process 'Mobius Desktop' -ErrorAction SilentlyContinue | Where-Object { $_.MainWindowHandle -ne [IntPtr]::Zero }
if ($procs) {
  $h = $procs[0].MainWindowHandle
  [Win32]::ShowWindowAsync($h, 9) | Out-Null      # SW_RESTORE
  Start-Sleep -Milliseconds 400
  [Win32]::SetForegroundWindow($h) | Out-Null
  Start-Sleep -Milliseconds 700
}
$b = [System.Windows.Forms.SystemInformation]::VirtualScreen
$bmp = New-Object System.Drawing.Bitmap $b.Width, $b.Height
$g = [System.Drawing.Graphics]::FromImage($bmp)
$g.CopyFromScreen($b.X, $b.Y, 0, 0, $b.Size)
$bmp.Save('C:\tmp\new-asar\screen.png')
$g.Dispose(); $bmp.Dispose()
Write-Output ('shot=' + (Get-Item 'C:\tmp\new-asar\screen.png').Length + ' ' + $b.Width + 'x' + $b.Height)

⚠️ 避坑:曾尝试在 screenshot.ps1 里加 $wsh.SendKeys('^+{R}') 触发 exe 的 Ctrl+Shift+R 硬刷新,结果 conda 的 PowerShell 报 ParserError: UnexpectedTokenreload exe 改用 swap 重启(swap 不换 asar 也行,纯重启就重新 loadURL 拉最新前端),别在 ps1 里混 SendKeys。


4. 截图 feedback 循环(本 skill 的核心价值)

「改了壳代码但看不到效果」是桌面端调试最大痛点。这套循环让你纯远程、无需用户介入就能看到渲染结果并迭代。

4.1 截图

aimux send-keys "<remote>/chk" -- 'powershell -ExecutionPolicy Bypass -File C:\tmp\new-asar\screenshot.ps1' Enter
sleep 6   # 激活+截图含几处 sleep,留够时间
aimux capture "<remote>/chk" --lines 5   # 看到 shot=xxxx 即成功

4.2 下载到本地

aimux get_files <remote> /tmp/host-screen 'C:\tmp\new-asar\screen.png'

4.3 裁剪 + 放大要看的区域

全屏图(可能双屏 3840×1080)细节看不清。用 ffmpeg 裁目标区域放大:

cd /tmp/host-screen
# 裁右上角窗口按钮区(坐标按实际截图调整:crop=宽:高:x:y,原点左上)
ffmpeg -y -loglevel error -i screen.png -filter "crop=380:130:3460:0,scale=1140:390" topright.png
# 裁整个顶栏
ffmpeg -y -loglevel error -i screen.png -filter "crop=1920:420:1920:0,scale=1600:350" topnav.png

没有 ffmpeg 就用 PIL:python3 -c "from PIL import Image; Image.open('screen.png').crop((x,y,x+w,y+h)).save('out.png')"

4.4 看图 + 客观验证

  • Read 一张图 → 直接看到渲染效果(图会自动上传 CDN)。
  • 细节拿不准(按钮有没有渲染?图标大小协调吗?)→ 用 analyze_image 客观提问(「右上角有几个按钮?图标颜色?距右边缘多远?」),不要让它推测。
  • 根据截图判断是否符合预期 → 不符合就回 §2 步骤 1 改代码,进入下一轮。

4.5 实战案例:标题栏按钮的 5 轮迭代

这个循环在本任务里跑了多轮,每轮都靠截图发现问题:

轮次 改动 截图反馈 结论
v1 titleBarStyle:hidden + titleBarOverlay:{color:rgba(0,0,0,0)} 右上角无按钮 透明 color 不渲染符号
v2 overlay color 改不透明 #0a0e16 右上角仍无按钮(只有背景色块,无 min/max/close 符号) 此环境(未签名 exe + 高 DPI)titleBarOverlay 原生按钮符号根本不渲染
v3 放弃 overlay,改前端自绘按钮 + window:* IPC 右上角4 个按钮齐全 自绘方案生效
v4 自绘按钮缩小 + 加刷新按钮 刷新图标比其他大很多 svg viewBox 24 width 12 vs 其他 viewBox 11 width 10,视觉不一致
v5 刷新 svg 改 width 10 4 图标大小协调 ✅ 完成

没有截图循环,v1/v2 的「按钮不渲染」根本发现不了(代码逻辑全对、tsc 全过、exe 正常跑),会误以为成功。


5. aimux bridge session 的坑

坑 1:session 状态不一致(zombie session)

exe 重启(bridge 断再重连)后,旧的 session 在 aimux 本地有记录、但 bridge 上已失效:

aimux new  --reuse   →  error: session 'X' already exists     # 本地有记录
aimux capture X      →  error: session not found              # bridge 上没有
aimux kill X         →  error: session not found              # kill 走 bridge 通道也失败,清不掉本地记录

解法:直接换一个新 session 名swsw2sw3…),绕开僵尸记录。不要在 kill/new 上死磕。

坑 2:capture 报 client replaced

detached 脚本 kill exe 时,当前 capture 会报 bridge remote disconnected: client replaced。这是预期(新 exe 已重连替换旧连接),不是错误。等 20s 后 aimux new 新会话即可。

坑 3:bridge remote 必须带 --profile

反向 Windows 设备的 aimux new 必须带 --profilecmd / powershell / mingw64,见 aimux remote ls 的 PROFILES 列)。推荐 powershell(脚本兼容性最好)。


6. titleBarOverlay 陷阱 + 自绘窗口按钮方案

陷阱

Windows 上 titleBarStyle:"hidden" + titleBarOverlay:{color,symbolColor,height} 理论上叠原生 min/max/close 按钮。但在未签名 exe(signAndEditExecutable:false)+ 高 DPI 缩放的真机上,overlay 只渲染背景色块、按钮符号(symbolColor)不显示。用户将无法最小化/关闭窗口。

方案:前端自绘按钮(VSCode 同款,完全可控)

  1. 主进程 main.tstitleBarStyle:"hidden"不用 titleBarOverlay;加 window:minimize / window:toggle-maximize / window:close / window:is-maximized IPC;maximize/unmaximize 事件经 broadcast 推前端。
  2. preloadmobiusDesktop 暴露 windowMinimize / windowToggleMaximize / windowClose / windowIsMaximized / onMaximizeChange
  3. 前端 window-controls.tsx:仅 !IS_MAC_PLATFORM 渲染(macOS 用系统交通灯 hiddenInset);图标色 var(--text-primary)天然随主题;关闭键 hover 红 #e81123
  4. 顶栏 drag.mobius-topnav-webkit-app-region:drag,内部交互元素 no-drag(仅 window.mobiusDesktop.isDesktop 时挂 class,Web 端零影响)。

主题自适应

顶栏背景本就是 var(--bg-primary)(随主题切换的 CSS 变量)。隐藏原生标题栏后,顶栏直接充当标题栏 → 切主题自动变色,零额外逻辑。这是「让前端既有顶栏充当标题栏」相比「自绘独立标题栏条」的最大优势。


7. 回滚

真机保留了两个备份(在 resources\ 下):

  • app.asar.orig —— 真机出厂原版(永久,首次 swap 时存)。最稳回滚点。
  • app.asar.bak —— 上一次替换前的版本(每次 swap 覆盖)。

回滚:Copy-Item app.asar.orig app.asar -Force → 重启 exe(再跑一次 swap-asar.ps1,或改脚本只重启不替换)。


8. 速查表(一次迭代)

# 0. PATH
export PATH="$HOME/.local/bin:$PATH"
REMOTE=<remote>; BASE='C:\tmp\mobius-desktop-<version>-win-x64'

# 1. 改代码 + 类型检查
cd mobius/desktop && npx tsc --noEmit

# 2. 重打包(只 win-x64)
python3 build.py --build-electron --targets win-x64 --skip-menu-sync
# 前端改动另加: python3 start.py --only-update-frontend

# 3. 推 asar + 脚本到临时目录
aimux send_files $REMOTE 'C:\tmp\new-asar' 'mobius/desktop/release/win-unpacked/resources/app.asar'
aimux send_files $REMOTE 'C:\tmp\new-asar' '/tmp/swap-asar.ps1'

# 4. detached 原子替换 + 重启
aimux new --remote $REMOTE --profile powershell --name sw --reuse
aimux send-keys "$REMOTE/sw" -- 'Start-Process powershell -WindowStyle Hidden -ArgumentList "-NoProfile","-ExecutionPolicy","Bypass","-File","C:\tmp\new-asar\swap-asar.ps1"; echo GO' Enter

# 5. 等重连 + 验证
sleep 20 && aimux remote ls | grep $REMOTE
aimux new --remote $REMOTE --profile powershell --name chk
aimux send-keys "$REMOTE/chk" -- "Write-Output ((Get-Item '$BASE\resources\app.asar').Length)" Enter
sleep 3 && aimux capture "$REMOTE/chk" --lines 6

# 6. 截图 → 下载 → 裁剪 → 看
aimux send-keys "$REMOTE/chk" -- 'powershell -ExecutionPolicy Bypass -File C:\tmp\new-asar\screenshot.ps1' Enter
sleep 6
aimux get_files $REMOTE /tmp/host-screen 'C:\tmp\new-asar\screen.png'
cd /tmp/host-screen && ffmpeg -y -loglevel error -i screen.png -filter "crop=380:130:3460:0,scale=1140:390" topright.png
# Read topright.png 看效果; 不满意回到步骤 1

9. 收尾

  • 任务完成后销毁 aimux 会话:aimux kill "<remote>/chk" 等(exe 多次重启后旧会话已是 zombie,kill 报 not found 属正常)。
  • 真机临时文件 C:\tmp\new-asar\* 可留(下次迭代复用脚本);app.asar.orig 务必保留。
  • 壳改动入 git(mobius/desktop/electron/** 被跟踪;只有 release/node_modules/desktop-builds/ 被 gitignore)。

有意识地管理

安装与管理

前置条件与目标 Profile

目标 终端 UI Profile

交付方式 Skill 文件 — https://raw.githubusercontent.com/nutshellai-tech/mobius/1eb8750d2d9012e1f50a18f7c60c2ad040c04889/skills/mobius-electron-debug/SKILL.md

兼容性与访问范围

Mobius Electron desktop client with an aimux-connected Windows machine Not declared in supplied evidence

检查兼容性证据

风险事实

remote-device-control

Stops and restarts the remote Mobius Desktop process and replaces its app.asar file.

证据
license

The supplied license permits non-commercial use; commercial use requires a separate license.

证据
证据与编辑审查Manifest、Bundle patch、分发与新鲜度

不可变证据

审查状态与源码活动

人工已批准

在核对来源内容和不可变发布记录后,已由人工批准发布。AI 参与了内容草稿生成,最终发布决定由人工完成。

人工审查于 2026/9/4 UTC 11:38GitHub 事实核对日期: 2026/9/3 UTC 15:47

自当前证据基线以来,没有记录到重要源码变化。

下一步

比较生态 Artifact 类型

订阅重要变化: mobius-electron-debug