awesome-ios-sim:把 iOS 模擬器狀態變成可版本化的代碼

前言

在 DeepSeek Harness(DSH)裏給智能體接 iOS 模擬器,常見做法是開放一個 shell,讓它直接調 xcrun simctl。這條路的問題很實際:環境配置散落在腳本和沒寫進文檔的 defaults 命令裏,測試環境難以復現;模型拿到的只是一個無類型、不安全的 shell 入口,改了什麼、按什麼順序改的,事後無從審計。

qubyyang/awesome-ios-sim 解決的就是這個問題。它不新增模擬器能力,而是把「變更模擬器狀態」收進一條固定流程:

profile + current snapshot -> diff -> deterministic plan -> explicit confirmation -> audited apply

先有目標 profile 和當前快照,做 diff,生成確定性的有序操作計劃,顯式確認後才帶審計地執行。下面按功能、安裝、用法依次介紹。

這是什麼

awesome-ios-sim 的定位是 Simulator State as Code:通過確定性 Swift CLI 與 MCP stdio server,將 iOS 模擬器狀態捕獲、diff、規劃並安全應用爲可復現的版本化 profile。作者爲 qubyyang,MIT 許可證,當前項目狀態爲 alpha,狀態 schema 爲 v1alpha1。

它同時面向三類使用者:iOS 開發者、CI 流水線,以及 AI 智能體。

核心功能

一條固定流程:capture → diff → plan → 確認 → apply

模擬器設置被轉成可版本化的 JSON profile,可以和測試代碼一起提交到倉庫。任何變更都先離線生成計劃、審查後再應用,計劃是確定性的有序操作列表。

CLI 與 MCP server 共用同一套引擎

倉庫產出兩個可執行文件:ios-sim-state(CLI)與 ios-sim-state-mcp(MCP stdio server)。兩者共享同一 planner、校驗與 apply 門控,不會出現命令行和智能體各走一套邏輯的情況。

面向智能體的安全默認值

MCP 工具使用 JSON Schema 描述入參;simulator_apply 默認 dry-run,必須顯式確認纔會產生實際變更。

可複用的 layers 與 presets

內置 booted、clean-status-bar、shutdown 三個 preset,運行 ios-sim-state presets 可查看各自的描述。layer 只含可複用的 spec 字段,沒有 target。--layer 與 --preset 可以按需要疊加的順序重複傳入,應用到 compose、diff 或 plan。合併規則是確定的:標量後值覆蓋,application 按 bundleIdentifier 替換,preference 按 domain + key 替換,狀態欄字段按鍵合併。v1alpha1 沒有通用的 delete/tombstone 操作符,想卸載應用要用 presence: "absent"。

嚴格校驗與執行回執

profile 由 v1alpha1 JSON Schema 校驗,嚴格解碼,拒絕未知字段與空標識符。apply 之後,每條執行回執記錄實際執行的參數數組、退出碼、stdout、stderr 與時間戳;apply 在第一個失敗操作處停止。

只走公開 API,本地優先

所有變更僅通過 Apple 公開的 xcrun simctl 完成,不使用私有 CoreSimulator 框架。無守護進程、雲賬號、遙測或 API key。

安裝與啓用

先確認環境,再安裝。

系統要求

  • macOS 13 或更高版本;
  • Swift 6;
  • 完整 Xcode 及 iOS 模擬器 runtime(inventory、snapshot、apply 實際操作都需要);
  • xcode-select 指向目標 Xcode 安裝。

僅裝 Command Line Tools 可以構建,但不含 CoreSimulator/simctl,做不了實際操作。

Homebrew 安裝

brew tap qubyyang/awesome-ios-sim https://github.com/qubyyang/awesome-ios-sim
brew install qubyyang/awesome-ios-sim/awesome-ios-sim

在 Homebrew 尚未識別的 prerelease macOS 上,可能遇到 packages.*_dunno API 錯誤,可用源碼 tap 模式繞過:

HOMEBREW_NO_INSTALL_FROM_API=1 \
  brew install qubyyang/awesome-ios-sim/awesome-ios-sim

需要注意:初期 Release 歸檔(Apple Silicon/Intel)尚未代碼簽名或公證;下一個 tagged 發行版將進行 Developer ID 簽名與 Apple 公證,並改用 universal 歸檔。

源碼安裝

