{"id":"ios-simulator-skill","name":"ios-simulator-skill","summary":"iOSアプリのテスト、ビルド、自動化のための29本の本番対応スクリプト。セマンティックUIナビゲーション、ビルド自動化、アクセシビリティテスト、シミュレーターライフサイクル管理を提供します。","body":"# iOS Simulator Skill\n\nBuild, test, and automate iOS applications using accessibility-driven navigation and structured data instead of pixel coordinates.\n\n## Quick Start\n\n```bash\n# 1. Check environment\nbash scripts/sim_health_check.sh\n\n# 2. Launch app\npython scripts/app_launcher.py --launch com.example.app\n\n# 3. Map screen to see elements\npython scripts/screen_mapper.py\n\n# 4. Tap button\npython scripts/navigator.py --find-text \"Login\" --tap\n\n# 5. Enter text\npython scripts/navigator.py --find-type TextField --enter-text \"user@example.com\"\n```\n\nAll scripts support `--help` for detailed options and `--json` for machine-readable output.\n\n## Navigation Strategy\n\n**Always prefer the accessibility tree over screenshots for navigation.** The accessibility tree gives you element types, labels, frames, and tap targets — structured data that's cheaper and more reliable than image analysis.\n\nUse this priority:\n1. `screen_mapper.py` → structured element list (5-7 lines, ~10 tokens)\n2. `navigator.py --find-text/--find-type/--find-id` → semantic interaction\n3. Screenshots → only for visual verification, bug reports, or visual diff\n\nScreenshots cost 1,600–6,300 tokens depending on size. The accessibility tree costs 10–50 tokens in default mode.\n\n## 29 Production Scripts\n\n### Build & Development (2 scripts)\n\n1. **build_and_test.py** - Build Xcode projects, run tests, parse results with progressive disclosure\n   - Build with live result streaming\n   - Parse errors and warnings from xcresult bundles\n   - Retrieve detailed build logs on demand\n   - Options: `--project`, `--scheme`, `--clean`, `--test`, `--verbose`, `--json`\n\n2. **log_monitor.py** - Real-time log monitoring with intelligent filtering\n   - Stream logs or capture by duration\n   - Filter by severity (error/warning/info/debug)\n   - Deduplicate repeated messages\n   - Options: `--app`, `--severity`, `--follow`, `--duration`, `--output`, `--json`\n\n### Device State (2 scripts)\n\n3. **appearance.py** - Control simulator appearance: dark mode, Dynamic Type size, and locale/region\n   - Toggle light/dark theme via `xcrun simctl ui`\n   - Set Dynamic Type size with friendly aliases (XS through AX5)\n   - Write locale and region defaults; optional app restart via `--bundle-id`\n   - RTL flagged automatically for ar/he/fa/ur/yi locales\n   - Options: `--theme`, `--text-size`, `--locale`, `--region`, `--reset`, `--bundle-id`, `--udid`, `--json`, `--verbose`\n\n4. **location.py** - Simulate GPS coordinates, named city presets, and GPX scenario playback\n   - Fix a coordinate with `--lat`/`--lng` or pick a city with `--city`\n   - Play a built-in scenario (City Run, Freeway Drive, etc.) via `--gpx <scenario>`\n   - Animate multi-waypoint paths with configurable speed via `--waypoints` and `--speed`\n   - Clear simulated location with `--clear`; list available scenarios with `--list-scenarios`\n   - Options: `--lat`, `--lng`, `--city`, `--gpx`, `--waypoints`, `--speed`, `--clear`, `--list-scenarios`, `--udid`, `--json`, `--verbose`\n\n### Navigation & Interaction (5 scripts)\n\n5. **screen_mapper.py** - Analyze current screen and list interactive elements\n   - Element type breakdown\n   - Interactive button list\n   - Text field status\n   - Options: `--verbose`, `--hints`, `--json`\n\n6. **navigator.py** - Find and interact with elements semantically\n   - Find by text (fuzzy matching)\n   - Find by element type\n   - Find by accessibility ID\n   - Enter text or tap elements\n   - Options: `--find-text`, `--find-type`, `--find-id`, `--tap`, `--enter-text`, `--json`\n\n7. **gesture.py** - Perform swipes, scrolls, pinches, and complex gestures\n   - Directional swipes (up/down/left/right)\n   - Multi-swipe scrolling\n   - Pinch zoom\n   - Long press\n   - Pull to refresh\n   - Options: `--swipe`, `--scroll`, `--pinch`, `--long-press`, `--refresh`, `--json`\n\n8. **keyboard.py** - Text input and hardware button control\n   - Type text (fast or slow)\n   - Special keys (return, delete, tab, space, arrows)\n   - Hardware buttons (home, lock, volume, screenshot)\n   - Key combinations\n   - Options: `--type`, `--key`, `--button`, `--slow`, `--clear`, `--dismiss`, `--json`\n\n9. **app_launcher.py** - App lifecycle management\n   - Launch apps by bundle ID\n   - Terminate apps\n   - Install/uninstall from .app bundles\n   - Deep link navigation\n   - List installed apps\n   - Check app state\n   - Pass launch arguments (`--args`) and environment variables (`--env KEY=VALUE`, injected as `SIMCTL_CHILD_*`) to the app on launch/restart\n   - Options: `--launch`, `--terminate`, `--restart`, `--install`, `--uninstall`, `--open-url`, `--list`, `--state`, `--args`, `--env`, `--wait-for-debugger`\n\n### Testing & Analysis (9 scripts)\n\n10. **accessibility_audit.py** - Check WCAG compliance on current screen\n    - Critical issues (missing labels, empty buttons, no alt text)\n    - Warnings (missing hints, small touch targets)\n    - Info (missing IDs, deep nesting)\n    - Options: `--verbose`, `--output`, `--json`\n\n11. **visual_diff.py** - Compare two screenshots for visual changes\n    - Pixel-by-pixel comparison\n    - Threshold-based pass/fail\n    - Generate diff images\n    - Options: `--threshold`, `--output`, `--details`, `--json`\n\n12. **test_recorder.py** - Automatically document test execution\n    - Capture screenshots and accessibility trees per step\n    - Generate markdown reports with timing data\n    - Options: `--test-name`, `--output`, `--verbose`, `--json`\n\n13. **app_state_capture.py** - Create comprehensive debugging snapshots\n    - Screenshot, UI hierarchy, app logs, device info\n    - Markdown summary for bug reports\n    - Options: `--app-bundle-id`, `--output`, `--log-lines`, `--json`\n\n14. **sim_health_check.sh** - Verify environment is properly configured\n    - Check macOS, Xcode, simctl, IDB, Python\n    - List available and booted simulators\n    - Verify Python packages (Pillow)\n\n15. **model_inspector.py** - Inspect Core Data and SwiftData models from project files\n    - Parse .xcdatamodeld packages (entities, attributes, relationships)\n    - Detect model versions and current active version\n    - Best-effort SwiftData @Model class extraction\n    - Raw source dump for any model on demand (`--raw ModelName`)\n    - Options: `--project-path`, `--core-data-only`, `--swiftdata-only`, `--show-versions`, `--raw`, `--verbose`, `--json`\n\n16. **container.py** - Inspect app sandbox: files, UserDefaults, and Core Data store paths\n    - List data container files at configurable depth via `--ls`\n    - Read files with auto-detected plist decoding via `--cat` (large files cached)\n    - Dump UserDefaults as key=value or JSON via `--userdefaults`\n    - Locate `.sqlite` / `.sqlite-wal` / `.sqlite-shm` stores via `--core-data-path`\n    - Export full container snapshot via `--export`\n    - Options: `--ls`, `--cat`, `--userdefaults`, `--core-data-path`, `--export`, `--udid`, `--json`, `--verbose`\n\n17. **hang_watcher.py** (HangBuster) - Record + summarise os_log hang events with progressive disclosure\n    - **Session mode (HangBuster, agent-native):** start a detached recorder, interact with the simulator, stop for a token-tight summary\n      - `--start` → returns a session ID; detached worker normalises + thresholds events on the fly\n      - `--stop SESSION_ID` → emits ~80–120 token L1 summary (header + top-N clusters + drill hint)\n      - `--get-details SESSION_ID [--cluster N | --raw]` → L2 full clusters or L3 per-event detail\n      - `--list-sessions` / `--clear-sessions [--older-than 24h]` / `--diff A B` (cross-session regression report)\n      - Filter pipeline: parse → normalise → threshold → bucket → cluster → aggregate → rank → format (in `common/hang_pipeline.py`)\n      - `--budget-tokens N` picks the densest level (L0/L1/L2) that fits; `--terse` forces L0\n      - `--auto-sample` captures a main-thread stack on first event per cluster (soft dependency: `main_thread_sampler.py` #62; graceful no-op if absent)\n    - **Raw capture mode (full fidelity for `jq` exploration):** skip the clustering pipeline, dump every matching log line verbatim to `raw.ndjson`\n      - `--start --raw-capture [--max-size-mb 10] [--no-gzip]` — spawns `log stream --style ndjson`\n      - Per-session size cap (`--max-size-mb`, default 10) — worker stops cleanly on cap; `extras.truncated=true`\n      - `--stop` gzips `raw.ndjson` → `raw.ndjson.gz` (~15–19× compression; `--no-gzip` opts out)\n      - `--get-details SESSION_ID` on a raw session prints the path with a `zcat | jq ...` hint\n    - **Resilience (auto-restart on stream death):** EOF or subprocess death triggers a `stream_died` event then a bounded restart with 2s backoff. After `IOS_SIM_HANG_MAX_RESTARTS` (default 3) the session is marked `crashed`, never left in stale `running` state. `--list-sessions` shows `capture=Xs` and `restarts=N`.\n    - **Cleanup is automatic:** TTL prune (`IOS_SIM_HANG_SESSION_TTL_HOURS`, default 24h) + aggregate cap (`IOS_SIM_HANG_TOTAL_CAP_MB`, default 100 MB, oldest-first eviction) both run on every `--start`.\n    - **Legacy modes (unchanged for backward compat):** `--watch [--duration N]` (live stream) and `--since 5m` (historical)\n    - Filters: `--bundle-id` (post-parse — hang capture stays simulator-global so RunningBoard/SpringBoard events are kept), `--predicate` (also via `IOS_SIM_HANG_PREDICATE`)\n    - All output supports `--json`; session storage at `~/.ios-simulator-skill/sessions/<id>/{meta.json,events.jsonl,summary.json,raw.ndjson.gz}`\n\n    **Quick start (summarised mode):**\n    ```bash\n    SID=$(python scripts/hang_watcher.py --start --min-hang-ms 200)\n    # ... interact with the simulator (open sheets, scroll, navigate) ...\n    python scripts/hang_watcher.py --stop $SID                  # token-tight L1 summary\n    python scripts/hang_watcher.py --get-details $SID --cluster 1  # drill into cluster 1\n    python scripts/hang_watcher.py --diff $SID_BASELINE $SID    # cross-session regression\n    ```\n\n    **Quick start (raw capture + `jq` exploration):**\n    ```bash\n    SID=$(python scripts/hang_watcher.py --start --raw-capture --max-size-mb 5)\n    # ... interact with the simulator ...\n    python scripts/hang_watcher.py --stop $SID\n    # → \"Session ...: raw mode, 737 lines, 0.96 MB → 0.05 MB gzipped\"\n\n    # Top processes by event count:\n    zcat ~/.ios-simulator-skill/sessions/$SID/raw.ndjson.gz \\\n      | jq -s 'group_by(.processImagePath) | map({proc: (.[0].processImagePath | split(\"/\") | last), n: length}) | sort_by(-.n) | .[:5]'\n\n    # All RunningBoard assertion invalidations:\n    zcat .../raw.ndjson.gz | jq -c 'select(.subsystem == \"com.apple.runningboard\" and (.eventMessage | startswith(\"Invalidating\")))'\n\n    # Hangs per minute:\n    zcat .../raw.ndjson.gz | jq -r '.timestamp[:16]' | sort | uniq -c\n    ```\n\n18. **localization_audit.py** - Detect string catalog gaps, missing keys, and placeholder mismatches\n    - Report missing and `needs_review`/`new` keys per locale in `.xcstrings` catalogs\n    - Cross-reference catalog keys against Swift source (`String(localized:)` / `NSLocalizedString`) via `--source`\n    - Flag placeholder count mismatches (`%d`, `%@`, `%s`, `%lld`) across locales\n    - Legacy `.strings` and `.stringsdict` support via `plistlib`\n    - CI-friendly `--strict` exits 2 on any finding\n    - Options: `--catalog`, `--source`, `--locale`, `--strict`, `--json`, `--verbose`\n\n### Advanced Testing & Permissions (4 scripts)\n\n19. **clipboard.py** - Manage simulator clipboard for paste testing\n    - Copy text to clipboard\n    - Test paste flows without manual entry\n    - Options: `--copy`, `--test-name`, `--expected`, `--json`\n\n20. **status_bar.py** - Override simulator status bar appearance\n    - Presets: clean (9:41, 100% battery), testing (11:11, 50%), low-battery (20%), airplane (offline)\n    - Custom time, network, battery, WiFi settings\n    - Options: `--preset`, `--time`, `--data-network`, `--battery-level`, `--clear`, `--json`\n\n21. **push_notification.py** - Send simulated push notifications\n    - Simple mode (title + body + badge)\n    - Custom JSON payloads\n    - Test notification handling and deep links\n    - Options: `--bundle-id`, `--title`, `--body`, `--badge`, `--payload`, `--json`\n\n22. **privacy_manager.py** - Grant, revoke, and reset app permissions\n    - 13 supported services (camera, microphone, location, contacts, photos, calendar, health, etc.)\n    - Batch operations (comma-separated services)\n    - Audit trail with test scenario tracking\n    - Options: `--bundle-id`, `--grant`, `--revoke`, `--reset`, `--list`, `--json`\n\n### Simulator Discovery (2 scripts)\n\n23. **sim_list.py** - List simulators with progressive disclosure\n    - Concise summary by default (total / available / booted)\n    - Full details on demand via cache IDs\n    - Filter by device type\n    - Suggest recommended simulators with `--suggest`\n    - 96% token reduction vs raw `simctl list` (57k → 2k tokens)\n    - Options: `--get-details`, `--suggest`, `--device-type`, `--json`\n\n24. **simulator_selector.py** - Suggest the best simulator for the job\n    - Ranks candidates by recent use (from `config.json`), latest iOS, common test models, and boot status\n    - List all available simulators with `--list`\n    - Boot a selected simulator directly with `--boot`\n    - JSON output for programmatic use\n    - Options: `--suggest`, `--list`, `--boot`, `--json`\n\n### Device Lifecycle Management (5 scripts)\n\n25. **simctl_boot.py** - Boot simulators with optional readiness verification\n    - Boot by UDID or device name\n    - Wait for device ready with timeout\n    - Batch boot operations (--all, --type)\n    - Performance timing\n    - Options: `--udid`, `--name`, `--wait-ready`, `--timeout`, `--all`, `--type`, `--json`\n\n26. **simctl_shutdown.py** - Gracefully shutdown simulators\n    - Shutdown by UDID or device name\n    - Optional verification of shutdown completion\n    - Batch shutdown operations\n    - Options: `--udid`, `--name`, `--verify`, `--timeout`, `--all`, `--type`, `--json`\n\n27. **simctl_create.py** - Create simulators dynamically\n    - Create by device type and iOS version\n    - List available device types and runtimes\n    - Custom device naming\n    - Returns UDID for CI/CD integration\n    - Options: `--device`, `--runtime`, `--name`, `--list-devices`, `--list-runtimes`, `--json`\n\n28. **simctl_delete.py** - Permanently delete simulators\n    - Delete by UDID or device name\n    - Safety confirmation by default (skip with --yes)\n    - Batch delete operations\n    - Smart deletion (--old N to keep N per device type)\n    - Options: `--udid`, `--name`, `--yes`, `--all`, `--type`, `--old`, `--json`\n\n29. **simctl_erase.py** - Factory reset simulators without deletion\n    - Preserve device UUID (faster than delete+create)\n    - Erase all, by type, or booted simulators\n    - Optional verification\n    - Options: `--udid`, `--name`, `--verify`, `--timeout`, `--all`, `--type`, `--booted`, `--json`\n\n## Common Patterns\n\n**Auto-UDID Detection**: Most scripts auto-detect the booted simulator if --udid is not provided.\n\n**Device Name Resolution**: Use device names (e.g., \"iPhone 16 Pro\") instead of UDIDs - scripts resolve automatically.\n\n**Batch Operations**: Many scripts support `--all` for all simulators or `--type iPhone` for device type filtering.\n\n**Output Formats**: Default is concise human-readable output. Use `--json` for machine-readable output in CI/CD.\n\n**Help**: All scripts support `--help` for detailed options and examples.\n\n**Screenshot Sizing**: Screenshots are resized to save tokens. Presets: `full` (3-4 tiles, ~5K tokens), `half` (1 tile, ~1.6K tokens, default), `quarter` (1 tile, ~800 tokens, less detail). Use `quarter` for quick visual checks, `half` for readable UI, `full` only when pixel-level detail matters. Scripts that capture screenshots (`app_state_capture.py`, `test_recorder.py`) default to `half`.\n\n## Typical Workflow\n\n1. Verify environment: `bash scripts/sim_health_check.sh`\n2. Launch app: `python scripts/app_launcher.py --launch com.example.app`\n3. Analyze screen: `python scripts/screen_mapper.py`\n4. Interact: `python scripts/navigator.py --find-text \"Button\" --tap`\n5. Verify: `python scripts/accessibility_audit.py`\n6. Debug if needed: `python scripts/app_state_capture.py --app-bundle-id com.example.app`\n\n## Configuration\n\nMost operational limits can be tuned via environment variables. Defaults work for typical local development; raise them for slow CI runners, large monorepo builds, or accessibility audits on complex screens.\n\n| Variable | Default | Controls |\n|---|---|---|\n| `IOS_SIM_A11Y_LABEL_MAX` | `80` | Max chars of `AXLabel` retained in accessibility audit output |\n| `IOS_SIM_A11Y_TOP_ISSUES` | `10` | Top accessibility issues surfaced per audit |\n| `IOS_SIM_APPS_PREVIEW` | `30` | App entries listed by `app_launcher.py` before truncation |\n| `IOS_SIM_BOOT_SUBPROCESS_TIMEOUT` | `60` | Timeout for the `simctl boot` subprocess itself (seconds) |\n| `IOS_SIM_BOOT_TIMEOUT` | `300` | Wait-for-ready timeout after boot (seconds) |\n| `IOS_SIM_BUILD_JSON_CAP` | `50` | Max build errors / failed tests in JSON output |\n| `IOS_SIM_BUILD_LOG_PREVIEW` | `4000` | Chars of build log preview in default output |\n| `IOS_SIM_BUILD_TIMEOUT` | `1800` | Max seconds for an `xcodebuild build` invocation before kill |\n| `IOS_SIM_INTROSPECT_TIMEOUT` | `60` | Timeout for `xcodebuild -list` and `simctl list` lookups (seconds) |\n| `IOS_SIM_TEST_TIMEOUT` | `2700` | Max seconds for an `xcodebuild test` invocation before kill |\n| `IOS_SIM_BUILD_SUMMARY_CAP` | `15` | Errors/failures in default build summary |\n| `IOS_SIM_BUILD_VERBOSE_CAP` | `100` | Errors/warnings in verbose build output |\n| `IOS_SIM_CACHE_MAX_ENTRIES` | `500` | Max entries in progressive disclosure cache (LRU eviction) |\n| `IOS_SIM_CACHE_TTL_HOURS` | `1` | Cache entry expiration |\n| `IOS_SIM_ERASE_TIMEOUT` | `90` | Wait-for-erase timeout (seconds) |\n| `IOS_SIM_HANG_PREDICATE` | _(default)_ | Override the `os_log` predicate used by `hang_watcher.py` (default catches RunningBoard kills + \"Hang detected\" + main-thread hangs). Hang events originate from system daemons (RunningBoard, SpringBoard) so the predicate stays simulator-global — `--bundle-id` is applied post-parse, not ANDed in. |\n| `IOS_SIM_HANG_MIN_MS` | `250` | HangBuster threshold — events below this duration never reach disk (smaller = more sensitive, larger summaries) |\n| `IOS_SIM_HANG_SESSION_TTL_HOURS` | `24` | HangBuster session prune age; pruning runs on every `--start` |\n| `IOS_SIM_HANG_DEFAULT_TOP_N` | `3` | Default top-N clusters in `--stop` L1 output |\n| `IOS_SIM_HANG_BUDGET_TOKENS` | _(unset)_ | Default token budget for `--stop` (picks L0/L1/L2 to fit) |\n| `IOS_SIM_HANG_MAX_RESTARTS` | `3` | HangBuster worker: max `log stream` respawn attempts on EOF/subprocess death before the session is marked `crashed` |\n| `IOS_SIM_HANG_TOTAL_CAP_MB` | `100` | HangBuster aggregate disk cap. When total session-state exceeds this on `--start`, oldest sessions are dropped first. Set to `0` to disable. |\n| `IOS_SIM_LOG_JSON_CAP` | `100` | Max errors/warnings in `log_monitor.py` JSON output |\n| `IOS_SIM_LOG_LINE_MAX` | `300` | Per-line truncation in log summaries |\n| `IOS_SIM_LOG_TAIL` | `200` | Lines of log tail in verbose / sample output |\n| `IOS_SIM_LOG_TEXT_SUMMARY` | `15` | Errors/warnings shown in text-mode log summary |\n| `IOS_SIM_MAX_ELEMENTS` | `25` | Tappable elements listed by `navigator.py` |\n| `IOS_SIM_POLL_INTERVAL` | `0.5` | Boot/erase state polling interval (seconds) |\n| `IOS_SIM_RELAUNCH_DELAY_MS` | `1000` | Delay between terminate and re-launch in `app_launcher.py` |\n| `IOS_SIM_SCREEN_BUTTONS_PREVIEW` | `15` | Button names listed by `screen_mapper.py` |\n| `IOS_SIM_SCREEN_SECTION_ITEMS` | `10` | Items per section shown by `screen_mapper.py` |\n| `IOS_SIM_STATE_SUBPROCESS_TIMEOUT` | `15` | Subprocess timeout in `app_state_capture.py` (seconds) |\n| `IOS_SIM_TAP_SETTLE_MS` | `500` | Post-tap settle delay in `navigator.py` |\n\nExample:\n\n```bash\n# Slow GitHub Actions runner: give boot 10 minutes\nIOS_SIM_BOOT_TIMEOUT=600 python scripts/simctl_boot.py --wait-ready\n```\n\n## Requirements\n\n- macOS 12+\n- Xcode Command Line Tools\n- Python 3\n- IDB (optional, for interactive features)\n\n## Documentation\n\n- **SKILL.md** (this file) - Script reference and quick start\n- **README.md** - Installation and examples\n- **CLAUDE.md** - Architecture and implementation details\n- **references/** - Deep documentation on specific topics\n- **examples/** - Complete automation workflows\n\n## Key Design Principles\n\n**Semantic Navigation**: Find elements by meaning (text, type, ID) not pixel coordinates. Survives UI changes.\n\n**Token Efficiency**: Concise default output (3-5 lines) with optional verbose and JSON modes for detailed results.\n\n**Accessibility-First**: Built on standard accessibility APIs for reliability and compatibility.\n\n**Zero Configuration**: Works immediately on any macOS with Xcode. No setup required.\n\n**Structured Data**: Scripts output JSON or formatted text, not raw logs. Easy to parse and integrate.\n\n**Auto-Learning**: Build system remembers your device preference. Configuration stored per-project.\n\n---\n\nUse these scripts directly or let Claude Code invoke them automatically when your request matches the skill description.","author":"@conorluddy","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/conorluddy/ios-simulator-skill/tree/main/ios-simulator-skill/skills/ios-simulator-skill","license":"MIT","category":"coding","lang":"en","tokens":5587,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"scripts/accessibility_audit.py","size":10561,"sha256":"23ea6ed52689fb5b7b109227d9c5b653e972e812a01eb17c13cd7a59bff12ee3"},{"path":"scripts/appearance.py","size":11591,"sha256":"97db9296f957501b0c3780d739c45986ba9c68783329e76cb915688e2bebf139"},{"path":"scripts/app_launcher.py","size":12161,"sha256":"f96163167bea4f71fae42905f1cfa7fe62e54a0213092328c86ae2189b757b23"},{"path":"scripts/app_state_capture.py","size":13485,"sha256":"aae5671fee3d7ecce5d77f8901f47c4449c5cde06f524480b47158437b1aaeab"},{"path":"scripts/build_and_test.py","size":12189,"sha256":"fb4e85618ab0290bfaa1e391fb47ed2de18fa3cbeda3af7f0c1648ab2aa43541"},{"path":"scripts/clipboard.py","size":2669,"sha256":"a322b34e833c4e54e464129a128703f554f2a82a880a8f3f91bc44abec4a92ce"},{"path":"scripts/common/cache_utils.py","size":9517,"sha256":"b01ef1fd4d7661ca23693524b73f286e811f12f759d12a3c0fdfbcc0c3a2821e"},{"path":"scripts/common/device_utils.py","size":14930,"sha256":"011eb71cd9dfce80366ff7d094796e055c5130a20c7305f352143717993dc518"},{"path":"scripts/common/env_config.py","size":1132,"sha256":"c23f742c74ae65781c893cc74c00ed7e6ffab08b26fb6ac5e5b16dc1cf0ee79a"},{"path":"scripts/common/hang_pipeline.py","size":30351,"sha256":"1d049974996d29ab822087b5eb5c1eb05e8cdb595d46b90e35bf279a77949dc6"},{"path":"scripts/common/hang_sessions.py","size":18360,"sha256":"82edd8aced216eef0220f92c03125d241a353ed6ea92e566ed14758ecdc66190"},{"path":"scripts/common/idb_utils.py","size":5393,"sha256":"2569b55a7ced7d87bdf27924ede95575aac4968860d94dbec6ae499347b5aa6e"},{"path":"scripts/common/__init__.py","size":1634,"sha256":"b95d91b6d145324a93e03d2232615514780ad81a41934cb4ad373f28b2514143"},{"path":"scripts/common/screenshot_utils.py","size":10229,"sha256":"4a89e0b54acfbe4802ad3797b05ad6e28cdff52f3e97534de8957b639a39c44f"},{"path":"scripts/container.py","size":23230,"sha256":"7bbe505a9067150a0c0d96282db729cffec2440c5c9c976740356d5ced7bfbe7"},{"path":"scripts/gesture.py","size":12628,"sha256":"fe4b269e3fe100c84454ddd21a1ead60c32fb5dc809343363d2dc335898c8cd5"},{"path":"scripts/hang_watcher.py","size":57890,"sha256":"725717dccbe66814d713748151e4c456de20f1cd6e90c8ac005228b9d5e2358c"},{"path":"scripts/keyboard.py","size":11772,"sha256":"12ae50a87eb3f76925750dfe0d3880bb1cb1534039363ee4110d3bf30bc2311f"},{"path":"scripts/localization_audit.py","size":16618,"sha256":"75652120935beb74589c749740f557a83554c1366e97503973aeab04a02d2393"},{"path":"scripts/location.py","size":15783,"sha256":"c0d1d1dec98c50547a4d19036e12d002be6d84ad6dbf6e1a6ce27061f9616211"},{"path":"scripts/log_monitor.py","size":15157,"sha256":"ab4a060758f54e6384ab93d5a8a3c94aabfaa151046688ddf2388681a2184795"},{"path":"scripts/model_inspector.py","size":22215,"sha256":"4c9338e6f95abfdae825f7354f49b7593238b948dbeaddd8ce462211082774f4"},{"path":"scripts/navigator.py","size":14519,"sha256":"4b3dec8ce63c5b9efa6aa4df4c328ea7529d2a74786e6c7ebc618841f0e11335"},{"path":"scripts/privacy_manager.py","size":8944,"sha256":"67dfd9749da2edbb84186d32022124ac317e8aa0c69b94350caaadc6cd5a2dc4"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[{"code":"net.endpoints","kind":"exfiltration","excerpt":"developer.apple.com","message":"bundled scripts reach 1 external host(s)","severity":"warn"}],"scannedAt":"2026-08-22","hasScripts":true,"networkEndpoints":["developer.apple.com"]}}