dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
把官方 ZCode ios-simulator 插件移植为 DSH 原生工具:原有 20 个 ios_* 工具的命名与参数保持不变,另加 ios_shutdown_simulator,覆盖 Xcode 工程发现与生成、模拟器启动与关闭、构建、安装、启动与结束进程、截图、日志读取,并提供应用内设置页与可选的 idb UI 自动化。仅支持 macOS。
English | 简体中文
A DeepSeek Harness (DSH) native port of the official ZCode ios-simulator@0.1.0 plugin: all 20 original MCP tools preserved as native DSH tools, plus a parameter page on the plugin's own detail page in the Plugins panel (Plugins → Installed plugins → iOS Simulator Helper) that edits the simulator parameters in-app instead of through environment variables.
ios_simulator MCP server keep working; one tool is added — ios_shutdown_simulator, because the original could boot a simulator but never stop one.IOS_SIM_* variable, then to the built-in default.spawn xcrun ENOENT, while ios_preflight reports the failing host check and ios_discover_project, ios_create_app and ios_ui_status still answer.@zhz8888/dsh-ios-simulator-helper; the plugin page shows iOS Simulator Helper / iOS 模拟器助手 from locale/ rather than the raw package name, and both descriptions say the plugin is unofficial and not affiliated with Apple.On a Mac with full Xcode, at least one iOS runtime and DSH installed:
Install the plugin
dsh plugin --profile <profile> add @zhz8888/dsh-ios-simulator-helper
In DSH Desktop, open Plugins and add the same package name there. Reload or restart DSH afterwards.
Check the machine — open Plugins → Installed plugins → iOS Simulator Helper and press Run diagnostic. It runs exactly the checks ios_preflight runs (full Xcode, a simulator runtime, idb), and prints a fix for anything missing.
Use it — ask for what you want ("build and run this project on the iPhone 16 simulator", "screenshot the running app"), or call the 21 ios_* tools directly. Everything the tools need is editable on that page.
| Dependency | Notes |
|---|---|
| macOS | The only supported host. xcrun simctl, xcodebuild and the simulator window app exist nowhere else. |
| Full Xcode | xcode-select -p must point at Xcode.app/Contents/Developer; Command Line Tools alone are not enough. |
| An iOS Simulator runtime | At least one iOS/iPadOS runtime installed from Xcode → Settings → Platforms. |
| Node.js ≥ 22 | The DSH host runtime. |
idb (optional) | Needed only by the ios_ui_* tools. Without it, build/run/screenshot/logs are unaffected. |
ios_preflight checks every item above and prints a fix for each failure; the parameter page's "Run diagnostic" button runs the same checks.
dsh plugin --profile <profile> add @zhz8888/dsh-ios-simulator-helper
DSH Desktop: the desktop profile belongs to the Electron app — open Plugins, add @zhz8888/dsh-ios-simulator-helper there, and enable the row it creates. After a reload or restart the form is at Plugins → Installed plugins → iOS Simulator Helper; it only appears while the host half actually serves this plugin's settings namespace.
The published tarball contains everything the plugin needs — the host half, the browser bundle, the bundled skill and the locale/ entries — and nothing is compiled at install time, so no build approval step is involved. @deepseek-ai/cordis, @deepseek-ai/dsh-tools and @deepseek-ai/schemastery are peer dependencies provided by the harness, so the plugin pulls in no second copy and has no runtime dependencies of its own; DSH's compatibility gate compares the @deepseek-ai/dsh* peer ranges against the running version and refuses to install on a mismatch.
Mount the package exactly once.
dsh plugin addrecords the row indsh.profile.bundles; adding a second row for the same package in the profile's owncordis.patch.ymlregisters every tool name twice and fails at the loader.
dsh plugin --profile <profile> add @zhz8888/dsh-ios-simulator-helper@latest # upgrade
dsh plugin --profile <profile> remove @zhz8888/dsh-ios-simulator-helper # uninstall
Settings live in the profile, not in the package, so both commands leave them in place. The data directory (by default $DSH_HOME/ios-simulator-helper) holds screenshots, build logs and DerivedData; it is yours to delete, and uninstalling does not touch it.
The DSH compatibility range is >=0.2.1-rc.2, a lower bound only, declared identically in peerDependencies, engines.dsh and dsh.compatibility.dsh: a runtime below it is refused at install time, and no future harness release is excluded.
One node-semver detail survives — a new tuple's prerelease such as 0.2.2-alpha.1 is not admitted by npm's and pnpm's default rules, so that install fails until either the range gains a branch for the tuple (">=0.2.1-rc.2 <0.2.2-0 || >=0.2.2-0") or the peer check is skipped:
dsh plugin --profile <profile> add @zhz8888/dsh-ios-simulator-helper \
--config.strict-peer-dependencies=false
Stable releases (0.2.1, 0.2.2, 0.3.0, 1.0.0, …) are unaffected and always admitted.
The settings namespace equals the profile patch row id equals ios-simulator-helper (also dsh.name). The form registers with the Plugins page's plugins.bundle.config slot, keyed by the package name, so it renders inside the plugin's detail page in the Plugins panel instead of in the Settings dialog; it exists only while the host half serves that namespace. It reads and writes through ctx.configForms, so staged edits, dirty detection, inline validation, optimistic concurrency (revisions) and "overridden / reset to default" all come from the harness. The detail page draws the plugin's title, icon and description; the form contributes one line saying when an edit takes effect, one card per category — built from the same field kit as the built-in settings pages (@deepseek-ai/dsh-client-ui-primitives) — and the save bar. The three timeouts are entered in whole seconds, while the legacy IOS_SIM_*_MS variables are still read in milliseconds and converted.
Saving happens in a pill that sticks to the bottom of the form: it appears while edits are staged (or a write is in flight, or one failed), names that state next to a status dot, and carries Discard changes and Save (disabled while a draft is invalid). A draft that merely puts a control back to the value already in effect counts as no edit at all, a confirmation toast reports a write that landed, and leaving the page discards staged edits.
| Group | Field | Type | Default | Legacy env fallback | Notes |
|---|---|---|---|---|---|
| Simulator and device | defaultDevice | text (suggestions from this machine) | iPhone 16 | IOS_SIM_DEFAULT_DEVICE | Device-name fragment used when a tool names no udid/device; falls back to the first available iPhone on a miss. |
defaultRuntime | text (suggestions from installed runtimes) | empty | IOS_SIM_DEFAULT_RUNTIME | Runtime fragment such as iOS-27; empty matches any. A preference, not a requirement: a stale value widens the pool instead of erroring. | |
autoBootSimulator | switch | on | IOS_SIM_AUTO_BOOT | When off, tools fail instead of running simctl boot for a stopped target. | |
autoOpenSimulator | switch | on | IOS_SIM_AUTO_OPEN | Matches the original by opening the Simulator window (boot / show / open URL / build and run); off keeps everything headless. | |
bootTimeoutSeconds | integer | 120 | IOS_SIM_BOOT_TIMEOUT_MS (ms) | Longest wait for one simctl boot / bootstatus, in seconds. The legacy variable keeps its millisecond spelling and is converted. | |
| UI automation | uiBackend | select | auto | IOS_SIM_UI_BACKEND | auto probes for idb; idb requires it; none disables the UI tools; xcodebuildmcp is reserved. |
idbBinary | text | idb | IOS_SIM_IDB_BINARY | Command name or absolute path of idb. | |
uiTimeoutSeconds | integer | 60 | IOS_SIM_UI_TIMEOUT_MS (ms) | Longest runtime of one idb UI command, in seconds; the legacy variable is milliseconds. | |
| Build and DerivedData | defaultConfiguration | text | Debug | IOS_SIM_CONFIGURATION | Used when a tool names no configuration. |
buildTimeoutSeconds | integer | 600 | IOS_SIM_BUILD_TIMEOUT_MS (ms) | Longest runtime of one xcodebuild build, in seconds; the legacy variable is milliseconds. | |
extraBuildArgs | multiline | empty | IOS_SIM_EXTRA_BUILD_ARGS | One argument per line, # starts a comment; inserted after -derivedDataPath and before build. | |
derivedDataDir | text | empty | IOS_SIM_DERIVED_DATA_DIR | Empty uses <data dir>/DerivedData/<project fingerprint>. | |
disableCodeSigning | switch | on | IOS_SIM_DISABLE_CODE_SIGNING | The original always passed CODE_SIGNING_ALLOWED=NO; off lets Xcode decide. | |
| Logs | logSeconds | integer | 120 | IOS_SIM_LOG_SECONDS | Recent seconds ios_logs reads when the call names no window; capped at 3600. |
logLimit | integer | 20000 | IOS_SIM_LOG_LIMIT | Largest rendered log ios_logs returns when the call names no limit. | |
| Output directories | dataDir | text | empty | IOS_SIM_PLUGIN_DATA | Root for screenshots, build logs and DerivedData; empty uses $DSH_HOME/ios-simulator-helper, then ~/.dsh/ios-simulator-helper. |
screenshotDir | text | empty | IOS_SIM_SCREENSHOT_DIR | Empty uses <data dir>/screenshots. |
Below the form sit the host check and two buttons:
GET /api/ios-simulator-helper/host; the host wins on a conflict. When the host is unsupported — or the host never answered and the browser itself is non-macOS — a red notice titled "This plugin only supports macOS" appears above the form and names the detected platform.GET /api/ios-simulator-helper/status, the same checks ios_preflight runs, listed one by one with status, detail and fix.GET /api/ios-simulator-helper/inventory, which discovers the Xcode path and version, the macOS version, simulators, runtimes and the resolved default target, to fill the fields' suggestion lists.The original plugin's userConfig (default_device, ui_backend) and its environment variables IOS_SIM_DEFAULT_DEVICE, IOS_SIM_UI_BACKEND and IOS_SIM_PLUGIN_DATA still work as fallbacks (last column above), so an existing ZCode or CI setup needs no change. The original's IOS_SIM_PACKAGE_ROOT only located the plugin for its own MCP launcher; DSH resolves the package path directly and does not need it.
All four are the live page in DSH harness 0.2.1-rc.2, in the order you scroll it — nothing is mocked up. They show the form inside the plugin's own detail view in the Plugins panel, the 1.1.0 card layout and the timeouts in whole seconds; the save bar only appears while an edit is staged, so it is not in these shots. The window ran the Chinese locale, so the card headings are Chinese while every field name is the same in both languages.
1. Simulator and device — the plugin heading and description, then the fields every ios_* call reads:

