本文へ移動
cccskills
無料GitHub で公開

software-ios-runtime-debugging

Proves iOS build/install/launch truth and triages hangs, crashes, jank, memory kills, and stale builds. Use when simulator, bundle, or runtime performance state is in doubt.

インストール方法を見る

含まれるファイル(11)

  • SKILL.md22.2 KB
  • agents/openai.yaml603 B
  • assets/template-ios-runtime-debug-request.md593 B
  • data/sources.json9.0 KB
  • learnings.consolidated.md606 B
  • learnings.md1.5 KB
  • references/runtime-performance-triage.md21.7 KB
  • references/runtime-proof-loop.md914 B
  • references/stale-build-triage.md4.4 KB
  • references/swift-concurrency-crash-triage.md19.2 KB
  • references/xcodegen-resource-packaging.md2.0 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Native iOS Runtime Debugging

Use this skill when the core problem is not app architecture or visual design, but runtime truth: did the current binary build, install, launch, and render on the intended simulator or device — and once that's proven, is the live complaint a hang, a crash, jank, a memory kill, or a launch-time regression?

This skill owns stale-build suspicion, simulator drift, malformed .app bundles, missing executables, XcodeGen resource packaging mistakes, and the proof loop required before trusting screenshots, UI behavior, or downstream API/auth debugging. It also owns classifying and diagnosing live runtime performance and stability complaints once that proof exists: hangs and watchdog kills, crash symbolication, jank against frame budgets, Jetsam/memory pressure, and launch-time measurement traps.

Quick Reference

