Skip to content

Development ​

Commands ​

CommandWhat it does
npm run buildBuilds into dist/.
npm run typecheckType-checks src/ and test/.
npm run lintRuns ESLint with type-aware rules.
npm run formatFormats the code with Prettier. format:check only verifies.
npm testBuilds and runs the unit and end-to-end tests. They need no Mac.
npm run test:watchRuns the tests in watch mode while you develop.
npm run test:integrationTests against a real simulator. macOS only; they boot a device.
npm run docs:devServes this documentation locally.
npm run docs:buildBuilds the static site.
npm run docs:toolsRegenerates the tool reference from the server, in both languages.

Tests ​

npm test runs five groups of tests, none of which need a Mac:

FolderWhat it testsWhat is replaced
test/domain/Model, element queries, errors.Nothing: it is pure code.
test/application/The rules of each service: cache, waiting, validation, sequences, pasting, scrolling.The ports, by in-memory implementations.
test/infrastructure/The commands each gateway builds and how it parses their output.Command execution.
test/mcp/The whole server through a real MCP client, in memory.Command execution and the clock.
test/process/The compiled binary, started as a process and driven over stdio.Nothing.

npm run test:integration adds another level: it boots a real simulator and runs the tools against it. It is what proves that the commands the other tests expect are commands the real tools accept. It has two suites:

  • simulator.integration.test.ts uses the apps that ship with iOS.
  • fixture.integration.test.ts installs a small SwiftUI app from test/fixtures/app/, built with swiftc and no Xcode project, and asserts on what it shows after typing, pasting, scrolling, opening a deep link or receiving a push. It also records timings and response sizes. It needs the FIXTURE_APP variable:
bash
FIXTURE_APP="$(bash test/fixtures/app/build.sh | tail -n 1)" npm run test:integration

The UI tests are skipped when idb is not installed.

Continuous integration runs linting, npm test on Ubuntu and macOS with Node 20 and 22, and the integration tests on a macOS runner with idb installed.

Test utilities in test/support/:

  • Harness: an MCP client connected to the whole server, with fake commands and a fake clock.
  • FakeCommandRunner: records commands and answers with canned output or failures.
  • FakeClock: a clock that only advances when the code sleeps.
  • fakes.ts: in-memory implementations of every domain port.

Adding a tool ​

  1. If a new capability is needed, add it to the matching port in src/domain/ports/ and implement it in its gateway in src/infrastructure/.
  2. Expose the use case in the service in src/application/.
  3. Declare the tool in the ToolProvider in src/mcp/tools/:
ts
defineTool({
  name: 'set_appearance',
  title: 'Set light or dark mode',
  description: 'Switches the simulator between light and dark appearance.',
  inputSchema: {
    appearance: z.enum(APPEARANCES).describe('Appearance to apply.'),
    device: deviceParam,
  },
  annotations: { ...Hints.mutating, idempotentHint: true },
  execute: async ({ appearance, device }) => {
    const target = await this.environment.setAppearance(appearance, device);
    return text(`${target.label} now uses the ${appearance} appearance.`);
  },
}),
  1. Add tests: the rule in test/application/, the command in test/infrastructure/ and the visible behaviour in test/mcp/. Add the name to the list in protocol.e2e.test.ts.
  2. Run npm run docs:tools to regenerate the reference.

Documentation ​

The site is built with VitePress. The content is the Markdown files in docs/ (Spanish at the root, English under docs/en/) and the configuration lives in docs/.vitepress/config.ts. Every change on main is published to GitHub Pages by the .github/workflows/docs.yml workflow.

The Tools page is generated by scripts/generate-tool-docs.mjs and must not be edited by hand.

Releasing ​

  1. Update the version in package.json and add an entry to CHANGELOG.md.
  2. Tag the commit (git tag v1.2.0 && git push --tags) and create a GitHub release.
  3. Publishing the release runs .github/workflows/publish.yml, which publishes the package to npm when the NPM_TOKEN secret is configured.

Released under the MIT License.