Captures or analyzes iOS memgraph files and persistent heap growth with Apple CLI evidence, ownership paths, raw artifacts, and matched-flow verification. Use for leaks or memory-growth investigations; route interactive Xcode Memory Graph, Instruments, or LLDB work to debugging-instruments.
97%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
The canonical home for this skill is dpearson2699/swift-ios-skills
Use memory graphs to prove why memory survives a defined lifetime boundary. Separate unreachable leaks from reachable growth, preserve raw tool output, and verify the same app-owned type and ownership path after a fix.
This skill owns .memgraph capture and command-line ownership/growth analysis.
Use the Memory Graph Debugger or Instruments when their interactive graph and
allocation timeline are the primary task. Use source review for a suspected
closure capture only after runtime evidence identifies the lifetime or path.
Do not collapse these conditions:
leaks may correctly report zero.Apple's leak scanner uses conservative pointer discovery and incomplete type metadata. Counts can fluctuate, and a zero result does not prove the absence of an ownership bug. Strong evidence identifies the expected lifetime, an app-owned type or allocation, and a credible path or isolated reproduction.
Name the object that should disappear and the event that ends its useful life.
For example: EditorViewModel should deinitialize after dismissing the editor
and completing pending save work.
Record one deterministic sequence:
Keep build, simulator/device, data, Malloc Stack Logging setting, and repetition count stable. Malloc Stack Logging adds valuable allocation backtraces but also overhead; compare only runs with the same setting.
Xcode can export a graph from the Memory Graph Debugger. For a running Simulator app, use the helper from this skill:
mkdir -p /tmp/myapp-memory
mkdir /tmp/myapp-memory/run-01
python3 scripts/capture_sim_memgraph.py \
--bundle-id com.example.MyApp \
--output-dir /tmp/myapp-memory/run-01 \
--pretty > /tmp/myapp-memory/run-01/capture.jsonThe per-run mkdir must fail if the capture directory already exists. Use a
new run name rather than mixing stale evidence with a retry.
Pass --udid when more than one Simulator is booted. The helper accepts only
one exact launchd label and PID; zero or multiple matches are errors. It runs the
host leaks --outputGraph command, retains stdout/stderr, and writes a manifest.
Do not replace this with pgrep | head -1 or a substring match.
Capturing suspends the process. Do not use capture latency as performance data.
MEMGRAPH=$(jq -er \
'select(.status == "captured") | .memgraph | select(type == "string" and length > 0)' \
/tmp/myapp-memory/run-01/capture.json)
test -s "$MEMGRAPH"
python3 scripts/summarize_memgraph.py \
"$MEMGRAPH" \
--artifact-dir /tmp/myapp-memory/run-01/analysis-raw \
--app-image 'MyApp|MyFeatureKit' \
--trace-limit 3 --group-by-type --pretty \
> /tmp/myapp-memory/run-01/analysis.jsonRead the exact graph path from the preserved capture report; do not guess a
timestamped filename. The helper creates a dedicated raw-artifact directory,
refuses to reuse it, runs leaks --list, and parses only a conservative subset
of its text. --app-image marks candidate rows; it does not prove ownership.
--trace-limit runs bounded
leaks --traceTree=<address> queries. Add --reference-tree when aggregate
root paths are more useful than individual leaked addresses. With
--group-by-type, that reference-tree query is grouped in the same invocation.
Exit statuses 0 and 1 from leaks remain analyzable; a primary status above 1
fails the summary, while optional-query failures are preserved and warned as
unusable without discarding a valid primary summary.
Apple does not publish these text formats as stable machine schemas. Treat parse warnings as a reason to inspect the raw artifacts, not to loosen the parser until it emits a desired answer.
Start with an app-owned leaked type or allocation stack. Inspect:
--traceTree=<address> for objects that reference one address;--groupByType to compress repeated types and reveal a retained payload;--referenceTree for a top-down view when the responsible address is unclear;An unreachable self-cycle may have no live root in traceTree. Use the grouped
leak graph plus source verification or reduce the behavior to an isolated
reproduction. Never invent a root path that the graph does not contain.
leaks is emptyUse matching baseline and post-flow graphs, locate the growing region, compare
object types, then trace a suspicious address back to an app-owned edge. The
evidence goal is persistent reachable growth across the same lifetime—not a
lower RSS value or a single large snapshot. Load
reachable-growth.md only for this empty-leak
branch; it contains the ordered vmmap, heap, leaks, and malloc_history
queries and their logging-dependent alternatives.
Prefer the narrowest ownership correction: break the unintended strong edge,
cancel work that owns the object, remove an observer, bound/evict a cache, or
release a large buffer after its last use. Use weak when the reference may
legitimately become nil; use unowned only with a proven lifetime guarantee.
Repeat the identical flow. A fix is supported when the same app-owned type/path disappears or the pre/post growth attributable to it is removed across repeated runs. Lower RSS, a smaller graph file, or a lower aggregate leak count alone is not proof.
| Evidence | Next action |
|---|---|
| App type in a root cycle | Inspect both strong edges and allocation stack. |
| No root for a leaked address | Inspect grouped cycle evidence and isolate the flow. |
| Live root retains dismissed feature state | Follow the path to the first app-owned edge. |
| Zero leaks but repeated malloc growth | Diff baseline/post heap objects. |
| Framework object dominates | Find the app-created owner, input, or call frequency. |
| Growth stabilizes at a documented bound | Test eviction/pressure behavior before changing it. |
leaks returned zero once.[weak self] without reasoning about lifetime.leaks is empty —
matched-graph comparison and address-to-owner workflowthienqo/ios-skills
6bf8b62
Canonical home
since Jul 13, 2026
Also appears in
since Aug 28, 2026
since Aug 24, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.