用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/Jasonzhangf/zterm --skill zterm-mac-dev命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
审计、开发和验证 zterm Android 客户端;按当前架构、最新目标和 owner 选择门禁,区分源码、设备与 OTA 证据。
terminal buffer / render / daemon mirror 真源与门禁
Apply AppSDK engineering quality gates, project contracts and lifecycle evidence. Use optional Guidance for planning; keep automatic multi-worker Collab separate from quality admission.
正在显示 SKILL.md
| name | zterm-mac-dev |
| description | zterm Mac 客户端开发工作流 - Electron 壳、terminal renderer、local/remote tmux、自闭环验证 |
mac/ 下的 Electron / renderer / preload / local tmux / remote bridge 开发~/.codex/AGENTS.md~/.codex/USER.mdcoding-principals/SKILL.mdandroid/docs/decisions/0001-cross-platform-layout-profile.mdandroid/docs/architecture.mdandroid/docs/dev-workflow.mdmac/MEMORY.mdSKILL.mdzterm-mac-dev。PaneStage / resolvePaneProfile token 与 Mac shell chrome CSS;禁止在 runtime / renderer / buffer 层补外观。验证至少跑 pane targeted tests、type-check/build,并用渲染 smoke 证明 split DOM 与 spacing token(如 stage gap / divider width)已进入最新 bundle。missingRanges 必须从 view -> runtime -> transport 原样透传;任一层清空它,scroll prefetch 都会静默失效。Ctrl + 字母 编码/默认 label 规则。BridgeSettings.terminalThemeId;不能只改本页 draft,避免出现“看起来切了主题,切页后又回默认”的假激活。capture-pane -E -1 会停在历史尾部,不能用于 app buffer truth,否则 packaged DOM 会落后真实 tmux capture-pane 尾部。finally / 结束清单中关闭或说明保留理由。禁止只跑完实验不清理测试窗口、临时服务、pipe-pane、debug port。frame.x/y 只保证相对其 immediate splitter;嵌套 split 必须先按 splitter cursor/offset 递归 flatten,再套一次 window top-left + content inset。禁止在度量阶段再次累加已定位 leaf offset;必须用真实复杂 split tree 回归和 live crop bounds gate 锁 cropRect 不越过 window。iterm2-pane,不能造假 tmux id 或拒绝选择。live gate 至少断言 nonItermAppWindows >= 1、nonTmuxPanes >= 1、outOfBounds == 0。mac/docs/function-map.mdmac/docs/mainline-call-map.jsonmac/docs/testing/mac-desktop-workspace-test-design.mdbinding pending,禁止伪造 symbol / caller / callee。MacRuntimeRegistry,pane UI 不得直接 connectRemote/connectLocalTmux。任何 Mac 改动,默认按下面顺序闭环;没走完,不要向 Jason 报“可以手测”。
改代码
-> type-check
-> build
-> package(若影响 packaged 行为)
-> 退出旧 app
-> 启动新 app / 新包
-> 自己完成 smoke
-> 采集证据(命令输出 / 截图 / 资源快照)
-> 只有证据闭环后,才能汇报 Jason
出现以下任一项,必须跑 packaged app smoke,而不只 dev server:
pnpm --filter @zterm/mac type-check
pnpm --filter @zterm/mac build
Mac terminal / transport / runtime 改动必须先跑本地客户端核心连接 gate,不能用 daemon-only probe 替代。
pnpm --dir mac test -- --reporter dot
pnpm --dir mac run type-check
最低覆盖面:
bridge-transport:remote daemon WebSocket 两阶段握手、connected state、head/body/input 发到 live socket、stale socket 不污染当前连接。local-tmux-transport:Electron local tmux API connect、connected event、head/body request、input/resize/activity/disconnect 同一 clientId。terminal-runtime:head 变化触发 body sync,same-end revision 变化不能被去重吞掉。证明范围:
.app、真实窗口、DOM 输入、资源/退出态已闭环。pnpm --filter @zterm/mac package
至少覆盖本轮改动直接影响的主路径:
tmux capture-panetmux pipe-panepnpm --dir mac run blackbox:terminal-buffer -- --case=allconnected、底部几何对齐或静态截图不算 terminal 数据闭环zterm_mac_gate_sequence / zterm_mac_gate_tui / zterm_mac_gate_large,并用 tmux option marker 验证 owner/case 后才允许 respawn / clear-history / cleanup;禁止 timestamp 新建一串 session,禁止碰无 marker 的用户 session--user-data-dir 直接启动二进制;禁止 open -n unsigned package(Launch Services 会在第二次或之后把 unsigned bundle 重新走 Gatekeeper,常见“恶意软件/移到废纸篓”回归)。正确顺序见 §3.6 Packaged App 启动协议。--cleanup-sessions 才能在 marker 验证通过后精确关闭它们。运行结束必须复核 tmux list-sessions,确认没有遗留新的 zterm_mac_* 临时 sessionscroll.atBottom=false、append 后 reading rows 不变、scroll-to-bottom 后 app tail 与 tmux tail 一致;若 clientHeight === scrollHeight,先修父容器高度约束,不准把 DOM 全量内容当作 reading 通过ps/top 资源采样 + 退出态进程检查证据至少二选二:
证据落点:
mac/evidence/<date>-<topic>/ps -axo pid,ppid,pgid,%cpu,rss,vsz,etime,comm | egrep 'PID|ZTerm|Electron Helper'
top -pid <renderer_pid> -stats pid,cpu,mem,threads,state,time -l 2
.app 正常只在闭环完成后使用:
Jason,已完成本轮自闭环:
1. 改动:
2. 静态验证:type-check/build/package 结果
3. 运行态 smoke:做了哪些真实操作
4. 证据:截图/命令输出/资源采样位置
5. 结论:哪些已验证通过,哪些仍未覆盖
6. 现在才轮到你手测的部分:
pnpm --filter @zterm/mac package 必须默认跳过 macOS code signing:CSC_IDENTITY_AUTO_DISCOVERY=false + build.mac.identity=null。electron-builder 自动发现 distribution identity;否则每次 package 都可能触发 Keychain 授权弹窗。.app 做 ad-hoc 重签:codesign --force --deep --sign - <ZTerm.app>,再复制到实际目标路径并对目标再签一次。目标路径必须从运行中进程或 Jason 实际点击入口确认,优先检查 /Applications/ZTerm.app、$HOME/Applications/ZTerm.app、~/Downloads、~/Desktop、~/.Trash;不要只修 /Applications 后宣称完成。xattr -cr 处理 .app bundle;它可能生成 ._* AppleDouble 文件并破坏 sealed resources。若误生成,只能在该 .app 内精确删除 ._* 后重新签名。可精确删除 com.apple.quarantine;不要把 spctl --assess rejected 当作 unsigned internal alpha 的启动失败证据,真实判定必须用 Finder/open 启动和进程路径。codesign --verify --deep --strict 与 spctl --assess --type execute --verbose=4。若输出 notarization indicates this code has been revoked,根因是旧 revoked 包仍在实际路径,必须退出该路径的运行中明确 PID、把旧包改名备份、安装当前构建、重签、再从同一路径启动验证;osascript tell application "ZTerm" to quit 可能被 revoked app 挂住,卡住时只结束该明确 osascript PID,再用旧 ZTerm 明确 PID 关闭。Unsigned 本地 package 启动必须严格按下列顺序,禁止改换步骤顺序。
<workspace>/mac/out/mac-arm64/ZTerm.app/Contents/MacOS/ZTerm 必须存在;缺失则直接失败并提示先跑 pnpm --dir mac run package。codesign --force --deep --sign - "$APP_PATH"
xattr -cr):
xattr -d com.apple.quarantine "$APP_PATH"
--user-data-dir 直接执行二进制,绝对不要 open -n unsigned package:
"$APP_PATH/Contents/MacOS/ZTerm" \
--remote-debugging-port=<port> \
--user-data-dir="$EVIDENCE/user-data" \
--no-sandbox \
> "$EVIDENCE/launch-stdout.txt" 2> "$EVIDENCE/launch-stderr.txt" &
tail -f stderr 不能阻挡主循环;用 child.on('exit', ...) / child.on('error', ...) + spawn(不是 spawnSync),把 exit code、stderr 写到 ${EVIDENCE}/launch-exit.json / launch-stderr.txt。open -n <unsigned.app> 启动 unsigned package;这是 Launch Services 重走 Gatekeeper 的常见触发。xattr -cr <unsigned.app>;会生成 ._* AppleDouble 破坏 sealed resources。spctl --assess rejected 当作 unsigned internal alpha 的启动失败证据。真实判定必须看 Finder/open 启动 + 进程路径 + CDP /json/version + /json/list 返回目标 page target。codesign --verify --deep --strict 立即确认 valid on disk。ps -axo pid,comm,args | egrep 'ZTerm|remote-debugging-port=<port>',再按 PID kill;禁止叠多个 instance 污染端口和 evidence。git log --oneline -- mac packages/shared .agents/skills/zterm-mac-devgit status --shortmac/MEMORY.mdmac/task.mdmac/docs/function-map.mdmac/docs/testing/mac-desktop-workspace-test-design.mdmac/docs/alpha-readiness.md(若不存在或过期,先补齐)mac/evidence/<date>-* 证据目录索引--remote-debugging-port 实例;新开前先用明确 PID/app-level quit 收掉旧实例,禁止多端口并发导致证据串线。tmux capture-pane -e 的 SGR 输出;纯 capture-pane -p 只保留文本,会把 fg/bg 全部退成默认色。LocalTmuxManager 的 head/sync capture 保留 -e -p,但禁止加 -E -1;若黑盒出现 tmux/pipe 有完整尾部而 app DOM 缺尾部,先查该 capture 参数,不要在 renderer 补偿。readSessionCapture 检测 alternate_on 后只用 bounded visible capture(-S -<paneRows>)作为当前 screen truth,避免历史帧累计成刷新延迟或旧行上移。System Events 注入快捷键作为真源;优先通过正式 preload IPC / menu owner 触发 MacWindowManager.createWindow(),再用 CDP 验证 page target、renderer windowId、workspace key、quit/reopen restore。若 System Events 卡住,只中断该明确 osascript 会话,不能用它证明失败或成功。preload.cts -> preload.cjs。凡修改 window.ztermMac bridge 或 IPC surface,必须同步更新 preload.ts 与 preload.cts,并用 packaged smoke 证明真实 preload bridge 可用;不能只看 renderer type 或 preload.ts。input.value = ... 当真源;自动化应先 focus/select 目标 input,再用 CDP Input.insertText 或等价真实输入路径触发 React state,最后点击正式 UI command。直接 setter 只可作诊断,不能作为 browse/connect/save 成功证据。list-sessions 路径:focus/select input 后用 Input.insertText 输入 host/port/token,点击正式 Discover / Save & connect;证明 discovery 不创建 runtime,Save & connect 才创建 remote runtime;只允许 dedicated marked tmux session;写入 evidence 前必须 redacted authToken / targetAuthToken / storage token 字段。close/error 时 reject pending command,尤其是 Browser.close;否则数据对比已绿也会因为未 settle 的 top-level await 退出 13,并且缺少 process-after-close evidence。tmux pipe-pane -o <log> 作为输入 oracle; 对 detached fixture 可能不稳定,不能单独证明 app input 到达或串线。完成后用 关闭观测管道,避免后台持续写日志。tmux send-keys、send-text 到任何不在本次测试范围内的 tmux sessionfin、rcc、server 等已有 session)zterm_mac_color),不碰其他 sessiontmux capture-pane -p -t <session> 确认只含测试内容,无污染capture-panecattmux pipe-pane -t <session>activePaneId 指向现存 pane、剩余 runtime 还能输入。list-sessions/Refresh,允许用现有用户 sessions 做列表观测,但禁止写 input、create、kill、rename。证据必须同时证明 refresh 后 live sessions 进入 rail、workspace pane/tab 数不变、terminal stage 未自动打开 session、错误时显示 error 且 saved/open sessions 保留。runtimeEnsureCalls=0,explicit rail session click 后才创建 remote runtime 并渲染 dedicated marked session 输出。只能使用本轮 dedicated marked session,evidence/storage 里的 authToken / targetAuthToken 必须 redacted,结束时复核 debug port、ZTerm/Electron helper、tmux session 已精确清理。--zterm-alpha-smoke 下,证据必须同时证明 active runtime error -> Reconnect -> connected、hidden runtime connect count 为 0、windowId 稳定、process-after-close* 为空或有明确解释。ShellWorkspace 引用、architecture truth gate 锁 MAC-16-LegacyRemoval、packaged DOM 无 .shell-workspace-root / forbidden root。历史 zterm:mac:shell-workspace:v1 localStorage 残留只说明用户数据未清理,不可当作 fallback 存在或已读取的证据。