git clone https://github.com/qubyyang/awesome-ios-sim.git
cd awesome-ios-sim
swift build -c release

構建產物在 .build/release/ios-sim-state 與 .build/release/ios-sim-state-mcp。

作爲 dsh-plugin 安裝

npm 包 @qubyyang/awesome-ios-sim(版本 0.2.0-dev,OS 限 darwin,engines 要求 Node ^22.19.0 || >=24.0.0)導出 ./dsh-plugin,可作爲 dsh-plugin bundle 安裝到 DeepSeek Harness。README 的安裝一節沒有給出專門的 DSH 安裝命令,倉庫頂欄鏈接了 docs/DEEPSEEK_HARNESS.md 與 docs/MCP.md,DSH 集成的具體步驟以這兩份文檔爲準。

典型用法

以倉庫自帶示例爲例,走一遍完整流程。第一步列出運行時與模擬器:

swift run ios-sim-state inventory

輸出爲穩定的 JSON。第二步捕獲一臺模擬器的受管狀態:

swift run ios-sim-state snapshot --device <UDID> > simulator.snapshot.json

第三步把層與預設按順序疊加,生成完整的目標 profile:

swift run ios-sim-state compose \
  --profile Examples/ui-tests.profile.json \
  --preset clean-status-bar \
  --layer Examples/ui-tests.layer.json > simulator.composed.json

第四步離線生成確定性的有序操作計劃:

swift run ios-sim-state plan \
  --profile Examples/ui-tests.profile.json \
  --snapshot Examples/ui-tests.snapshot.json > simulator.plan.json

第五步預覽 apply 的行爲。不帶 --confirm 時默認 dry-run,不做任何變更:

swift run ios-sim-state apply --plan simulator.plan.json

經過上面的步驟審查計劃後,加上 --confirm 真正執行,並用 --journal 保留執行日誌:

swift run ios-sim-state apply \
  --plan simulator.plan.json \
  --confirm \
  --journal simulator.report.json

profile 本身長這樣(取自 README 示例):

{
  "apiVersion": "awesome-ios-sim/v1alpha1",
  "kind": "SimulatorState",
  "metadata": { "name": "ui-tests" },
  "target": {
    "name": "iPhone 17 Pro",
    "runtime": "com.apple.CoreSimulator.SimRuntime.iOS-27-0"
  },
  "spec": {
    "power": "shutdown",
    "applications": [
      {
        "bundleIdentifier": "com.example.app",
        "sourcePath": "/absolute/path/to/Example.app",
        "running": true,
        "launchArguments": ["--uitesting"]
      }
    ],
    "preferences": [
      {
        "domain": "com.example.app",
        "key": "hasSeenOnboarding",
        "value": false
      }
    ],
    "statusBar": { "time": "09:41", "batteryLevel": 100 }
  }
}

有安全默認值的字段可以省略。power: "unchanged" 會在臨時工作後恢復原電源狀態;計劃包含 erase 時,已啓動的設備會先關機;boot 操作會等待 simctl bootstatus -b 完成再執行後續步驟。statusBar 只接受公開的 simctl status_bar 覆蓋項,枚舉值與數值範圍在規劃前就會校驗。

適用場景與注意事項

適合兩類人:一是需要在 CI 或團隊中復現 iOS 模擬器測試環境的開發者,把 profile 和測試代碼一起提交即可;二是給智能體接模擬器能力的 DSH 插件作者,用帶 JSON Schema、默認 dry-run 的 MCP 工具替代裸 shell。

使用前注意:

  1. 項目處於 alpha 狀態,schema 爲 v1alpha1,後續可能變動;
  2. 應用含 erase 或移除應用操作的計劃前,務必人工審查;
  3. apply 在第一個失敗操作處停止,靠 journal 排查後續;
  4. 初期 Release 歸檔未簽名、未公證,對供應鏈有要求的團隊可以先走源碼構建。

另外提醒一點:這類插件會以當前 dsh 進程的權限運行,安裝前建議檢查源碼與許可證(本項目爲 MIT)。

結尾

awesome-ios-sim 做的事情不復雜:把模擬器狀態變成和代碼一樣可以提交、diff、審查的 profile,讓智能體和人在同一套流程裏操作,默認安全、事後可審計。目錄頁見 https://www.skillhub.cn/plugins/qubyyang/awesome-ios-sim,源碼見 https://github.com/qubyyang/awesome-ios-sim。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