快速了解
它能做什么
远程调试 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 使用说明
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.json的version)。真机工作目录示例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: UnexpectedToken。reload 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 名(sw→sw2→sw3…),绕开僵尸记录。不要在 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 必须带 --profile(cmd / 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 同款,完全可控)
- 主进程
main.ts:titleBarStyle:"hidden",不用 titleBarOverlay;加window:minimize/window:toggle-maximize/window:close/window:is-maximizedIPC;maximize/unmaximize事件经broadcast推前端。 - preload:
mobiusDesktop暴露windowMinimize/windowToggleMaximize/windowClose/windowIsMaximized/onMaximizeChange。 - 前端
window-controls.tsx:仅!IS_MAC_PLATFORM渲染(macOS 用系统交通灯hiddenInset);图标色var(--text-primary)→ 天然随主题;关闭键 hover 红#e81123。 - 顶栏 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。
风险事实
证据与编辑审查Manifest、Bundle patch、分发与新鲜度
不可变证据
审查状态与源码活动
在核对来源内容和不可变发布记录后,已由人工批准发布。AI 参与了内容草稿生成,最终发布决定由人工完成。
人工审查于 2026/9/4 UTC 11:38。GitHub 事实核对日期: 2026/9/3 UTC 15:47。
自当前证据基线以来,没有记录到重要源码变化。