2. UI automation and builds — the idb backend and its timeout, then the xcodebuild configuration, build timeout and extra arguments:

3. Build tail and logs — the DerivedData directory and the code-signing switch, then the ios_logs window and character limit, and the start of the output directories:

4. Output directories and the host check — where screenshots, logs and DerivedData land, then the macOS verdict with the two detection buttons:

screenshots.json lists these four files in this order next to package.json in the repository, which is how a plugin market finds them.
21 tools: the original 20 with identical names and arguments, plus one addition.
| Tool | Purpose |
|---|---|
ios_preflight | Check the host (macOS), Xcode, xcodebuild, simctl, runtimes, simulators and the UI backend, and echo the current settings. |
ios_list_simulators | List iOS/iPadOS simulators and installed runtimes. |
ios_boot_simulator | Boot the selected simulator, optionally opening the Simulator window. |
ios_show_simulator | Open the simulator window app — Simulator.app on Xcode 25 and earlier, Device Hub on Xcode 26 and later — optionally focused on one UDID. |
ios_shutdown_simulator | Added: shut the selected simulator down (simctl shutdown); already-stopped is a success, not an error. |
ios_discover_project | Find .xcodeproj/.xcworkspace, schemes and bundle ids. |
ios_create_app | Generate a minimal SwiftUI project (refuses to overwrite generated files by default). |
ios_build_app | Build the iOS Simulator product with xcodebuild. |
ios_build_and_run | Build → install → launch → show. |
ios_install_app | Install a .app on the selected simulator (absolute paths allowed). |
ios_launch_app | Launch by bundle id. |
ios_terminate_app | Terminate by bundle id. |
ios_open_url | Open a URL in the simulator. |
ios_screenshot | Capture a PNG to disk, and return it as an image when the model accepts image input. |
ios_logs | Read log show output, optionally filtered by bundle id. |
ios_ui_status | Report UI-automation availability and the backend the settings selected. |
ios_ui_tap / ios_ui_swipe / ios_ui_type_text / ios_ui_button / ios_ui_describe | idb-backed tap / swipe / typing / hardware button / accessibility tree. |
Two behaviours deserve their own note:
ios_screenshot always writes the PNG to disk (under <data dir>/screenshots/ by default) and additionally submits it to the host's attachment service for a canonical image block. When the current model declares no image input, or the deployment stores no attachments, the result degrades to text plus the file path instead of failing the call.ios_build_and_run resolves the bundle id in four steps — a fix over the original, which asked xcodebuild -showBuildSettings alone and, in a restricted environment, silently returned undefined after a successful build: explicit bundleId argument → CFBundleIdentifier of the .app that was just built (read with plutil, i.e. the value simctl installs) → -showBuildSettings with the same -derivedDataPath → identifiers found in project.pbxproj. The winner is reported as bundleIdSource.ios-dev skill — shipped in skills/ios-dev/ and registered by the host half through ctx.skills.register() as an embedded skill with the skill directory as its resourceBase. Rewritten for DSH: no mcp__… prefix, environment configuration points at the plugin's configuration page, and the macOS precondition plus the "shut the simulator down when you are done" step are spelled out./ios-dev [goal] command — registered through ctx.commands.register(). DSH user commands deliberately never create a model message, so this command does the one thing that is useful without the model: it runs the environment diagnostic and prints the verdict, the failing checks and their fixes.| Aspect | Original (ZCode) | This plugin (DSH) |
|---|---|---|
| Tool exposure | stdio MCP server ios-simulator; the model sees mcp__ios_simulator__* | Native ctx.tools.register(); the model sees ios_* |
| User configuration | plugin.json userConfig (2 items), injected as environment variables | Configuration page with 17 fields on a schemastery Config, all .volatile(); the old environment variables remain as fallbacks |
| Host check | process.platform read once, inside ios_preflight | Centralised requireMacOS() in front of every Apple-tooling call, plus the configuration page's synchronous and authoritative verdicts |
| Working directory | process.cwd() | exec.agent.session.header.cwd (the session workspace) |
| Data directory | IOS_SIM_PLUGIN_DATA / temp | $DSH_HOME/ios-simulator-helper, configurable on the configuration page |
| Path safety | inside(cwd, path) refuses escapes | Same semantics, split into read-only paths (an absolute .app is fine) and write targets (the session workspace or the plugin's own output roots, so a path the tool reported absolute can be passed straight back) |
| Screenshot result | MCP image content (base64) | An image block built from a host attachment reference, degraded to text plus a disk path on refusal |
| Result normalisation | Providers return objects containing undefined | Every tool result passes through toLosslessJson() (the registry rejects undefined) |
| Slash command | Injects a prompt into the model's conversation | Runs the diagnostic and prints the verdict |
| Process invocation | node:child_process spawn | Unchanged |
ios_preflight fails the Host OS (macOS) check and skips the remaining probes instead of producing meaningless spawn failures; every tool that drives Apple tooling refuses, ios_discover_project, ios_create_app and ios_ui_status still answer, and the configuration page keeps the notice at the top.ios_ui_* needs idb; ios_ui_status explains what is missing. xcodebuildmcp is only a reserved value (matching the original's reservedBackends) and is not implemented.ios_build_and_run always opened the Simulator window; here that is the autoOpenSimulator setting (on by default, so behaviour matches). ios_build_app and ios_screenshot still do not open windows, as in the original. The window app is Simulator.app on Xcode 25 and earlier and Device Hub on Xcode 26 and later; a window that cannot be opened is reported in the result (opened: false plus openWarning) and never fails the simctl steps.ios_logs reads log show (no live stream), with a configurable and clamped window and length.@State, #Preview) need swift-plugin-server, which cannot start its nested sandbox-exec when the caller is itself sandboxed. ios_build_app then retries the build once with OTHER_SWIFT_FLAGS=-disable-sandbox and reports macroSandboxRetry: true; a caller that was never sandboxed never sees a retry.project.pbxproj, objectVersion = 56) and does not track newer Xcode templates.desktop profile, and the four shots in assets/ are the latest manual pass, top to bottom. Dark theme, narrow-width wrapping and the non-macOS notice are still covered by the render tests, not by eye.Every release is one commit in two places: tagged vX.Y.Z on main and published to npm from that tag, whose SHA npm records as gitHead. The list is at Releases — v1.2.0 is the latest, dated 2026-10-23, after v1.1.3 dated 2026-10-20, v1.1.2 dated 2026-10-19, v1.1.1, v1.1.0 and v1.0.0, the last three dated 2026-10-17.
Issues and pull requests are welcome at github.com/zhz8888/dsh-ios-simulator-helper. Every change has to keep pnpm check green — unit tests, a host/client consistency gate and a mount on a real Cordis host — and there is no CLA or form to fill in: a focused pull request that says what it changes and why is enough.
The package is shaped for the awesome-dsh-plugin market. Development conventions — commands, invariants, testing, commit and release rules — live in AGENTS.md.
MIT, copyright (c) 2026 zhz8888. Tool definitions, provider logic and the generated SwiftUI project template are ported from the ZCode official ios-simulator plugin, distributed under the MIT License by Z.ai; the template sources are kept verbatim. See the attribution at the end of LICENSE.