SymptomFirst MoveNotes
Screenshot does not match sourcePreserve repro, then replace/install and launch the known artifactReset or uninstall only after preserving evidence and isolating the suspected layer
Tool cannot read a simulator screenshot temp pathRe-capture from the current simulatorTemp screenshot files expire or move. Do not treat a missing temp path as invalidating the user's visible report
Install says app is missing executableInspect built .app bundleVerify Info.plist and executable path before touching Swift
Simulator behaves inconsistentlyProve destination, boot, install, launch stateDo not debate UI until runtime truth exists
Auth appears to succeed but next screen is unauthenticatedInspect token persistence and auth propagation after fresh launchDo not redesign UI first
Push works on Xcode build but fails on TestFlightInspect archived entitlements and newest backend device rowWrong APNs environment is more likely than feature-code regression
APNs returns BadDeviceToken for older installsCheck device-row environment and staleness firstOften stale tokens or env mismatch, not a current-device blocker
Push tap opens to black screen, freeze, or _performBlockAfterCATransactionCommitSynchronizesStart at references/swift-concurrency-crash-triage.md; web-search the exact symbol before any code reviewRoot-cause candidates include a nonisolated delegate or completion callback mutating main-actor UI state, nested actor hops, or SceneKit updates. Task { } inherits the actor context where its closure is formed; inspect that creation context rather than assuming every task is detached. Separate transport proof from push-open proof
UITest env var is present but the wrong screen is capturedVerify branch execution and a screen-specific accessibility markerProcess env alone is not runtime proof
Route state changes but the destination never appearsPrefer a direct presentation hook for isolated proofNavigationStack state is not the same as a visible screen
"cannot find X in scope" after adding new filesXcodeGen project not regeneratedRegenerate: scripts/generate-xcodeproj.sh or xcodegen generate
"cannot find X in scope" in a .pbxproj project after adding filesNew file not added to target membershipAdd the file to the target before touching Swift feature code
CoreSimulatorService "Connection refused"Simulator service crashedUse generic/platform=iOS destination instead of simulator; or restart Simulator.app
DerivedData write failure / sandbox errorCheck the denied path and active toolchainUse a writable project-specific DerivedData path; if platform services need wider access, use the runtime's scoped approval mechanism or Xcode.app
Swift "failed to produce diagnostic"Type inference overload in complex ViewBuilderSimplify: inline optional views, remove AnyView, split large computed properties
"Copy Bundle Resources contains entitlements" warningCheck whether the entitlements file was added as a bundled resourceKeep entitlements in signing configuration only; exclude them from copied app resources
Background xcodebuild … | tail -N output file stays 0 bytes until exitLooks like a stall; not onetail emits only when its input stream closes. In background execution, the output file appears empty for the entire build run, which looks stuck but is actually normal. Alternatives: 2>&1 | tee output.log for live progress, or drop tail entirely and accept the full output. The tail -N recipe trades live visibility for clean final output — pick based on whether you need progress signals during the run
Ld failed / missing file after project generationCheck generated paths and target membership, then try an isolated clean buildCache drift is a hypothesis; a missing source or resource remains missing after a cache reset
App terminates with 0x8badf00d / WATCHDOG reasonNot a code crash — a callback (scene-create, background task) failed to return in timeRead the reason string for which subsystem timed out; treat as a hang that ran out the clock. See references/runtime-performance-triage.md
Process still alive but input goes unansweredHang, not crash — no crash log will existCapture a main-thread backtrace via the Hangs instrument or lldb bt all; do not search for a nonexistent crash report
Scrolling or animation stutters but the app stays responsiveJank — a missed frame budget, not a hangProfile with Hitches/SwiftUI instrument, not the Hangs template. 60 Hz = 16.67 ms/frame, ProMotion 120 Hz = 8.33 ms/frame (adaptive; measure the target device's active refresh rate)
App disappears with no crash log after memory growthSuspect a Jetsam killConfirm via a jetsam event report or the memory diagnostic available in the target SDK; do not assume a normal crash was swallowed. Apple publishes no official per-device memory-limit table — treat any specific MB figure as empirical
"Main thread blocked" in a trace, but the code path looks finePossible priority inversion, not main-thread overworkCheck the QoS of every thread in the backtrace before moving work off main; a low-priority thread holding a lock the main thread needs looks identical to a slow main-thread task
Launch-time regression only shows up in some samplesPrewarming skewThe OS may prewarm the process before the user taps the icon — loads linked libraries, then suspends before any app code runs. No documented API detects it. Treat a single launch sample as unverified — use MetricKit's launch-type-bucketed metrics or a large field sample
MetricKit payload never arrives during local testingDistinguish field delivery from simulated payloadsOn a physical device, Xcode's Debug > Simulate MetricKit Payloads tests report handling with sample data; it does not measure the app's performance

When to Use This Skill

Use this skill to:

  • Prove the current binary builds, installs, and launches on the intended target
  • Diagnose stale installs or stale screenshots in simulator-driven workflows
  • Inspect built .app bundles when installation fails
  • Debug simulator boot, shutdown, destination, and launch-state drift
  • Investigate XcodeGen, resource packaging, bundle executable, or Info.plist path problems
  • Establish runtime truth before routing to feature implementation, design, or test skills
  • Classify a live complaint as a hang, a crash, jank, a memory (Jetsam) kill, or a launch-time regression before choosing a fix
  • Read Instruments, MetricKit, or crash-symbolication output and judge whether a lab fix will actually move field metrics

Core Workflow

  1. Discover the project entrypoint: workspace or project, scheme, configuration, destination, and bundle ID.
  2. Check the callable tool inventory against Agent Tool Selection; record the selected Xcode/toolchain and destination.
  3. Build the app with the simplest reproducible command.
  4. Inspect the built .app: verify Info.plist, executable name, and expected bundle contents.
  5. Preserve the reproduction before resetting anything: record launch arguments, deep link, account, local data dependency, installed bundle version/signature, logs, and the visible state.
  6. Install or upgrade the freshly built bundle while preserving its data container where the target supports that path. Uninstall/reset only when replacement fails, signing differs, migration/state corruption is the suspected layer, or the repro evidence has already been captured.
  7. Launch the freshly installed app and capture proof: screenshot, UI hierarchy, launch logs, and a target-screen-specific marker when isolating a route.
  8. Only after the app is freshly running, debug feature behavior, design, auth, or API issues.
    • For push issues, also prove the binary origin (Xcode debug vs TestFlight), the signed APNs entitlement on archive builds, and the newest backend device-row environment before chasing app logic.
  • Treat transport proof and push-open proof as separate gates: APNs success and a visible banner do not prove tapping is safe.
  1. Route onward:

Runtime Proof Loop

  • Prefer one bounded loop: discover -> build -> inspect bundle -> preserve repro -> replace/install -> launch -> capture evidence
  • Escalate separately to a clean build, container reset, or uninstall. Record which reset changes the symptom; that difference distinguishes build drift from persisted-state or migration defects.
  • If any step fails, stop there and fix that layer before moving deeper.
  • Do not trust screenshots from a simulator session that has not been tied to the current build.
  • Do not trust “build succeeded” on its own; install and launch proof still matter.
  • Do not stop on an unreadable temp screenshot path. Re-capture a screenshot, inspect the UI tree, or use the user's exact visible symptom to drive a focused source-level check.
  • Verify isolated launch hooks at three levels: the env reached the process, the intended app branch executed, and the target screen is present through a screen-specific accessibility marker.
  • If a screenshot or UI tree contradicts the expected launch hook, inspect only the named non-secret launch-hook flag values through a scoped app diagnostic and then verify the marker before trusting the capture.

Agent Tool Selection

Choose the smallest callable tool that covers the evidence needed. A documented tool is not proof that this runtime exposes it.

NeedDefaultCapability check / fallback
Build through an open Xcode projectApple's Xcode MCP bridgeCheck Xcode Intelligence access and the connected tool inventory; Apple documents xcrun mcpbridge. Use CLI if the bridge is unavailable. Apple guide
Simulator build/install/launch/log/UI loopExisting XcodeBuildMCP or MobileBuildMCP connectionUpstream is MobileBuildMCP; inspect the installed tool inventory and configuration rather than assume old tool names still work. Fall back to xcodebuild + simctl.
Paused-process stack, variables, steppingLLDB or its MCP interfaceLLVM's lldb-mcp requires a compatible installed debugger; verify availability and a stopped process. MCP debugger output excludes the debuggee's stdout.
Physical-device install/launch/controlxcrun devicectlUse xcrun devicectl help for the installed command surface and check device/signing state. It does not replace symbolication or Instruments. Apple CLI reference
Result bundle or performance tracexcresulttool or xctraceRead installed help for result/trace schemas; keep raw artifacts alongside filtered output.

Project scaffolding, buildable folders, warnings policies, and Xcode Cloud setup belong to software-ios-native. Server auth, writes, and deployment behavior belong to software-backend; request/response contracts belong to dev-api-design.

Stale-Build Heuristics

SymptomSuspectAction
UI doesn't match current sourceStale installPreserve repro; replace/install the verified bundle
App shows old screen after rebuildCached installInspect artifact and install logs; replace before reset
Build succeeded but app looks oldStale DerivedData or incremental build errorCheck install logs; do not keep editing feature code
Simulator already running, UI state surprisingPrevious simulator sessionRe-prove install and launch before reasoning about app state
Push works on Xcode build, fails on TestFlightAPNs environment mismatchLocal → sandbox; TestFlight / App Store → production; verify per-device row
Transport works, app freezes or crashes on push tapNotification-open path: delegate isolation, route staging, off-main mutationRoute to swift-concurrency-crash-triage.md
dataCorrupted + <!DOCTYPE html> responseAPI routing / auth bugLog URL, curl it; do not conflate with push-open crashes
Route state updates but destination never appearsPresentation hook not reachedUse a direct presentation hook to prove the screen in isolation
Simulator unresponsive (CoreSimulatorService errors)Simulator service crashedSwitch to generic/platform=iOS for compile-only verification

See references/stale-build-triage.md.

Packaging and Bundle Health

  • When installation fails, inspect the built .app bundle directly.
  • Confirm:
    • Info.plist has expanded values, not unresolved placeholders
    • the executable exists at the path referenced by the bundle metadata
    • expected resources are copied as resources, not malformed folder references
  • If the error mentions missing bundle executable, treat it as a packaging issue first.

See references/xcodegen-resource-packaging.md.

Swift Concurrency Hop Rule

In a @MainActor context, code after an await resumes on the MainActor. Swift does not lose isolation across an await (SE-0338). Under the default settings, the awaited nonisolated async function itself runs off the main actor. If that function reaches main-actor state (possible through @unchecked Sendable or minimally checked code), that access is the bug; a missed hop back is not. Swift 6.2's approachable-concurrency setting, or the NonisolatedNonsendingByDefault upcoming feature (SE-0461), makes nonisolated async functions run on the caller's actor unless marked @concurrent. Check the project's build settings before reasoning about where a function runs. Crash patterns and fixes are in references/swift-concurrency-crash-triage.md.

Runtime Performance Triage

Once build/install/launch truth is established, a live complaint still needs to be classified before you touch code. Hang, watchdog kill, jank, Jetsam kill, and launch-time regression have different evidence and different fix ladders — do not default to "read the code" until the failure class has a name.

  • Walk the triage order: terminated-with-crash-log → terminated-with-0x8badf00d/watchdog → alive-but-unresponsive (hang) → alive-and-responsive-but-stuttering (jank) → disappeared-with-no-crash-log (Jetsam) → slow-to-first-frame (launch).
  • Watch for the two most common misdiagnoses: blaming "main thread blocked" when it's priority inversion on a lower-QoS thread holding a shared lock, and trusting a single launch-time sample that may have been prewarmed.
  • Instruments, MetricKit, hang/watchdog thresholds, Jetsam behavior, frame-budget math, crash symbolication, LLDB workflows, thermal-state handling, and launch-time optimization are covered in depth in references/runtime-performance-triage.md — including which of these categories the Simulator cannot faithfully reproduce, and why lab evidence alone should never close out a field-facing performance fix.

Archive And APNs Validation

  • Validate the exact .xcarchive selected for upload before blaming runtime code. Avoid generic find ... .app | tail -1 shortcuts when multiple archives or export folders may exist:
codesign -d --entitlements :- "$APP" 2>/dev/null
security cms -D -i "$APP/embedded.mobileprovision" | plutil -p - | grep -A2 aps-environment
  • Pass condition for a TestFlight/App Store archive:
    • aps-environment = production in the archived app entitlements
    • get-task-allow = false
    • aps-environment = production in the embedded provisioning profile
  • If aps-environment = development or get-task-allow = true, the archive is still development-signed. If those values are correct but validation fails, inspect generated plist metadata next.
  • When push debugging crosses release channels, separate token-registration truth from transport truth. A common iOS/TestFlight failure is: many sandbox deliveries succeed, the only production delivery fails with BadDeviceToken, and the phone receives nothing. Treat that as a stale-registration or invalid-production-token problem first, not as proof that APNs transport or signing is generally broken.
  • Preserve the device registration and failure response before resetting. Prove the installed build channel, current token registration, APNs environment, successful send, actual receipt, and push-open behavior separately. Route backend device-row lifecycle changes to software-backend; an app uninstall is a later diagnostic reset, not a default transport fix.

XcodeGen and Project File Discovery

Generator specs and target membership cause install-time failures and "cannot find X in scope" errors that look like Swift bugs. Regenerate XcodeGen projects after adding files (scripts/generate-xcodeproj.sh or xcodegen generate), and add new files to the target in .pbxproj-managed projects. Details in references/xcodegen-resource-packaging.md.

Route Elsewhere

  • Use software-ios-native once runtime truth is established and the task becomes feature implementation, rewrite planning, or SwiftUI architecture.
  • Use software-ios-design once the screen is confirmed to come from a fresh build and the task is visual hierarchy, typography, materials, or HIG compliance.
  • Use qa-testing-ios once the app is buildable and installable and the task becomes test execution, xcresult, destinations, or flake control.
  • Use software-mobile for platform choice, Android, or cross-platform tradeoffs.

Navigation

References

ResourcePurpose
references/runtime-proof-loop.mdCanonical build/install/launch verification loop
references/stale-build-triage.mdHeuristics for screenshots, stale installs, and simulator drift
references/xcodegen-resource-packaging.mdXcodeGen and bundle-packaging failure patterns
references/swift-concurrency-crash-triage.mdSymptom-first triage for concurrency-rooted crashes and freezes
references/runtime-performance-triage.mdHang/crash/jank/memory/launch triage tree, Instruments, MetricKit, Jetsam, frame budgets, thermal state
data/sources.jsonPrimary Apple and XcodeBuildMCP sources

Templates

TemplatePurpose
assets/template-ios-runtime-debug-request.mdShort request format for proof-first runtime debugging

Related Skills

SkillPurpose
software-ios-nativeNative iOS implementation and rewrites after runtime truth exists
software-ios-designVisual audits after fresh build/install/launch proof
qa-testing-iosXCTest, XCUITest, xcresult, and flake control after installability is proven
software-mobileMobile platform choice and cross-platform tradeoffs
  • Prefer Apple documentation for xcodebuild, simctl, and bundle structure behavior.
  • Prefer upstream XcodeBuildMCP docs for tool names, CLI commands, and config keys.
  • Treat repo-specific build, scheme, bundle ID, and generator behavior as local facts that must be discovered, not assumed.
  • Instrument names, hardware-gated feature availability (e.g., Processor Trace chip requirements), and exact watchdog timings change across Xcode/iOS releases — re-verify against current Apple release notes rather than trusting a fixed number from this skill. Jetsam memory-limit figures are explicitly empirical, not Apple-published, and should be re-derived from device behavior (os_proc_available_memory, jetsam event reports), not hardcoded.

Learnings Loop

When prior decisions or pitfalls are relevant, consult learnings.consolidated.md if present; use learnings.md only for needed history or as the available fallback. Otherwise skip both.

After applying it, if you encountered a pattern worth remembering, a mistake worth preventing, or a domain fact that surprised you, append one dated bullet to learnings.md via agents-skills-feedback-loop/scripts/append_learning.py. Do not modify SKILL.md itself.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Configures Claude Code hooks and Codex hooks.json/notify. Use when adding PreToolUse guards, Stop hooks, managed hooks, format-on-save, preflight, audits, or worktree/budget hooks.

日本語の概要は準備中です。原文の説明を表示しています。

vasilyu1983/AI-Agents-public912026年10月5日 更新

Configures and hardens Claude Code and Codex MCP servers. Use when connecting databases, APIs, SaaS, building servers, or serving a clearance-filtered knowledge base.

日本語の概要は準備中です。原文の説明を表示しています。

vasilyu1983/AI-Agents-public912026年10月5日 更新

Owns instruction files: AGENTS.md, CLAUDE.md, personal and repo rules. Use when writing, pruning, auditing them, sharing rules across Claude and Codex, or fixing ignored rules.

日本語の概要は準備中です。原文の説明を表示しています。

vasilyu1983/AI-Agents-public912026年10月5日 更新

Creates and audits agent skills: SKILL.md, references, scripts, runtime metadata. Use when writing, validating, or security-reviewing a skill, or fixing truncated skill listings.

日本語の概要は準備中です。原文の説明を表示しています。

vasilyu1983/AI-Agents-public912026年10月5日 更新

Adds per-skill learnings loops for dated patterns, mistakes, and domain facts. Use when wiring skill memory, consolidation, or drift audits.

日本語の概要は準備中です。原文の説明を表示しています。

vasilyu1983/AI-Agents-public912026年10月5日 更新

Chooses subagent, team, workflow, or debate and launches it on Claude Code or Codex. Use when delegating, running agent review boards, or installing shared agents.

日本語の概要は準備中です。原文の説明を表示しています。

vasilyu1983/AI-Agents-public912026年10月5日 更新

vasilyu1983 のスキルをすべて見る

このスキルの問題を報告する