
simulator-use
app.nomac由 nomac.app 發布v0.15.2更新於 Nov 7, 2026
The iOS Simulator for coding agents: build Xcode projects, read the screen as text, tap by label.
發布方自己的服務:NoMac
概覽
讓編碼代理在 iOS 模擬器中建置並執行 Xcode 專案、以文字讀取畫面,並依標籤點擊、輸入與測試。
- 可以做什麼
- 建置、安裝並啟動 Xcode 專案,列出並選擇模擬器與裝置
- 以精簡文字行讀取應用程式畫面,可選擇截圖與全解析度 PNG
- 點擊、填寫、輸入、捲動、滑動、長按、設定滑桿並等待元素,每個步驟都會驗證
- 控制應用程式:啟動參數、權限、定位、推播、外觀、語言區域、StoreKit 測試購買
- 逐個案例執行單元與 UI 測試,讀取應用程式日誌、當機報告與螢幕錄影
- 為沒有 Xcode 的機器啟動、查看與停止雲端 iPhone
- 適用情境
- 適合需要端到端驗證 iOS 應用程式的情況:重現流程、檢查變更後的畫面、驅動 UI 測試,或不必人工點擊就產生 App Store 截圖。
- 執行需求
- 透過 npx 以 stdio 在本機執行,需要 Node 20 或更新版本,以及安裝 Xcode 與模擬器執行環境的 macOS。雲端模式需要登入 NoMac 帳號或設定 NOMAC_API_KEY 環境變數,並依分鐘計費;通道功能需要 Node 22 或更新版本。選用變數包括 SIMULATOR_USE_CACHE_DIR、SIMULATOR_USE_STATE_DIR 與 SIMULATOR_USE_MAX_BOOTED。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 simulator-use,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
simulator-use
The fastest, most token-efficient way for an AI agent to use the iOS Simulator. simulator-use gives Claude Code, Codex, Cursor and any other MCP client a phone: it builds and runs your Xcode project, reads the screen as a few lines of text, taps and types by label, and runs your tests case by case. Its own native engine talks to the Simulator directly, so reading the whole screen takes about 250 ms and a tap goes out in under a millisecond, where tools that start a helper for every call take 1.5 to 3 seconds. Free and open source (MIT), on any Mac with Xcode, and from Linux, Windows or a Mac without Xcode through a cloud iPhone.
- Fast: a whole-screen read in about 250 ms, a tap sent in under 1 ms, a screenshot in about 60 ms (measured on an M6 Mac mini, October 2026).
- Token-efficient: one line per element the agent can use, nothing else; a dozen tools with short descriptions.
- Complete: build, install, launch, XCTest and XCUITest per case, logs and crashes, video, permission prompts, in-app purchases, iPhone and iPad.
- Continuously improved: weekly releases driven by thousands of daily sessions.
- Anywhere:
npx simulator-use cloud startgives a cloud iPhone with Xcode to any machine.
It builds, runs and tests Xcode projects, reads and uses the screen of any app (SwiftUI, UIKit, React Native), answers iOS's permission prompts, reads the app's logs and crashes, and records video.
What the agent sees
- One line per element: kind, label,
#id(the app's accessibility identifier), state and@x,y, the center in points. - Groups, icons inside buttons, scroll bars, the status bar and the keyboard's keys are folded away. The tab bar, scrolling and the keyboard are one line each.
- Only what can be tapped is listed. An alert, a sheet, a menu or a full-screen view in front hides the screen behind it, and iOS's own permission prompts read as alerts over the app. Rows under the navigation bar, the tab bar or the keyboard are counted as hidden (above, below, to the left or right), not listed.
- A web view in UIKit (Capacitor, React Native's WebView, a sign-in page inside most apps) is read point by point, and its headings, texts, fields, checkboxes, buttons and links are listed like the rest. Web views hosted by SwiftUI, Safari's own pages, in-app browsers, maps, games and iOS's out-of-process pickers have nothing for accessibility to read. They come back as one
unreadableline with their place, so the agent knows to take a screenshot and tap by point. - A screenshot, when asked for, is sized to points, so a point in the picture is a point to tap.
screenshot_filesaves the screen at full resolution as a PNG for a person, a report or the App Store; in cloud mode it is saved on your machine too. Either waits for the screen to hold still (up to 2 s), so it shows the screen, not an animation into it. - The sign-in screen above is about 70 tokens. The full accessibility tree it comes from is about 40,000.
Using the screen
ui_act takes steps in the same words ui_look prints, runs them in order, and answers with what changed:
Steps:
Every step is checked, so nothing succeeds silently:
- Typed text is read back from the field. When iOS's autocorrect or smart punctuation changes it (
--to—,'to’), the text is pasted instead, which iOS takes as is. A field that still shows something else stops the call and says what it shows. - Text in any language (Café, 日本語, emoji) can be typed: what a US keyboard lacks goes through the Simulator's clipboard.
fillrefuses anything that isn't a text field, so keys never land in whichever field still has focus.- A tap that changes nothing is reported, after waiting 2.5 s for late answers such as a permission prompt. A tap inside an area that can't be read says it can't be checked.
- A target that isn't on screen yet gets two seconds to appear, then fails with the next step: "2 elements are below: scroll down", or, when an alert came up in front, "Answer it first: tap "Cancel" or "Open"".
- The first failing step stops the rest and returns the screen as it is now.
- A new screen comes back whole; otherwise only what changed.
Tools
The MCP server and the CLI are built from one list, so they always match. The tool list and instructions stay under 4,000 tokens; a test enforces it.
Build and run
app_run does the whole loop in one call: it finds the project (a workspace first, then a project, an XcodeGen spec, or ios/), picks the scheme, builds for the Simulator, installs, launches, and answers with the first screen.
The app's permissions are granted when it is installed and its first launch's prompts (notifications too) are answered, so no prompt stops the agent; permissions: "ask" keeps iOS's prompts, to test them. open_url answers iOS's "Open in …?" for a link that opens another app.
- A failed build answers with the errors only, as
Sources/App.swift:49:37: error: ..., and the path to the full log. - Each folder (each git worktree) builds into its own DerivedData, so rebuilds are incremental and worktrees never share products.
SIMULATOR_USE_CACHE_DIRputs it on a disk you keep, so the next machine's build is incremental too. - An XcodeGen project is regenerated from
project.ymlbefore each build (skipped when nothing changed), so new files are always in it. - The next call in the same folder needs no arguments.
env: "API_URL=http://127.0.0.1:8080 MODE=test"gives the app those variables (it reads them fromProcessInfo), as an Xcode scheme does; they stay for its later launches, andenv: ""clears them.- An MCP call answers within 40 s; a longer build answers with a job, and
job_statuswaits for it. From the CLI,simulator-use runsimply waits. - Two builds of one project never run at once, also from two processes: the second says which process is building it.
- Expo, React Native, Flutter and Capacitor builds are not done yet; build them with their own tools, then
app_control install.
Tests
tests_run runs the scheme's tests and reads the answer from Xcode's result bundle, not from the scrolling output:
- XCTest and Swift Testing both.
- Each failing test is named the way
onlytakes it, to rerun just that one. - "0 tests ran" (no test target, or a filter that matched nothing) is an error, never a pass.
In-app purchases
The App Store's sandbox cannot complete a purchase in a Simulator (Apple: purchases there need a device; signing in fails with AMSErrorDomain). StoreKit Testing can, and app_control storekit applies the app's .storekit file the way Xcode's Run does, with no Xcode window and no change to the app:
- Products, purchases, subscriptions and renewals are local (environment
Xcode), with no Apple Account. - Applying starts from the file's state: its products, no purchases. Purchases complete without iOS's purchase sheet, which is not in the app's accessibility tree.
- It lasts until the app is removed: building and installing over it keeps it.
- A relative path is looked up here, then in the folder of the project
app_runbuilt last (on a cloud phone, the uploaded project).
Any screen, and its screenshot
An app opens any screen without tapping through it when it reads launch arguments: -Key value sets Key in UserDefaults for that launch only, like the "Arguments Passed On Launch" of an Xcode scheme.
- The words after the app are its arguments, quoted as in a shell:
-Greeting "Hello there".valuetakes them the same way, and the app defaults to the one launched last. launchanswers once the app is in front and its screen settled, and a screenshot waits for the picture to hold still (up to 2 s: a spinner never does, and the answer says so), so it shows the screen asked for, not the launch.- Launch arguments are the app's process arguments, which every user of a Mac can read: a secret goes in
app_run'senv, which only the app sees. - A set of screens is a loop:
iPhone apps on an iPad
App Review runs iPhone apps on an iPad, where iPadOS draws them in a window, moved and scaled. ui_look says so in a line of its own, and gives every position in the iPad's screen points, as taps and screenshots use them; a tap beside the window is reported as landing outside it. Use an iPad Air Simulator for this: on iOS 27.0 an iPad Pro 11-inch (M5) Simulator crashes its display server (backboardd) when an iPhone-only app opens, also without simulator-use, and the app is gone with it.
Logs and crashes
app_logs shows what the app itself said, not the thousands of lines Apple's frameworks log from inside it:
- Its
print()output, kept from the momentapp_controllaunches it. - Its own system log lines (its subsystem, or logged by its own code), streamed from launch. macOS keeps info lines only in memory and drops them within seconds when the Simulator is busy, so reading the log store afterwards misses them.
grepalso searches Apple's lines, for things like a missing image or a layout warning.wait_forwaits up to 25 seconds for a line, for example after a tap that starts a network call.crasheslists crash reports with the crashing thread down to your code (ItemsView.body.getter (App.swift:64)), next to the app's last output, which holds Swift's own message (App.swift:64: Fatal error: ...). macOS can take up to a minute to write a report.
Several agents, one Mac
- Each agent runs its own MCP server and holds its own Simulator through
device_use, and its own cloud phone: one agent'scloud startnever moves another's tools, itscloud stopnever ends another's phone, and the phone stops when the agent's server ends. Acloud starttyped in a terminal is the command line's own. - Boots never overlap, across every simulator-use process on the Mac: two Simulators booting at once on an 8 GB Mac pushed it into swap for minutes.
SIMULATOR_USE_MAX_BOOTEDcaps how many run at once; asking for another shuts down the others first.- Steps on one Simulator run one at a time, across every simulator-use process on the Mac, so two agents' or two commands' taps never interleave.
One command at a time
Agents that run simulator-use through a shell, a command per call, get the same tools:
simulator-use useis remembered: the next command uses that Simulator, also with several booted.SIMULATOR_USE_STATE_DIRmoves simulator-use's files (default: simulator-use in the temporary folder).- Each command waits for its own work, so there is no job to follow.
simulator-use call <tool> '<json>'calls a tool by its MCP name and prints one line of MCP content,{"content":[...],"isError":true}on failure, images as base64:
What it can't do yet
- Read web views hosted by SwiftUI, Safari's pages, in-app browsers, Flutter or game canvases: it says so, and a screenshot plus tap by point works.
- Real devices, Android, rotating to landscape, pinch and multi-touch.
- Reading text an app hides from accessibility: some React Native apps set a test id as the label, and the read says when labels look like that.
Install
Support: GitHub issues or [email protected]. Privacy policy: https://nomac.app/privacy (the local tools send nothing anywhere; cloud mode runs on NoMac).
Needs macOS with Xcode and a Simulator runtime, and Node 20 or newer.
No Mac? If your agent works on Linux, Windows or in a cloud sandbox, NoMac gives it a real Mac in the cloud, with Xcode and the iOS Simulator, billed per minute.
Claude Code also takes it as a plugin: /plugin install simulator-use --marketplace NoMac-app/simulator-use. Gemini CLI as an extension: gemini extensions install https://github.com/NoMac-app/simulator-use. Clients of the open Agent Plugins format (Kiro and others) read plugin.json and mcp.json at the root.
Cursor, Windsurf, VS Code and other clients that take a JSON config:
Any other client: run npx -y simulator-use mcp as a stdio server. It speaks MCP 2024-11-05 through 2026-07-28.
Agents that work from a shell can use the CLI instead; skill/SKILL.md in the package teaches it in under 2 KB.
From a shell: npx simulator-use look.
Cloud
Where this machine can't run the Simulator (Linux, Windows, a cloud agent), or for CI, the same tools run on a cloud iPhone Simulator on NoMac, a Mac with Xcode, billed per minute:
Only the files the phone lacks are sent (a one-file change sends one file), into the account's own encrypted workspace, kept between sessions so builds stay incremental; build output and dependencies stay behind. Only files changed since the last send are read again (an index in simulator-use's state folder; SIMULATOR_USE_SYNC_INDEX=0 reads every file). A CocoaPods project builds there too: pod install runs on the phone's host before the build when the pods are not the ones Podfile and Podfile.lock name, keeping the lock's versions, and the next build skips it. The cloud tool does the same over MCP.
cloud start answers a link for a person to watch the phone in a browser and one to use it. cloud stop answers the session's replay: the screen as a video beside every call (typed text left out), kept for 7 days. cloud run saves that video in its --out folder (made if missing) beside the screenshot.
An app that talks to a backend on your machine reaches it through a tunnel (Node 22 or later):
The answer says the address the phone's apps use, such as http://127.0.0.1:20199; point the app there, for example with run --env "API_URL=http://127.0.0.1:20199". Each request that passes is listed with its status and time (cloud tunnel without a port shows them over MCP). It lasts while the phone runs and comes back by itself after a dropped connection; cloud tunnel with port 0 closes it. While it is open, anything on the phone reaches that port: its apps, pages in its Safari and your project's build; nothing outside the phone does.
On GitHub, from any runner, with the result posted on each pull request and the screenshot and recording kept as artifacts:
It runs the simulator-use of its own tag (@v0.12 runs what that tag holds; version picks another). path is the project's folder, scheme the scheme when the project has several, and tests: false skips the tests (a project without a test target fails otherwise: zero tests is not a pass). A cancelled run stops its phone, and a pull request from a fork, which gets no secrets, fails with that reason. A job's log and its pull request comment can be public, so in CI (CI or GITHUB_ACTIONS set) cloud run prints no link that opens without signing in: files it links are kept in the run's artifacts, and the replay's link is read with the account's key (GET https://nomac.app/api/v1/simulator/sessions/{id}, links.replay).
Privacy
simulator-use sends nothing unless cloud mode is on. There is no telemetry and no network access at runtime: it runs xcrun simctl, the bundled AXe binary and sips, all on your Mac. With cloud on, it sends the project being run or tested, and the tools' calls, to NoMac, which keeps the session's replay for 7 days. The project is the git repository it is in, as the files git tracks or would track (what .gitignore leaves out stays on your machine), or its folder when it is in none; either way never build output, dependencies, editor state or key and credential files (.env files but their examples, .p8, .p12, .pfx, .pem, .key, provisioning profiles, keystores, SSH keys, .netrc), even when git tracks them.
How it works
simulator-use reads the Simulator through a small native engine (native/engine), one process per Simulator, built on the frameworks of AXe (MIT), which is bundled at a pinned version with its checksum checked at packaging, and through xcrun simctl. The engine keeps the Simulator's input, its accessibility session and its screen buffer open, so a tap takes a millisecond, a whole screen a few hundred, and a step waits until the pixels stop changing instead of a fixed time. It reads web views point by point. When the engine can't run, AXe does the same work one process per call. There is no test runner to build, so the first call is as fast as the rest.
Develop
The engine builds only with the Swift that built AXe's frameworks: for AXe 1.8.0, Swift 6.3.2, which is Xcode 26.5 (build 17F42), the Xcode releases are built with. npm run native checks the compiler first; with another Xcode selected, set DEVELOPER_DIR to Xcode 26.5's Contents/Developer. The build is reproducible: from a fresh clone of a release tag, in any folder, with Xcode 26.5, the binaries match the published package byte for byte, signature included. sha256, checked October 30, 2026:
examples/swiftui-demo is the sample app the tests' screens come from. scripts/golden.sh builds it, runs it on a Simulator and checks 19 golden tasks: build and launch in one call, sign in, toggle, open an item, back and scroll, the app's logs, a crash, a build error and a failing test as file:line, a video, and a wrong password that must fail loudly.
examples/edge-lab is an app with every awkward screen: segments, steppers, sliders, menus, alerts, sheets, full-screen covers, permission prompts, text in any language, autocorrect, late content, toasts, swipe-to-delete, long press, a web view, UIKit and a deep link. scripts/lab.sh builds it and runs 26 checks on it.
SIMULATOR_USE_DEBUG=1 prints every step and every program run with its time.
Made at NoMac
simulator-use is built at NoMac, where AI agents rent real Macs in the cloud to build, run and test Apple apps. It comes from thousands of agent runs on those Macs: where agents get stuck, what they misread on screen, and what they need to be told to keep going.
When simulator-use can't run where it is (no Mac, no Xcode, no Simulator runtime), its error names NoMac as a place to get one. It never shows when simulator-use works, and SIMULATOR_USE_NO_CLOUD_HINT=1 hides it.
License
MIT. AXe and the IDB frameworks it includes are MIT too; see THIRD_PARTY_LICENSES.
來源:README.md,提交 ae67d6b
工具
0版本歷史
3- v0.15.2最新Nov 7, 2026
- v0.15.1Nov 3, 2026
- v0.12.2Oct 26, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分
其他 Nomac 整合
NoMac
app.nomac官方發布者
Cloud iPhones and Macs with Xcode for AI agents: build, run and test iOS apps, use the screen.
NoMac Session
app.nomac官方發布者
遠端 MCP 端點,為 AI 助理提供搭載 Xcode 的雲端 Mac:執行指令、建置與測試專案、操作螢幕。
NoMac Simulator
app.nomac官方發布者
Cloud iPhone Simulators for AI agents: build the Xcode project, read the screen, tap by label, test.
NoMac App Store
app.nomac官方發布者
遠端 MCP 端點,讓 AI 助理在 NoMac Mac 上完成 iOS App 簽署、TestFlight、App Store 中繼資料、截圖與 App 審查。
NoMac (all tools)
app.nomac官方發布者
NoMac 的遠端伺服器,把 Mac、雲端 iPhone 與 App Store 的所有工具整合成一個需 OAuth 驗證的端點,供 AI 助理使用。