{"owner":"getsentry","repo":"XcodeBuildMCP","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md","CLAUDE.md"],"skills":{"AGENTS.md":"# Development Rules\n\n## Build & Test\n- `npm run build` - Build (wireit + tsup, ESM)\n- `npm run test` - Unit/integration tests (Vitest)\n- `npm run test:smoke` - Smoke tests (builds first, serial execution)\n- `npm run lint` / `npm run lint:fix` - ESLint\n- `npm run format` / `npm run format:check` - Prettier\n- `npm run typecheck` - TypeScript type checking (src + test config)\n\n## Architecture\nESM TypeScript project (`type: module`). Key layers:\n\n- `src/cli/` - CLI entrypoint, yargs wiring, daemon routing\n- `src/server/` - MCP stdio server, lifecycle, workflow/resource registration\n- `src/runtime/` - Config bootstrap, session state, tool catalog assembly\n- `src/core/manifest/` - YAML manifest loading, validation, tool module imports\n- `src/mcp/tools/` - Tool implementations grouped by workflow (mirrors `manifests/workflows/`)\n- `src/mcp/resources/` - MCP resource implementations\n- `src/integrations/` - External integrations (Xcode tools bridge)\n- `src/utils/` - Shared helpers (execution, logging, validation, responses)\n- `src/visibility/` - Tool/workflow exposure predicates\n- `src/daemon/` - Background daemon for persistent sessions\n- `src/rendering/` - Output rendering and formatting\n- `src/types/` - Shared type definitions\n\n## Contributing Workflow\n1. Create a branch from `main`\n2. Make changes following the conventions in this file\n3. Run the pre-commit checklist before committing:\n   ```bash\n   npm run lint:fix\n   npm run typecheck\n   npm run format\n   npm run build\n   npm test\n   ```\n4. Update `CHANGELOG.md` under `## [Unreleased]`\n5. Update documentation if adding or modifying features\n6. Clone and test against example projects (e.g., `XcodeBuildMCP-iOS-Template`) when changes affect runtime behavior\n7. Push and create a pull request with a clear description\n8. Link any related issues\n\n## Code Quality\n- No `any` types unless absolutely necessary\n- Check node_modules for external API type definitions instead of guessing\n- **NEVER use inline imports** - no `await import(\"./foo.js\")`, no `import(\"pkg\").Type` in type positions, no dynamic imports for types. Always use standard top-level imports.\n- NEVER remove or downgrade code to fix type errors from outdated dependencies; upgrade the dependency instead\n- Always ask before removing functionality or code that appears to be intentional\n- Do not add fallback behavior by default. If required context, configuration, runtime state, or dependencies are missing, fail loudly and fix the caller/setup instead of silently switching to an alternate path. Add a fallback only when explicitly requested or when it is a documented product requirement.\n- Review the complete merge-base diff and trace changed or reused helper contracts, including error and sentinel returns, through callers, consumers, tests, and operational configuration.\n- Verify standard quality commands include every changed path and exercise exact entry points and argument variants; validate explicitly when they do not.\n- For asynchronous, workflow, or process-boundary changes, enumerate lifecycle states, retries, supersession, and race transitions; test terminal outcomes and missing or optional metadata.\n\n## Import Conventions\n- ESM with explicit `.ts` extensions in `src/` (tsup rewrites to `.js` at build)\n- No `.js` imports in `src/` (enforced by ESLint)\n- No barrel imports from `utils/index` - import from specific submodules (e.g., `src/utils/execution/index.ts`, `src/utils/logging/index.ts`)\n\n\n## Rendering and Streaming Contract\n- Streaming fragments are transient live-progress output only. They may be displayed while a tool is running, but MUST NOT provide final settled MCP/JSON/CLI text.\n- Final settled output MUST render from the final structured/domain result and next-step metadata. If final output needs data, add it to the final result type instead of reading it from fragments.\n- Streaming-capable renderers may observe fragment callbacks only for live progress. Fragment handling must not affect final structured output or final settled text.\n\n## Error Handling\n- Structured errors (domain results with `didError`) are for domain errors only: failures in the user's build/test/device/simulator workflow (compile errors, test failures, missing destinations, etc.).\n- System errors with the MCP server or CLI itself (invalid internal state, unresolvable configuration, infrastructure failures) must NOT be wrapped in structured domain results — let them surface as runtime tool errors so they are clearly distinguishable from workflow outcomes.\n\n## Test Conventions\n- Vitest with colocated `__tests__/` directories using `*.test.ts`\n- Snapshot tests (`*.snapshot.test.ts`) must only assert generated tool output against fixtures. Move helper, parser, schema, setup, or behavior assertions to non-snapshot unit/integration tests.\n- Smoke tests in `src/smoke-tests/__tests__/` (separate Vitest config, serial execution)\n- Use `vi.mock`/`vi.hoisted` for isolation; inject executors and mock file systems\n- MCP integration tests use `McpServer`, `InMemoryTransport`, and `Client`\n- External dependencies (command execution, file system) must use dependency injection via `createMockExecutor()` / `createMockFileSystemExecutor()` from `src/test-utils/`\n\n## Tool Development\n- Tool manifests in `manifests/tools/*.yaml` define `id`, `module`, `names.mcp` (snake_case), optional `names.cli` (kebab-case), predicates, and annotations\n- MCP `readOnlyHint` describes whether a tool mutates host/project state such as files, build artifacts, configuration, or external services. Simulator HID/UI actions that only tap, type, press, or gesture inside the simulator may remain `readOnlyHint: true`; do not flip them to `false` merely because app UI state changes.\n- Workflow manifests in `manifests/workflows/*.yaml` group tools and define exposure rules\n- Tool modules export a Zod `schema`, a pure `*Logic` function, and a `handler` built with `createTypedTool` or `createSessionAwareTool`\n- Resource modules export a `handler` (and a pure `*Logic` function); `uri`, `name`, `description`, and `mimeType` are declared in `manifests/resources/*.yaml`\n\n## Commands\n- NEVER commit unless user asks\n\n## GitHub\nWhen reading issues:\n- Always read all comments on the issue\n-\n## Tools\n- GitHub CLI for issues/PRs\n- CLI design note: do not rely on CLI session-default writes. CLI is intentionally deterministic for CI/scripting and should use explicit command arguments as the primary input surface.\n- When working on skill sources in `skills/`, use the `skill-creator` skill workflow.\n- After modifying any skill source, run `npx skill-check <skill-directory>` and address all errors/warnings before handoff.\n- Before handoff, run the matching manual Warden review for high-risk changes: runtime/CLI/daemon boundaries → `xcodebuildmcp-runtime-boundary-review`; test infrastructure or harnesses → `xcodebuildmcp-test-boundary-review`; tool manifests, schemas, or contracts → `xcodebuildmcp-tool-contract-review`. Invoke only applicable skills with `warden --skill <name>`.\n-\n## Multi-process filesystem state\n- XcodeBuildMCP explicitly supports multiple concurrent MCP server, daemon, CLI, test, and helper processes for the same or different workspaces.\n- Shared filesystem state under `~/Library/Developer/XcodeBuildMCP` must be multi-process safe.\n- Use workspace-key scoped directories for workspace-owned state.\n- Do not store runtime state under `~/.xcodebuildmcp`; `.xcodebuildmcp/config.yaml` is only project configuration.\n- Use shared lock and atomic-write helpers for mutable shared files.\n- Prefer one-record-per-file registries over shared aggregate files.\n- Cleanup must verify ownership before deleting shared artifacts.\n- Multi-process safety means concurrent processes must not corrupt or delete each other's state.\n  It does not mean ephemeral runtime handles should become portable between invocation surfaces.\n- Keep runtime/session-scoped handles isolated unless the product explicitly defines a cross-process\n  contract. For example, UI automation `elementRef` values from runtime snapshots are handles for\n  the runtime/session that produced them, not durable IDs to share between separate MCP and CLI\n  invocations.\n- User-facing artifact/log paths in final text or structured output must use `displayPath()` from `src/utils/build-preflight.ts`, so paths are cwd-relative when possible or `~/...` instead of absolute home paths. Keep stored files at their real absolute paths; only normalize response/display values.\n\n## Style\n- Keep answers short and concise\n- No emojis in commits, issues, PR comments, or code\n- No fluff or cheerful filler text\n- Technical prose only, be kind but direct (e.g., \"Thanks @user\" not \"Thanks so much @user!\")\n\n## Docs\n- Do not commit transient investigation notes, prompt exports, or scratch analysis docs after the work is complete.\n- If an investigation leaves unresolved follow-up work, move it to a GitHub issue instead of preserving the transient doc in the branch.\n- Structured output JSON schemas are auto-published to the website/public schema mirror when merged; do not manually update public schema copies unless explicitly asked.\n\n### Changelog\nLocation: `CHANGELOG.md`\n\n#### Format\nUse these sections under `## [Unreleased]`:\n- `### Added` - New features\n- `### Changed` - Changes to existing functionality\n- `### Fixed` - Bug fixes\n- `### Removed` - Removed features\n-\n#### Rules\n- Before adding entries, read the full `[Unreleased]` section to see which subsections already exist\n- New entries ALWAYS go under `## [Unreleased]` section\n- Append to existing subsections (e.g., `### Fixed`), do not create duplicates\n- NEVER modify already-released version sections (e.g., `## [0.12.2]`)\n- Each version section is immutable once released\n- NEVER update snapshot fixtures unless asked to do so, these are integration tests, on failure assume code is wrong before questioning the fixture\n-\n#### Attribution\n- **Internal changes (from issues)**: `Fixed foo bar ([#123](https://github.com/getsentry/XcodeBuildMCP/issues/123))`\n- **External contributions**: `Added feature X ([#456](https://github.com/getsentry/XcodeBuildMCP/pull/456) by [@username](https://github.com/username))`\n\n## Test Execution Rules\n- **NEVER run the snapshot or smoke test suites without explicit user permission.** They are expensive (~7 min baseline, spawn real `xcodebuild`/`simctl`/`devicectl` processes and can wedge). This covers `npm run test:snapshot`, `npm run test:smoke`, and any direct `vitest run --config vitest.snapshot.config.ts` / `vitest.smoke.config.ts` invocation. Ask first, then run only if the user agrees.\n- The default unit suite (`npm test` / `vitest run`), `npm run typecheck`, `npm run lint`, and `npm run build` are cheap and may be run freely without asking.\n- When running long test suites (snapshot tests, smoke tests), ALWAYS write full output to a log file and read it afterwards. NEVER pipe through `tail` or `grep` directly — that loses output you may need to debug failures.\n- Pattern: `DEVICE_ID=... npm run test:snapshot 2>&1 | tee /tmp/snapshot-results.txt` then read `/tmp/snapshot-results.txt` with the native read tool.\n- If you need a summary, read the log file and grep/filter it — the full output is always preserved.\n- Snapshot test command: `DEVICE_ID=<YOUR_DEVICE_ID> npm run test:snapshot`\n- **Snapshot suite expected duration**: ~7 min baseline (measured at 423s). Anything longer than ~10 min should be treated as a likely hang, not a slow run.\n  - Do NOT just kill the run — first inspect the process tree (`ps -ef | grep -E \"vitest|xcodebuild|simctl|devicectl\"`) to identify what's stuck.\n  - Common hang causes: locked physical device, stale simulator state, `devicectl diagnose` waiting for password, orphaned daemon process.\n  - Capture what you find before killing, so the root cause can be fixed rather than papered over.\n- If physical-device snapshot tests hang after the final test summary, the likely cause is Apple post-failure diagnostics invoking `devicectl diagnose`, which may prompt for a macOS password and wedge in automated runs.\n- When asked to review changes or test failures, focus on regressions: behavior changes caused by the branch. Do not treat known/acceptable test flakes, environment setup issues, or nondeterministic tool output churn as regressions unless explicitly asked to investigate them.\n\n## **CRITICAL** Tool Usage Rules **CRITICAL**\n- NEVER use sed/cat to read a file or a range of a file. Always use the native read tool.\n- You MUST read every file you modify in full before editing.\n","CLAUDE.md":"# Development Rules\n\n## Code Quality\n- No `any` types unless absolutely necessary\n- Check node_modules for external API type definitions instead of guessing\n- **NEVER use inline imports** - no `await import(\"./foo.js\")`, no `import(\"pkg\").Type` in type positions, no dynamic imports for types. Always use standard top-level imports.\n- NEVER remove or downgrade code to fix type errors from outdated dependencies; upgrade the dependency instead\n- Always ask before removing functionality or code that appears to be intentional\n- Do not add fallback behavior by default. If required context, configuration, runtime state, or dependencies are missing, fail loudly and fix the caller/setup instead of silently switching to an alternate path. Add a fallback only when explicitly requested or when it is a documented product requirement.\n- Review the complete merge-base diff and trace changed or reused helper contracts, including error and sentinel returns, through callers, consumers, tests, and operational configuration.\n- Verify standard quality commands include every changed path and exercise exact entry points and argument variants; validate explicitly when they do not.\n- For asynchronous, workflow, or process-boundary changes, enumerate lifecycle states, retries, supersession, and race transitions; test terminal outcomes and missing or optional metadata.\n\n## Test Conventions\n- Snapshot tests (`*.snapshot.test.ts`) must only assert generated tool output against fixtures. Move helper, parser, schema, setup, or behavior assertions to non-snapshot unit/integration tests.\n\n## Commands\n- NEVER commit unless user asks\n\n## GitHub\nWhen reading issues:\n- Always read all comments on the issue\n-\n## Tools\n- GitHub CLI for issues/PRs\n- MCP `readOnlyHint` describes whether a tool mutates host/project state such as files, build artifacts, configuration, or external services. Simulator HID/UI actions that only tap, type, press, or gesture inside the simulator may remain `readOnlyHint: true`; do not flip them to `false` merely because app UI state changes.\n- CLI design note: do not rely on CLI session-default writes. CLI is intentionally deterministic for CI/scripting and should use explicit command arguments as the primary input surface.\n- When working on skill sources in `skills/`, use the `skill-creator` skill workflow.\n- After modifying any skill source, run `npx skill-check <skill-directory>` and address all errors/warnings before handoff.\n- Before handoff, run the matching manual Warden review for high-risk changes: runtime/CLI/daemon boundaries → `xcodebuildmcp-runtime-boundary-review`; test infrastructure or harnesses → `xcodebuildmcp-test-boundary-review`; tool manifests, schemas, or contracts → `xcodebuildmcp-tool-contract-review`. Invoke only applicable skills with `warden --skill <name>`.\n-\n## Multi-process filesystem state\n- XcodeBuildMCP explicitly supports multiple concurrent MCP server, daemon, CLI, test, and helper processes for the same or different workspaces.\n- Shared filesystem state under `~/Library/Developer/XcodeBuildMCP` must be multi-process safe.\n- Use workspace-key scoped directories for workspace-owned state.\n- Do not store runtime state under `~/.xcodebuildmcp`; `.xcodebuildmcp/config.yaml` is only project configuration.\n- Use shared lock and atomic-write helpers for mutable shared files.\n- Prefer one-record-per-file registries over shared aggregate files.\n- Cleanup must verify ownership before deleting shared artifacts.\n- User-facing artifact/log paths in final text or structured output must use `displayPath()` from `src/utils/build-preflight.ts`, so paths are cwd-relative when possible or `~/...` instead of absolute home paths. Keep stored files at their real absolute paths; only normalize response/display values.\n\n## Style\n- Keep answers short and concise\n- No emojis in commits, issues, PR comments, or code\n- No fluff or cheerful filler text\n- Technical prose only, be kind but direct (e.g., \"Thanks @user\" not \"Thanks so much @user!\")\n\n## Docs\n- Do not commit transient investigation notes, prompt exports, or scratch analysis docs after the work is complete.\n- If an investigation leaves unresolved follow-up work, move it to a GitHub issue instead of preserving the transient doc in the branch.\n- Structured output JSON schemas are auto-published to the website/public schema mirror when merged; do not manually update public schema copies unless explicitly asked.\n\n### Changelog\nLocation: `CHANGELOG.md`\n\n#### Format\nUse these sections under `## [Unreleased]`:\n- `### Added` - New features\n- `### Changed` - Changes to existing functionality\n- `### Fixed` - Bug fixes\n- `### Removed` - Removed features\n-\n#### Rules\n- Before adding entries, read the full `[Unreleased]` section to see which subsections already exist\n- New entries ALWAYS go under `## [Unreleased]` section\n- Append to existing subsections (e.g., `### Fixed`), do not create duplicates\n- NEVER modify already-released version sections (e.g., `## [0.12.2]`)\n- Each version section is immutable once released\n- NEVER update snapshot fixtures unless asked to do so, these are integration tests, on failure assume code is wrong before questioning the fixture\n-\n#### Attribution\n- **Internal changes (from issues)**: `Fixed foo bar ([#123](https://github.com/cameroncook/XcodeBuildMCP/issues/123))`\n- **External contributions**: `Added feature X ([#456](https://github.com/cameroncook/XcodeBuildMCP/pull/456) by [@username](https://github.com/username))`\n\n\n## Rendering and Streaming Contract\n- Streaming fragments are transient live-progress output only. They may be displayed while a tool is running, but MUST NOT provide final settled MCP/JSON/CLI text.\n- Final settled output MUST render from the final structured/domain result and next-step metadata. If final output needs data, add it to the final result type instead of reading it from fragments.\n- Streaming-capable renderers may observe fragment callbacks only for live progress. Fragment handling must not affect final structured output or final settled text.\n\n## Error Handling\n- Structured errors (domain results with `didError`) are for domain errors only: failures in the user's build/test/device/simulator workflow (compile errors, test failures, missing destinations, etc.).\n- System errors with the MCP server or CLI itself (invalid internal state, unresolvable configuration, infrastructure failures) must NOT be wrapped in structured domain results — let them surface as runtime tool errors so they are clearly distinguishable from workflow outcomes.\n\n## Test Execution Rules\n- **NEVER run the snapshot or smoke test suites without explicit user permission.** They are expensive (~7 min baseline, spawn real `xcodebuild`/`simctl`/`devicectl` processes and can wedge). This covers `npm run test:snapshot`, `npm run test:smoke`, and any direct `vitest run --config vitest.snapshot.config.ts` / `vitest.smoke.config.ts` invocation. Ask first, then run only if the user agrees.\n- The default unit suite (`npm test` / `vitest run`), `npm run typecheck`, `npm run lint`, and `npm run build` are cheap and may be run freely without asking.\n- When running long test suites (snapshot tests, smoke tests), ALWAYS write full output to a log file and read it afterwards. NEVER pipe through `tail` or `grep` directly — that loses output you may need to debug failures.\n- Pattern: `DEVICE_ID=... npm run test:snapshot 2>&1 | tee /tmp/snapshot-results.txt` then read `/tmp/snapshot-results.txt` with the native read tool.\n- If you need a summary, read the log file and grep/filter it — the full output is always preserved.\n- Snapshot test command: `DEVICE_ID=<YOUR_DEVICE_ID> npm run test:snapshot`\n- **Snapshot suite expected duration**: ~7 min baseline (measured at 423s). Anything longer than ~10 min should be treated as a likely hang, not a slow run.\n  - Do NOT just kill the run — first inspect the process tree (`ps -ef | grep -E \"vitest|xcodebuild|simctl|devicectl\"`) to identify what's stuck.\n  - Common hang causes: locked physical device, stale simulator state, `devicectl diagnose` waiting for password, orphaned daemon process.\n  - Capture what you find before killing, so the root cause can be fixed rather than papered over.\n- When asked to review changes or test failures, focus on regressions: behavior changes caused by the branch. Do not treat known/acceptable test flakes, environment setup issues, or nondeterministic tool output churn as regressions unless explicitly asked to investigate them.\n\n## **CRITICAL** Tool Usage Rules **CRITICAL**\n- NEVER use sed/cat to read a file or a range of a file. Always use the native read tool.\n- You MUST read every file you modify in full before editing.\n"},"files":{"AGENTS.md":"# Development Rules\n\n## Build & Test\n- `npm run build` - Build (wireit + tsup, ESM)\n- `npm run test` - Unit/integration tests (Vitest)\n- `npm run test:smoke` - Smoke tests (builds first, serial execution)\n- `npm run lint` / `npm run lint:fix` - ESLint\n- `npm run format` / `npm run format:check` - Prettier\n- `npm run typecheck` - TypeScript type checking (src + test config)\n\n## Architecture\nESM TypeScript project (`type: module`). Key layers:\n\n- `src/cli/` - CLI entrypoint, yargs wiring, daemon routing\n- `src/server/` - MCP stdio server, lifecycle, workflow/resource registration\n- `src/runtime/` - Config bootstrap, session state, tool catalog assembly\n- `src/core/manifest/` - YAML manifest loading, validation, tool module imports\n- `src/mcp/tools/` - Tool implementations grouped by workflow (mirrors `manifests/workflows/`)\n- `src/mcp/resources/` - MCP resource implementations\n- `src/integrations/` - External integrations (Xcode tools bridge)\n- `src/utils/` - Shared helpers (execution, logging, validation, responses)\n- `src/visibility/` - Tool/workflow exposure predicates\n- `src/daemon/` - Background daemon for persistent sessions\n- `src/rendering/` - Output rendering and formatting\n- `src/types/` - Shared type definitions\n\n## Contributing Workflow\n1. Create a branch from `main`\n2. Make changes following the conventions in this file\n3. Run the pre-commit checklist before committing:\n   ```bash\n   npm run lint:fix\n   npm run typecheck\n   npm run format\n   npm run build\n   npm test\n   ```\n4. Update `CHANGELOG.md` under `## [Unreleased]`\n5. Update documentation if adding or modifying features\n6. Clone and test against example projects (e.g., `XcodeBuildMCP-iOS-Template`) when changes affect runtime behavior\n7. Push and create a pull request with a clear description\n8. Link any related issues\n\n## Code Quality\n- No `any` types unless absolutely necessary\n- Check node_modules for external API type definitions instead of guessing\n- **NEVER use inline imports** - no `await import(\"./foo.js\")`, no `import(\"pkg\").Type` in type positions, no dynamic imports for types. Always use standard top-level imports.\n- NEVER remove or downgrade code to fix type errors from outdated dependencies; upgrade the dependency instead\n- Always ask before removing functionality or code that appears to be intentional\n- Do not add fallback behavior by default. If required context, configuration, runtime state, or dependencies are missing, fail loudly and fix the caller/setup instead of silently switching to an alternate path. Add a fallback only when explicitly requested or when it is a documented product requirement.\n- Review the complete merge-base diff and trace changed or reused helper contracts, including error and sentinel returns, through callers, consumers, tests, and operational configuration.\n- Verify standard quality commands include every changed path and exercise exact entry points and argument variants; validate explicitly when they do not.\n- For asynchronous, workflow, or process-boundary changes, enumerate lifecycle states, retries, supersession, and race transitions; test terminal outcomes and missing or optional metadata.\n\n## Import Conventions\n- ESM with explicit `.ts` extensions in `src/` (tsup rewrites to `.js` at build)\n- No `.js` imports in `src/` (enforced by ESLint)\n- No barrel imports from `utils/index` - import from specific submodules (e.g., `src/utils/execution/index.ts`, `src/utils/logging/index.ts`)\n\n\n## Rendering and Streaming Contract\n- Streaming fragments are transient live-progress output only. They may be displayed while a tool is running, but MUST NOT provide final settled MCP/JSON/CLI text.\n- Final settled output MUST render from the final structured/domain result and next-step metadata. If final output needs data, add it to the final result type instead of reading it from fragments.\n- Streaming-capable renderers may observe fragment callbacks only for live progress. Fragment handling must not affect final structured output or final settled text.\n\n## Error Handling\n- Structured errors (domain results with `didError`) are for domain errors only: failures in the user's build/test/device/simulator workflow (compile errors, test failures, missing destinations, etc.).\n- System errors with the MCP server or CLI itself (invalid internal state, unresolvable configuration, infrastructure failures) must NOT be wrapped in structured domain results — let them surface as runtime tool errors so they are clearly distinguishable from workflow outcomes.\n\n## Test Conventions\n- Vitest with colocated `__tests__/` directories using `*.test.ts`\n- Snapshot tests (`*.snapshot.test.ts`) must only assert generated tool output against fixtures. Move helper, parser, schema, setup, or behavior assertions to non-snapshot unit/integration tests.\n- Smoke tests in `src/smoke-tests/__tests__/` (separate Vitest config, serial execution)\n- Use `vi.mock`/`vi.hoisted` for isolation; inject executors and mock file systems\n- MCP integration tests use `McpServer`, `InMemoryTransport`, and `Client`\n- External dependencies (command execution, file system) must use dependency injection via `createMockExecutor()` / `createMockFileSystemExecutor()` from `src/test-utils/`\n\n## Tool Development\n- Tool manifests in `manifests/tools/*.yaml` define `id`, `module`, `names.mcp` (snake_case), optional `names.cli` (kebab-case), predicates, and annotations\n- MCP `readOnlyHint` describes whether a tool mutates host/project state such as files, build artifacts, configuration, or external services. Simulator HID/UI actions that only tap, type, press, or gesture inside the simulator may remain `readOnlyHint: true`; do not flip them to `false` merely because app UI state changes.\n- Workflow manifests in `manifests/workflows/*.yaml` group tools and define exposure rules\n- Tool modules export a Zod `schema`, a pure `*Logic` function, and a `handler` built with `createTypedTool` or `createSessionAwareTool`\n- Resource modules export a `handler` (and a pure `*Logic` function); `uri`, `name`, `description`, and `mimeType` are declared in `manifests/resources/*.yaml`\n\n## Commands\n- NEVER commit unless user asks\n\n## GitHub\nWhen reading issues:\n- Always read all comments on the issue\n-\n## Tools\n- GitHub CLI for issues/PRs\n- CLI design note: do not rely on CLI session-default writes. CLI is intentionally deterministic for CI/scripting and should use explicit command arguments as the primary input surface.\n- When working on skill sources in `skills/`, use the `skill-creator` skill workflow.\n- After modifying any skill source, run `npx skill-check <skill-directory>` and address all errors/warnings before handoff.\n- Before handoff, run the matching manual Warden review for high-risk changes: runtime/CLI/daemon boundaries → `xcodebuildmcp-runtime-boundary-review`; test infrastructure or harnesses → `xcodebuildmcp-test-boundary-review`; tool manifests, schemas, or contracts → `xcodebuildmcp-tool-contract-review`. Invoke only applicable skills with `warden --skill <name>`.\n-\n## Multi-process filesystem state\n- XcodeBuildMCP explicitly supports multiple concurrent MCP server, daemon, CLI, test, and helper processes for the same or different workspaces.\n- Shared filesystem state under `~/Library/Developer/XcodeBuildMCP` must be multi-process safe.\n- Use workspace-key scoped directories for workspace-owned state.\n- Do not store runtime state under `~/.xcodebuildmcp`; `.xcodebuildmcp/config.yaml` is only project configuration.\n- Use shared lock and atomic-write helpers for mutable shared files.\n- Prefer one-record-per-file registries over shared aggregate files.\n- Cleanup must verify ownership before deleting shared artifacts.\n- Multi-process safety means concurrent processes must not corrupt or delete each other's state.\n  It does not mean ephemeral runtime handles should become portable between invocation surfaces.\n- Keep runtime/session-scoped handles isolated unless the product explicitly defines a cross-process\n  contract. For example, UI automation `elementRef` values from runtime snapshots are handles for\n  the runtime/session that produced them, not durable IDs to share between separate MCP and CLI\n  invocations.\n- User-facing artifact/log paths in final text or structured output must use `displayPath()` from `src/utils/build-preflight.ts`, so paths are cwd-relative when possible or `~/...` instead of absolute home paths. Keep stored files at their real absolute paths; only normalize response/display values.\n\n## Style\n- Keep answers short and concise\n- No emojis in commits, issues, PR comments, or code\n- No fluff or cheerful filler text\n- Technical prose only, be kind but direct (e.g., \"Thanks @user\" not \"Thanks so much @user!\")\n\n## Docs\n- Do not commit transient investigation notes, prompt exports, or scratch analysis docs after the work is complete.\n- If an investigation leaves unresolved follow-up work, move it to a GitHub issue instead of preserving the transient doc in the branch.\n- Structured output JSON schemas are auto-published to the website/public schema mirror when merged; do not manually update public schema copies unless explicitly asked.\n\n### Changelog\nLocation: `CHANGELOG.md`\n\n#### Format\nUse these sections under `## [Unreleased]`:\n- `### Added` - New features\n- `### Changed` - Changes to existing functionality\n- `### Fixed` - Bug fixes\n- `### Removed` - Removed features\n-\n#### Rules\n- Before adding entries, read the full `[Unreleased]` section to see which subsections already exist\n- New entries ALWAYS go under `## [Unreleased]` section\n- Append to existing subsections (e.g., `### Fixed`), do not create duplicates\n- NEVER modify already-released version sections (e.g., `## [0.12.2]`)\n- Each version section is immutable once released\n- NEVER update snapshot fixtures unless asked to do so, these are integration tests, on failure assume code is wrong before questioning the fixture\n-\n#### Attribution\n- **Internal changes (from issues)**: `Fixed foo bar ([#123](https://github.com/getsentry/XcodeBuildMCP/issues/123))`\n- **External contributions**: `Added feature X ([#456](https://github.com/getsentry/XcodeBuildMCP/pull/456) by [@username](https://github.com/username))`\n\n## Test Execution Rules\n- **NEVER run the snapshot or smoke test suites without explicit user permission.** They are expensive (~7 min baseline, spawn real `xcodebuild`/`simctl`/`devicectl` processes and can wedge). This covers `npm run test:snapshot`, `npm run test:smoke`, and any direct `vitest run --config vitest.snapshot.config.ts` / `vitest.smoke.config.ts` invocation. Ask first, then run only if the user agrees.\n- The default unit suite (`npm test` / `vitest run`), `npm run typecheck`, `npm run lint`, and `npm run build` are cheap and may be run freely without asking.\n- When running long test suites (snapshot tests, smoke tests), ALWAYS write full output to a log file and read it afterwards. NEVER pipe through `tail` or `grep` directly — that loses output you may need to debug failures.\n- Pattern: `DEVICE_ID=... npm run test:snapshot 2>&1 | tee /tmp/snapshot-results.txt` then read `/tmp/snapshot-results.txt` with the native read tool.\n- If you need a summary, read the log file and grep/filter it — the full output is always preserved.\n- Snapshot test command: `DEVICE_ID=<YOUR_DEVICE_ID> npm run test:snapshot`\n- **Snapshot suite expected duration**: ~7 min baseline (measured at 423s). Anything longer than ~10 min should be treated as a likely hang, not a slow run.\n  - Do NOT just kill the run — first inspect the process tree (`ps -ef | grep -E \"vitest|xcodebuild|simctl|devicectl\"`) to identify what's stuck.\n  - Common hang causes: locked physical device, stale simulator state, `devicectl diagnose` waiting for password, orphaned daemon process.\n  - Capture what you find before killing, so the root cause can be fixed rather than papered over.\n- If physical-device snapshot tests hang after the final test summary, the likely cause is Apple post-failure diagnostics invoking `devicectl diagnose`, which may prompt for a macOS password and wedge in automated runs.\n- When asked to review changes or test failures, focus on regressions: behavior changes caused by the branch. Do not treat known/acceptable test flakes, environment setup issues, or nondeterministic tool output churn as regressions unless explicitly asked to investigate them.\n\n## **CRITICAL** Tool Usage Rules **CRITICAL**\n- NEVER use sed/cat to read a file or a range of a file. Always use the native read tool.\n- You MUST read every file you modify in full before editing.\n","CLAUDE.md":"# Development Rules\n\n## Code Quality\n- No `any` types unless absolutely necessary\n- Check node_modules for external API type definitions instead of guessing\n- **NEVER use inline imports** - no `await import(\"./foo.js\")`, no `import(\"pkg\").Type` in type positions, no dynamic imports for types. Always use standard top-level imports.\n- NEVER remove or downgrade code to fix type errors from outdated dependencies; upgrade the dependency instead\n- Always ask before removing functionality or code that appears to be intentional\n- Do not add fallback behavior by default. If required context, configuration, runtime state, or dependencies are missing, fail loudly and fix the caller/setup instead of silently switching to an alternate path. Add a fallback only when explicitly requested or when it is a documented product requirement.\n- Review the complete merge-base diff and trace changed or reused helper contracts, including error and sentinel returns, through callers, consumers, tests, and operational configuration.\n- Verify standard quality commands include every changed path and exercise exact entry points and argument variants; validate explicitly when they do not.\n- For asynchronous, workflow, or process-boundary changes, enumerate lifecycle states, retries, supersession, and race transitions; test terminal outcomes and missing or optional metadata.\n\n## Test Conventions\n- Snapshot tests (`*.snapshot.test.ts`) must only assert generated tool output against fixtures. Move helper, parser, schema, setup, or behavior assertions to non-snapshot unit/integration tests.\n\n## Commands\n- NEVER commit unless user asks\n\n## GitHub\nWhen reading issues:\n- Always read all comments on the issue\n-\n## Tools\n- GitHub CLI for issues/PRs\n- MCP `readOnlyHint` describes whether a tool mutates host/project state such as files, build artifacts, configuration, or external services. Simulator HID/UI actions that only tap, type, press, or gesture inside the simulator may remain `readOnlyHint: true`; do not flip them to `false` merely because app UI state changes.\n- CLI design note: do not rely on CLI session-default writes. CLI is intentionally deterministic for CI/scripting and should use explicit command arguments as the primary input surface.\n- When working on skill sources in `skills/`, use the `skill-creator` skill workflow.\n- After modifying any skill source, run `npx skill-check <skill-directory>` and address all errors/warnings before handoff.\n- Before handoff, run the matching manual Warden review for high-risk changes: runtime/CLI/daemon boundaries → `xcodebuildmcp-runtime-boundary-review`; test infrastructure or harnesses → `xcodebuildmcp-test-boundary-review`; tool manifests, schemas, or contracts → `xcodebuildmcp-tool-contract-review`. Invoke only applicable skills with `warden --skill <name>`.\n-\n## Multi-process filesystem state\n- XcodeBuildMCP explicitly supports multiple concurrent MCP server, daemon, CLI, test, and helper processes for the same or different workspaces.\n- Shared filesystem state under `~/Library/Developer/XcodeBuildMCP` must be multi-process safe.\n- Use workspace-key scoped directories for workspace-owned state.\n- Do not store runtime state under `~/.xcodebuildmcp`; `.xcodebuildmcp/config.yaml` is only project configuration.\n- Use shared lock and atomic-write helpers for mutable shared files.\n- Prefer one-record-per-file registries over shared aggregate files.\n- Cleanup must verify ownership before deleting shared artifacts.\n- User-facing artifact/log paths in final text or structured output must use `displayPath()` from `src/utils/build-preflight.ts`, so paths are cwd-relative when possible or `~/...` instead of absolute home paths. Keep stored files at their real absolute paths; only normalize response/display values.\n\n## Style\n- Keep answers short and concise\n- No emojis in commits, issues, PR comments, or code\n- No fluff or cheerful filler text\n- Technical prose only, be kind but direct (e.g., \"Thanks @user\" not \"Thanks so much @user!\")\n\n## Docs\n- Do not commit transient investigation notes, prompt exports, or scratch analysis docs after the work is complete.\n- If an investigation leaves unresolved follow-up work, move it to a GitHub issue instead of preserving the transient doc in the branch.\n- Structured output JSON schemas are auto-published to the website/public schema mirror when merged; do not manually update public schema copies unless explicitly asked.\n\n### Changelog\nLocation: `CHANGELOG.md`\n\n#### Format\nUse these sections under `## [Unreleased]`:\n- `### Added` - New features\n- `### Changed` - Changes to existing functionality\n- `### Fixed` - Bug fixes\n- `### Removed` - Removed features\n-\n#### Rules\n- Before adding entries, read the full `[Unreleased]` section to see which subsections already exist\n- New entries ALWAYS go under `## [Unreleased]` section\n- Append to existing subsections (e.g., `### Fixed`), do not create duplicates\n- NEVER modify already-released version sections (e.g., `## [0.12.2]`)\n- Each version section is immutable once released\n- NEVER update snapshot fixtures unless asked to do so, these are integration tests, on failure assume code is wrong before questioning the fixture\n-\n#### Attribution\n- **Internal changes (from issues)**: `Fixed foo bar ([#123](https://github.com/cameroncook/XcodeBuildMCP/issues/123))`\n- **External contributions**: `Added feature X ([#456](https://github.com/cameroncook/XcodeBuildMCP/pull/456) by [@username](https://github.com/username))`\n\n\n## Rendering and Streaming Contract\n- Streaming fragments are transient live-progress output only. They may be displayed while a tool is running, but MUST NOT provide final settled MCP/JSON/CLI text.\n- Final settled output MUST render from the final structured/domain result and next-step metadata. If final output needs data, add it to the final result type instead of reading it from fragments.\n- Streaming-capable renderers may observe fragment callbacks only for live progress. Fragment handling must not affect final structured output or final settled text.\n\n## Error Handling\n- Structured errors (domain results with `didError`) are for domain errors only: failures in the user's build/test/device/simulator workflow (compile errors, test failures, missing destinations, etc.).\n- System errors with the MCP server or CLI itself (invalid internal state, unresolvable configuration, infrastructure failures) must NOT be wrapped in structured domain results — let them surface as runtime tool errors so they are clearly distinguishable from workflow outcomes.\n\n## Test Execution Rules\n- **NEVER run the snapshot or smoke test suites without explicit user permission.** They are expensive (~7 min baseline, spawn real `xcodebuild`/`simctl`/`devicectl` processes and can wedge). This covers `npm run test:snapshot`, `npm run test:smoke`, and any direct `vitest run --config vitest.snapshot.config.ts` / `vitest.smoke.config.ts` invocation. Ask first, then run only if the user agrees.\n- The default unit suite (`npm test` / `vitest run`), `npm run typecheck`, `npm run lint`, and `npm run build` are cheap and may be run freely without asking.\n- When running long test suites (snapshot tests, smoke tests), ALWAYS write full output to a log file and read it afterwards. NEVER pipe through `tail` or `grep` directly — that loses output you may need to debug failures.\n- Pattern: `DEVICE_ID=... npm run test:snapshot 2>&1 | tee /tmp/snapshot-results.txt` then read `/tmp/snapshot-results.txt` with the native read tool.\n- If you need a summary, read the log file and grep/filter it — the full output is always preserved.\n- Snapshot test command: `DEVICE_ID=<YOUR_DEVICE_ID> npm run test:snapshot`\n- **Snapshot suite expected duration**: ~7 min baseline (measured at 423s). Anything longer than ~10 min should be treated as a likely hang, not a slow run.\n  - Do NOT just kill the run — first inspect the process tree (`ps -ef | grep -E \"vitest|xcodebuild|simctl|devicectl\"`) to identify what's stuck.\n  - Common hang causes: locked physical device, stale simulator state, `devicectl diagnose` waiting for password, orphaned daemon process.\n  - Capture what you find before killing, so the root cause can be fixed rather than papered over.\n- When asked to review changes or test failures, focus on regressions: behavior changes caused by the branch. Do not treat known/acceptable test flakes, environment setup issues, or nondeterministic tool output churn as regressions unless explicitly asked to investigate them.\n\n## **CRITICAL** Tool Usage Rules **CRITICAL**\n- NEVER use sed/cat to read a file or a range of a file. Always use the native read tool.\n- You MUST read every file you modify in full before editing.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# Development Rules\n\n## Build & Test\n- `npm run build` - Build (wireit + tsup, ESM)\n- `npm run test` - Unit/integration tests (Vitest)\n- `npm run test:smoke` - Smoke tests (builds first, serial execution)\n- `npm run lint` / `npm run lint:fix` - ESLint\n- `npm run format` / `npm run format:check` - Prettier\n- `npm run typecheck` - TypeScript type checking (src + test config)\n\n## Architecture\nESM TypeScript project (`type: module`). Key layers:\n\n- `src/cli/` - CLI entrypoint, yargs wiring, daemon routing\n- `src/server/` - MCP stdio server, lifecycle, workflow/resource registration\n- `src/runtime/` - Config bootstrap, session state, tool catalog assembly\n- `src/core/manifest/` - YAML manifest loading, validation, tool module imports\n- `src/mcp/tools/` - Tool implementations grouped by workflow (mirrors `manifests/workflows/`)\n- `src/mcp/resources/` - MCP resource implementations\n- `src/integrations/` - External integrations (Xcode tools bridge)\n- `src/utils/` - Shared helpers (execution, logging, validation, responses)\n- `src/visibility/` - Tool/workflow exposure predicates\n- `src/daemon/` - Background daemon for persistent sessions\n- `src/rendering/` - Output rendering and formatting\n- `src/types/` - Shared type definitions\n\n## Contributing Workflow\n1. Create a branch from `main`\n2. Make changes following the conventions in this file\n3. Run the pre-commit checklist before committing:\n   ```bash\n   npm run lint:fix\n   npm run typecheck\n   npm run format\n   npm run build\n   npm test\n   ```\n4. Update `CHANGELOG.md` under `## [Unreleased]`\n5. Update documentation if adding or modifying features\n6. Clone and test against example projects (e.g., `XcodeBuildMCP-iOS-Template`) when changes affect runtime behavior\n7. Push and create a pull request with a clear description\n8. Link any related issues\n\n## Code Quality\n- No `any` types unless absolutely necessary\n- Check node_modules for external API type definitions instead of guessing\n- **NEVER use inline imports** - no `await import(\"./foo.js\")`, no `import(\"pkg\").Type` in type positions, no dynamic imports for types. Always use standard top-level imports.\n- NEVER remove or downgrade code to fix type errors from outdated dependencies; upgrade the dependency instead\n- Always ask before removing functionality or code that appears to be intentional\n- Do not add fallback behavior by default. If required context, configuration, runtime state, or dependencies are missing, fail loudly and fix the caller/setup instead of silently switching to an alternate path. Add a fallback only when explicitly requested or when it is a documented product requirement.\n- Review the complete merge-base diff and trace changed or reused helper contracts, including error and sentinel returns, through callers, consumers, tests, and operational configuration.\n- Verify standard quality commands include every changed path and exercise exact entry points and argument variants; validate explicitly when they do not.\n- For asynchronous, workflow, or process-boundary changes, enumerate lifecycle states, retries, supersession, and race transitions; test terminal outcomes and missing or optional metadata.\n\n## Import Conventions\n- ESM with explicit `.ts` extensions in `src/` (tsup rewrites to `.js` at build)\n- No `.js` imports in `src/` (enforced by ESLint)\n- No barrel imports from `utils/index` - import from specific submodules (e.g., `src/utils/execution/index.ts`, `src/utils/logging/index.ts`)\n\n\n## Rendering and Streaming Contract\n- Streaming fragments are transient live-progress output only. They may be displayed while a tool is running, but MUST NOT provide final settled MCP/JSON/CLI text.\n- Final settled output MUST render from the final structured/domain result and next-step metadata. If final output needs data, add it to the final result type instead of reading it from fragments.\n- Streaming-capable renderers may observe fragment callbacks only for live progress. Fragment handling must not affect final structured output or final settled text.\n\n## Error Handling\n- Structured errors (domain results with `didError`) are for domain errors only: failures in the user's build/test/device/simulator workflow (compile errors, test failures, missing destinations, etc.).\n- System errors with the MCP server or CLI itself (invalid internal state, unresolvable configuration, infrastructure failures) must NOT be wrapped in structured domain results — let them surface as runtime tool errors so they are clearly distinguishable from workflow outcomes.\n\n## Test Conventions\n- Vitest with colocated `__tests__/` directories using `*.test.ts`\n- Snapshot tests (`*.snapshot.test.ts`) must only assert generated tool output against fixtures. Move helper, parser, schema, setup, or behavior assertions to non-snapshot unit/integration tests.\n- Smoke tests in `src/smoke-tests/__tests__/` (separate Vitest config, serial execution)\n- Use `vi.mock`/`vi.hoisted` for isolation; inject executors and mock file systems\n- MCP integration tests use `McpServer`, `InMemoryTransport`, and `Client`\n- External dependencies (command execution, file system) must use dependency injection via `createMockExecutor()` / `createMockFileSystemExecutor()` from `src/test-utils/`\n\n## Tool Development\n- Tool manifests in `manifests/tools/*.yaml` define `id`, `module`, `names.mcp` (snake_case), optional `names.cli` (kebab-case), predicates, and annotations\n- MCP `readOnlyHint` describes whether a tool mutates host/project state such as files, build artifacts, configuration, or external services. Simulator HID/UI actions that only tap, type, press, or gesture inside the simulator may remain `readOnlyHint: true`; do not flip them to `false` merely because app UI state changes.\n- Workflow manifests in `manifests/workflows/*.yaml` group tools and define exposure rules\n- Tool modules export a Zod `schema`, a pure `*Logic` function, and a `handler` built with `createTypedTool` or `createSessionAwareTool`\n- Resource modules export a `handler` (and a pure `*Logic` function); `uri`, `name`, `description`, and `mimeType` are declared in `manifests/resources/*.yaml`\n\n## Commands\n- NEVER commit unless user asks\n\n## GitHub\nWhen reading issues:\n- Always read all comments on the issue\n-\n## Tools\n- GitHub CLI for issues/PRs\n- CLI design note: do not rely on CLI session-default writes. CLI is intentionally deterministic for CI/scripting and should use explicit command arguments as the primary input surface.\n- When working on skill sources in `skills/`, use the `skill-creator` skill workflow.\n- After modifying any skill source, run `npx skill-check <skill-directory>` and address all errors/warnings before handoff.\n- Before handoff, run the matching manual Warden review for high-risk changes: runtime/CLI/daemon boundaries → `xcodebuildmcp-runtime-boundary-review`; test infrastructure or harnesses → `xcodebuildmcp-test-boundary-review`; tool manifests, schemas, or contracts → `xcodebuildmcp-tool-contract-review`. Invoke only applicable skills with `warden --skill <name>`.\n-\n## Multi-process filesystem state\n- XcodeBuildMCP explicitly supports multiple concurrent MCP server, daemon, CLI, test, and helper processes for the same or different workspaces.\n- Shared filesystem state under `~/Library/Developer/XcodeBuildMCP` must be multi-process safe.\n- Use workspace-key scoped directories for workspace-owned state.\n- Do not store runtime state under `~/.xcodebuildmcp`; `.xcodebuildmcp/config.yaml` is only project configuration.\n- Use shared lock and atomic-write helpers for mutable shared files.\n- Prefer one-record-per-file registries over shared aggregate files.\n- Cleanup must verify ownership before deleting shared artifacts.\n- Multi-process safety means concurrent processes must not corrupt or delete each other's state.\n  It does not mean ephemeral runtime handles should become portable between invocation surfaces.\n- Keep runtime/session-scoped handles isolated unless the product explicitly defines a cross-process\n  contract. For example, UI automation `elementRef` values from runtime snapshots are handles for\n  the runtime/session that produced them, not durable IDs to share between separate MCP and CLI\n  invocations.\n- User-facing artifact/log paths in final text or structured output must use `displayPath()` from `src/utils/build-preflight.ts`, so paths are cwd-relative when possible or `~/...` instead of absolute home paths. Keep stored files at their real absolute paths; only normalize response/display values.\n\n## Style\n- Keep answers short and concise\n- No emojis in commits, issues, PR comments, or code\n- No fluff or cheerful filler text\n- Technical prose only, be kind but direct (e.g., \"Thanks @user\" not \"Thanks so much @user!\")\n\n## Docs\n- Do not commit transient investigation notes, prompt exports, or scratch analysis docs after the work is complete.\n- If an investigation leaves unresolved follow-up work, move it to a GitHub issue instead of preserving the transient doc in the branch.\n- Structured output JSON schemas are auto-published to the website/public schema mirror when merged; do not manually update public schema copies unless explicitly asked.\n\n### Changelog\nLocation: `CHANGELOG.md`\n\n#### Format\nUse these sections under `## [Unreleased]`:\n- `### Added` - New features\n- `### Changed` - Changes to existing functionality\n- `### Fixed` - Bug fixes\n- `### Removed` - Removed features\n-\n#### Rules\n- Before adding entries, read the full `[Unreleased]` section to see which subsections already exist\n- New entries ALWAYS go under `## [Unreleased]` section\n- Append to existing subsections (e.g., `### Fixed`), do not create duplicates\n- NEVER modify already-released version sections (e.g., `## [0.12.2]`)\n- Each version section is immutable once released\n- NEVER update snapshot fixtures unless asked to do so, these are integration tests, on failure assume code is wrong before questioning the fixture\n-\n#### Attribution\n- **Internal changes (from issues)**: `Fixed foo bar ([#123](https://github.com/getsentry/XcodeBuildMCP/issues/123))`\n- **External contributions**: `Added feature X ([#456](https://github.com/getsentry/XcodeBuildMCP/pull/456) by [@username](https://github.com/username))`\n\n## Test Execution Rules\n- **NEVER run the snapshot or smoke test suites without explicit user permission.** They are expensive (~7 min baseline, spawn real `xcodebuild`/`simctl`/`devicectl` processes and can wedge). This covers `npm run test:snapshot`, `npm run test:smoke`, and any direct `vitest run --config vitest.snapshot.config.ts` / `vitest.smoke.config.ts` invocation. Ask first, then run only if the user agrees.\n- The default unit suite (`npm test` / `vitest run`), `npm run typecheck`, `npm run lint`, and `npm run build` are cheap and may be run freely without asking.\n- When running long test suites (snapshot tests, smoke tests), ALWAYS write full output to a log file and read it afterwards. NEVER pipe through `tail` or `grep` directly — that loses output you may need to debug failures.\n- Pattern: `DEVICE_ID=... npm run test:snapshot 2>&1 | tee /tmp/snapshot-results.txt` then read `/tmp/snapshot-results.txt` with the native read tool.\n- If you need a summary, read the log file and grep/filter it — the full output is always preserved.\n- Snapshot test command: `DEVICE_ID=<YOUR_DEVICE_ID> npm run test:snapshot`\n- **Snapshot suite expected duration**: ~7 min baseline (measured at 423s). Anything longer than ~10 min should be treated as a likely hang, not a slow run.\n  - Do NOT just kill the run — first inspect the process tree (`ps -ef | grep -E \"vitest|xcodebuild|simctl|devicectl\"`) to identify what's stuck.\n  - Common hang causes: locked physical device, stale simulator state, `devicectl diagnose` waiting for password, orphaned daemon process.\n  - Capture what you find before killing, so the root cause can be fixed rather than papered over.\n- If physical-device snapshot tests hang after the final test summary, the likely cause is Apple post-failure diagnostics invoking `devicectl diagnose`, which may prompt for a macOS password and wedge in automated runs.\n- When asked to review changes or test failures, focus on regressions: behavior changes caused by the branch. Do not treat known/acceptable test flakes, environment setup issues, or nondeterministic tool output churn as regressions unless explicitly asked to investigate them.\n\n## **CRITICAL** Tool Usage Rules **CRITICAL**\n- NEVER use sed/cat to read a file or a range of a file. Always use the native read tool.\n- You MUST read every file you modify in full before editing.\n","category":"root","tokens":3144},{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# Development Rules\n\n## Code Quality\n- No `any` types unless absolutely necessary\n- Check node_modules for external API type definitions instead of guessing\n- **NEVER use inline imports** - no `await import(\"./foo.js\")`, no `import(\"pkg\").Type` in type positions, no dynamic imports for types. Always use standard top-level imports.\n- NEVER remove or downgrade code to fix type errors from outdated dependencies; upgrade the dependency instead\n- Always ask before removing functionality or code that appears to be intentional\n- Do not add fallback behavior by default. If required context, configuration, runtime state, or dependencies are missing, fail loudly and fix the caller/setup instead of silently switching to an alternate path. Add a fallback only when explicitly requested or when it is a documented product requirement.\n- Review the complete merge-base diff and trace changed or reused helper contracts, including error and sentinel returns, through callers, consumers, tests, and operational configuration.\n- Verify standard quality commands include every changed path and exercise exact entry points and argument variants; validate explicitly when they do not.\n- For asynchronous, workflow, or process-boundary changes, enumerate lifecycle states, retries, supersession, and race transitions; test terminal outcomes and missing or optional metadata.\n\n## Test Conventions\n- Snapshot tests (`*.snapshot.test.ts`) must only assert generated tool output against fixtures. Move helper, parser, schema, setup, or behavior assertions to non-snapshot unit/integration tests.\n\n## Commands\n- NEVER commit unless user asks\n\n## GitHub\nWhen reading issues:\n- Always read all comments on the issue\n-\n## Tools\n- GitHub CLI for issues/PRs\n- MCP `readOnlyHint` describes whether a tool mutates host/project state such as files, build artifacts, configuration, or external services. Simulator HID/UI actions that only tap, type, press, or gesture inside the simulator may remain `readOnlyHint: true`; do not flip them to `false` merely because app UI state changes.\n- CLI design note: do not rely on CLI session-default writes. CLI is intentionally deterministic for CI/scripting and should use explicit command arguments as the primary input surface.\n- When working on skill sources in `skills/`, use the `skill-creator` skill workflow.\n- After modifying any skill source, run `npx skill-check <skill-directory>` and address all errors/warnings before handoff.\n- Before handoff, run the matching manual Warden review for high-risk changes: runtime/CLI/daemon boundaries → `xcodebuildmcp-runtime-boundary-review`; test infrastructure or harnesses → `xcodebuildmcp-test-boundary-review`; tool manifests, schemas, or contracts → `xcodebuildmcp-tool-contract-review`. Invoke only applicable skills with `warden --skill <name>`.\n-\n## Multi-process filesystem state\n- XcodeBuildMCP explicitly supports multiple concurrent MCP server, daemon, CLI, test, and helper processes for the same or different workspaces.\n- Shared filesystem state under `~/Library/Developer/XcodeBuildMCP` must be multi-process safe.\n- Use workspace-key scoped directories for workspace-owned state.\n- Do not store runtime state under `~/.xcodebuildmcp`; `.xcodebuildmcp/config.yaml` is only project configuration.\n- Use shared lock and atomic-write helpers for mutable shared files.\n- Prefer one-record-per-file registries over shared aggregate files.\n- Cleanup must verify ownership before deleting shared artifacts.\n- User-facing artifact/log paths in final text or structured output must use `displayPath()` from `src/utils/build-preflight.ts`, so paths are cwd-relative when possible or `~/...` instead of absolute home paths. Keep stored files at their real absolute paths; only normalize response/display values.\n\n## Style\n- Keep answers short and concise\n- No emojis in commits, issues, PR comments, or code\n- No fluff or cheerful filler text\n- Technical prose only, be kind but direct (e.g., \"Thanks @user\" not \"Thanks so much @user!\")\n\n## Docs\n- Do not commit transient investigation notes, prompt exports, or scratch analysis docs after the work is complete.\n- If an investigation leaves unresolved follow-up work, move it to a GitHub issue instead of preserving the transient doc in the branch.\n- Structured output JSON schemas are auto-published to the website/public schema mirror when merged; do not manually update public schema copies unless explicitly asked.\n\n### Changelog\nLocation: `CHANGELOG.md`\n\n#### Format\nUse these sections under `## [Unreleased]`:\n- `### Added` - New features\n- `### Changed` - Changes to existing functionality\n- `### Fixed` - Bug fixes\n- `### Removed` - Removed features\n-\n#### Rules\n- Before adding entries, read the full `[Unreleased]` section to see which subsections already exist\n- New entries ALWAYS go under `## [Unreleased]` section\n- Append to existing subsections (e.g., `### Fixed`), do not create duplicates\n- NEVER modify already-released version sections (e.g., `## [0.12.2]`)\n- Each version section is immutable once released\n- NEVER update snapshot fixtures unless asked to do so, these are integration tests, on failure assume code is wrong before questioning the fixture\n-\n#### Attribution\n- **Internal changes (from issues)**: `Fixed foo bar ([#123](https://github.com/cameroncook/XcodeBuildMCP/issues/123))`\n- **External contributions**: `Added feature X ([#456](https://github.com/cameroncook/XcodeBuildMCP/pull/456) by [@username](https://github.com/username))`\n\n\n## Rendering and Streaming Contract\n- Streaming fragments are transient live-progress output only. They may be displayed while a tool is running, but MUST NOT provide final settled MCP/JSON/CLI text.\n- Final settled output MUST render from the final structured/domain result and next-step metadata. If final output needs data, add it to the final result type instead of reading it from fragments.\n- Streaming-capable renderers may observe fragment callbacks only for live progress. Fragment handling must not affect final structured output or final settled text.\n\n## Error Handling\n- Structured errors (domain results with `didError`) are for domain errors only: failures in the user's build/test/device/simulator workflow (compile errors, test failures, missing destinations, etc.).\n- System errors with the MCP server or CLI itself (invalid internal state, unresolvable configuration, infrastructure failures) must NOT be wrapped in structured domain results — let them surface as runtime tool errors so they are clearly distinguishable from workflow outcomes.\n\n## Test Execution Rules\n- **NEVER run the snapshot or smoke test suites without explicit user permission.** They are expensive (~7 min baseline, spawn real `xcodebuild`/`simctl`/`devicectl` processes and can wedge). This covers `npm run test:snapshot`, `npm run test:smoke`, and any direct `vitest run --config vitest.snapshot.config.ts` / `vitest.smoke.config.ts` invocation. Ask first, then run only if the user agrees.\n- The default unit suite (`npm test` / `vitest run`), `npm run typecheck`, `npm run lint`, and `npm run build` are cheap and may be run freely without asking.\n- When running long test suites (snapshot tests, smoke tests), ALWAYS write full output to a log file and read it afterwards. NEVER pipe through `tail` or `grep` directly — that loses output you may need to debug failures.\n- Pattern: `DEVICE_ID=... npm run test:snapshot 2>&1 | tee /tmp/snapshot-results.txt` then read `/tmp/snapshot-results.txt` with the native read tool.\n- If you need a summary, read the log file and grep/filter it — the full output is always preserved.\n- Snapshot test command: `DEVICE_ID=<YOUR_DEVICE_ID> npm run test:snapshot`\n- **Snapshot suite expected duration**: ~7 min baseline (measured at 423s). Anything longer than ~10 min should be treated as a likely hang, not a slow run.\n  - Do NOT just kill the run — first inspect the process tree (`ps -ef | grep -E \"vitest|xcodebuild|simctl|devicectl\"`) to identify what's stuck.\n  - Common hang causes: locked physical device, stale simulator state, `devicectl diagnose` waiting for password, orphaned daemon process.\n  - Capture what you find before killing, so the root cause can be fixed rather than papered over.\n- When asked to review changes or test failures, focus on regressions: behavior changes caused by the branch. Do not treat known/acceptable test flakes, environment setup issues, or nondeterministic tool output churn as regressions unless explicitly asked to investigate them.\n\n## **CRITICAL** Tool Usage Rules **CRITICAL**\n- NEVER use sed/cat to read a file or a range of a file. Always use the native read tool.\n- You MUST read every file you modify in full before editing.\n","category":"root","tokens":2178}]}