feat(simctl): Add clone, create, and delete simulator management commands#418
feat(simctl): Add clone, create, and delete simulator management commands#418yjmeqt wants to merge 5 commits into
Conversation
…ands Wraps xcrun simctl clone, create, and delete as MCP/CLI tools, registered under the simulator-management workflow. Co-Authored-By: deepseek v4 pro <noreply@anthropic.com>
Use NonStreamingExecutor pattern with SimulatorActionResultDomainResult, add action types to domain-results and renderer labels. Co-Authored-By: deepseek v4 pro <noreply@anthropic.com>
Co-Authored-By: deepseek v4 pro <noreply@anthropic.com>
commit: |
| const command = ['xcrun', 'simctl', 'clone', params.sourceSimulatorId]; | ||
| if (params.newName) { | ||
| command.push(params.newName); | ||
| } |
There was a problem hiding this comment.
Bug: The clone_sims tool incorrectly treats the newName parameter as optional, causing the underlying simctl clone command to fail if it's not provided.
Severity: HIGH
Suggested Fix
Make the newName parameter required in the Zod schema for the clone_sims tool. This ensures that the simctl clone command is always constructed with the required name argument, preventing runtime errors.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: src/mcp/tools/simulator-management/clone_sims.ts#L79-L82
Potential issue: The `clone_sims` tool defines the `newName` parameter as optional and
constructs the `simctl` command to only include the name if provided. However, the
underlying `xcrun simctl clone` command requires a name as a positional argument. If the
tool is called without `newName`, the executed command `xcrun simctl clone <device>` is
incomplete, which will cause `simctl` to exit with a "Missing argument" error.
- Fix publicSchemaObject to not omit non-session-default params - Capture new simulator UDID from simctl clone/create stdout - Allow shutdownFirst for delete_sims with target=all - Add tests for clone, create, and delete tools Co-Authored-By: deepseek v4 pro <noreply@anthropic.com>
…on-result schema Co-Authored-By: DeepSeek V4 Pro <noreply@deepseek.com>
| artifacts: { | ||
| simulatorId: params.clonedSimulatorId ?? params.sourceSimulatorId, | ||
| }, |
There was a problem hiding this comment.
Bug: When a simulator clone fails, the structured output incorrectly reports the source simulator's ID as the resulting artifact instead of omitting the artifacts field.
Severity: MEDIUM
Suggested Fix
Modify the result creation to conditionally include the artifacts object only when params.clonedSimulatorId is present. This can be achieved using conditional spreading, similar to the implementation in create_sim.ts: ...(params.clonedSimulatorId ? { artifacts: { simulatorId: params.clonedSimulatorId } } : {}).
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: src/mcp/tools/simulator-management/clone_sims.ts#L54-L56
Potential issue: In `clone_sims.ts`, when a simulator cloning operation fails, the
`createCloneSimsResult` function incorrectly constructs the structured output. Because
`params.clonedSimulatorId` is `undefined` on failure, the null-coalescing operator
(`??`) causes `artifacts.simulatorId` to fall back to `params.sourceSimulatorId`. This
results in a misleading output that incorrectly identifies the source simulator as the
artifact of the failed operation. This behavior is inconsistent with other tools like
`create_sim`, which correctly omit the `artifacts` field on failure, and could cause
automated clients to operate on the wrong simulator.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4f8fef6. Configure here.
| import { createBasicDiagnostics } from '../../../utils/diagnostics.ts'; | ||
|
|
||
| const baseSchemaObject = z.object({ | ||
| sourceSimulatorId: z.string().uuid().describe('UDID of the simulator to clone'), |
There was a problem hiding this comment.
Deprecated z.string().uuid() used instead of z.uuid()
Medium Severity
clone_sims.ts uses z.string().uuid() for sourceSimulatorId, but the project uses Zod v4 ("zod": "^4.0.0") where z.string().uuid() is deprecated. Every other simulator tool in the codebase (erase_sims, reset_sim_location, set_sim_appearance, set_sim_location, sim_statusbar) uses z.uuid() instead. Beyond the deprecation, z.uuid() enforces stricter RFC 4122 validation, so this inconsistency means clone_sims may accept UUIDs that other tools would reject, creating confusing behavior differences.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 4f8fef6. Configure here.


Summary
clone_sims(xcrun simctl clone) — clone an existing simulatorcreate_sim(xcrun simctl create) — create a new simulatordelete_sims(xcrun simctl delete) — delete by UDID, all, or unavailable simulators (withshutdownFirstoption)simulator-managementworkflowCloses #414
Test plan
npm run buildsucceeds