mcpField
M
memorydetective

memorydetective

ローカル
github.com/carloshpdoc開発ツール1422 週間前に更新

memorydetective について

memorydetective は、memgraph ファイル、トレース、MetricKit 診断データを調べ、iOS のメモリーリークやパフォーマンス問題を分析する MCP サーバー兼コマンドラインツールです。開発者向けに、循環参照やハングの調査に加え、シミュレーターでの再現と修正確認を支援します。

主な機能

  1. 01memgraph の循環参照を分析・分類
  2. 02トレースのハング、メモリー、性能を調査
  3. 03MetricKit 診断ペイロードを分析
  4. 04シミュレーターのシナリオを記録・再生
  5. 05メモリーグラフを比較して修正を検証

活用シーン

  1. 01循環参照を SwiftUI や Combine のパターンに照らして調査
  2. 02iOS トレースからハングのホットスポットを特定
  3. 03MetricKit ファイルのクラッシュやハングの集積を確認
  4. 04コード変更前後のメモリーグラフを比較

MCP 対応

MCP サーバーは、分析、記録、比較、修正検証のツールを MCP クライアントに公開します。summarize-trace プロンプトも提供します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"carloshpdoc-memorydetective": {
"command": "npx",
"args": [
"-y",
"memorydetective"
]
}
}
}
起動コマンドnpx -y memorydetective

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npmmemorydetective1.18.1

ツール

42

掲載時のツール一覧 · 2 週間前に更新

パラメーター型必須説明
pathstringはい`.memgraph` ファイルの絶対パス(Xcode Memory Graph Debugger からエクスポート)。
verbosityenumいいえクラス名の詳細度です。`compact`(デフォルト)ではモジュール接頭辞を削除し、ネストされた SwiftUI ModifiedContent を `+N modifiers` にまとめ、深いジェネリクスをハッシュのプレースホルダーで切り詰めます。`normal` はより多くの詳細を保持します。`full` は Swift のデマングル済み名称をそのまま返します。compact | normal | full
fullChainsbooleanいいえtrue の場合、完全なネストされた保持チェーンをレスポンスに含めます。デフォルトの false では、ペイロードを小さく保つためトップレベルの ROOT CYCLE の要約のみを返します。
outputFormatenumいいえレスポンス形式です。省略するか `json`(デフォルト、v1.8 の動作を維持)を指定すると、結果の JSON.stringify を返します。`markdown` は同じデータを人が読みやすい形式で表示します。`both` は 1 つのレスポンスで両方のコンテンツ項目を返すため、クライアントはユーザーに markdown を表示し、2 回目の呼び出しなしで Agent ループ用に JSON を解析できます。`verify-fix-table`(v1.10、`analyzeAbandonedMemory` と `diffMemgraphs` に適用)は、対応が必要な行に絞った 4 列の markdown 比較表(Class | Before | After | Delta)を出力します。他のツールでは、この値は `markdown` にフォールバックします。markdown | json | both | verify-fix-table
maxClassesInChainintegerいいえ各 cycle の `classesInChain` 配列に表示する一意なクラス名の上限です。デフォルトは 10 で、応答を肥大化させずにアプリレベルの型を識別できます。
referenceTreeTopNintegerいいえ`leakCount` が 0(典型的なメモリ放棄ケース)の場合、`leaks --referenceTree --groupByType --noContent` も実行し、存存インスタンス数の上位 N クラスを `abandonedMemoryTop[]` に表示します。0 に設定すると、2 回目の leaks 呼び出しをスキップします。デフォルトは 20 です。

詳細

memorydetective

English · Português brasileiro

チャットウィンドウから、iOS の retain cycle とパフォーマンスのリグレッションを診断できます。Xcode は不要です。

npm CI License: Apache 2.0 GitHub stars macOS node

demo

主な特徴

  • CLI 主導のリーク調査。 Xcode(またはシミュレーター上で memorydetective 自体)が取得した .memgraph ファイルを読み込み、ROOT CYCLE を検出して、既知の SwiftUI/Combine のパターンに照らして分類し、すぐに使える修正ヒントを提示します。スクリプトからでもチャットからでも実行できます。
  • MCP ネイティブ。 Claude Code、Claude Desktop、Cursor、Cline、その他あらゆる MCP クライアントと連携します。エージェントが調査 → 分類 → 修正提案の全工程を進めるため、Instruments を開く必要はありません。
  • 制限についても正直です。 出力を偽装せず、過剰な約束もしません。ハング解析は xctrace からクリーンに動作します。サンプルレベルの Time Profile は、xctrace がトレースのシンボルを解決できた場合に解析され、解決できない場合は構造化された回避策の通知を返します(シンボル未解決の大規模なトレースで発生する xctrace の SIGSEGV は Apple 側の制限であり、そのことを明示します)。Memory Graph の取得は Mac アプリと iOS シミュレーターで動作します。実機の iOS デバイスでは、引き続き Xcode が必要です。

v1.18 の新機能(2026-05-17):MetricKit と監査完了。analyzeMetricKitPayload は42番目の MCP ツールです。実機の TestFlight/App Store ビルドから Apple MetricKit の .mxdiagnostic JSON ペイロードを取り込みます(本番環境の事後診断に対応するもので、現時点でこの領域を扱う MCP の競合製品はありません)。実用的な出力は3種類です。例外の種類/バイナリ/最上位フレームごとのクラッシュクラスター、ローカライズされた期間表記("5.4 sec"/"20秒")を解析するハングのホットスポット、CPU とディスクの例外です。ツール間の連携ヒントも表示されます(例:objc_release のような最上位フレームが、findCycles の実行を提案します)。さらに、監査完了に向けた3項目も追加しました。オープンな列挙型 SupportStatusKind(後続の利用者が型を破壊的に変更せずに種類を追加できます)、呼び出しスコープの schemaDiscovery キャッシュ(実際の Apple トレースで、最初に TOC を一度取得することで summarizeTrace のエンドツーエンド処理時間を約28秒から約15秒に短縮)、実際の Apple .trace バンドルを使うローカル限定の統合テスト(v1.14 で発生した P+O のずれを恒久的に解消)。テスト数は701から757に増加しました。MCP ツール数は41から42に増加しました。

最近の更新(v1.17):信頼性の改善です。3つの層にわたって14件のバグを修正しました。主な変更点:strtobool による環境変数の真偽値解析、verifyFix のホワイトリスト照合モード(完全一致/部分一致/正規表現)、recordViaInstrumentsApp が watchDir の外に保存されたトレースを検出、inspectTrace のフォールバックによる障害耐性、設定可能な countAlive のフレームワークノイズフィルター、可変サイズクラスの最小値/最大値/中央値。

v1.16:macOS 26.x の記録ブロックを解消するリリースです。新しい recordViaInstrumentsApp MCP ツールは Instruments.app の GUI 操作を自動化します。アプリを開き、手順を段階的に表示し、保存された .trace をディレクトリ内で監視し、成功すると inspectTrace を実行します。Apple が macOS 26.x のシミュレーターで発生する xcrun xctrace record の回帰を修正するまでは、これが自動化された方法です。

v1.15:スキーマ対応の拡充と verify-fix の UX 改善です。新しい MCP トレースツールを3つ追加し、残っていたスキーマの不足を解消しました。analyzeMemoryFootprint(38番目。VM の resident/dirty/virtual と jetsam の診断)、analyzeEnergyImpact(39番目。バッテリー消費の調査)、analyzeLeakTimeline(40番目。xctrace の leaks 計測器による時系列分析)です。summarizeTrace が analyzeNetworkActivity も実行するようになりました。replayScenario は各ステップのシミュレーターのスクリーンショットを記録します。

それ以前:v1.14 ではトレース関連の信頼性、analyzeNetworkActivity、統合された supportStatus[]、FLEX に着想を得た countAlive のサイズ表示、MLeaksFinder と DebugSwift に着想を得た verifyFix のホワイトリストを追加しました。v1.13 では summarizeTrace と /summarize-trace MCP プロンプトをリリースしました。v1.12 では参照ツリーの伝播を完了しました。v1.11 では inspectTrace と diffMemgraphs の参照ツリーを追加しました。v1.9 では analyzeAbandonedMemory、detectLeaksInXCTest、cleanupTraces、mainThreadViolations をリリースしました。詳細は CHANGELOG をご覧ください。

macOS 26.x をお使いの方へ:Apple は macOS 26.x で task_for_pid のカーネル回帰を導入しました。このため、MallocStackLogging の設定にかかわらず、iOS シミュレータープロセスに対する leaks --outputGraph、heap、および xctrace --template Allocations がブロックされます。Xcode の「メモリーグラフの階層を表示」も同じ影響を受けますが、スキームの「Diagnostics」タブで Malloc Stack Logging を有効にすれば回避できます。memorydetective は、キャプチャー系ツールを初めて呼び出したときに、これを事前に知らせる platformAdvisory として表示します。また、leaks が呼び出された場合は issue: "macos-26-task-for-pid-broken" を含む workaroundNotice を表示します。現時点で最も信頼性の高い回避策は、iOS 18 のシミュレーターランタイムを使うことです(Xcode > Settings > Platforms > +iOS 18.x からインストールしてください)。2026-05-12 の notelet investigation では、iOS 18 が有効な回避策として特定される前に、独立した3つの CLI メモリー調査経路すべてで失敗することを実機で確認しました。回避策を決めた後に通知を抑制するには、MEMORYDETECTIVE_SUPPRESS_PLATFORM_ADVISORY=1 を設定してください。 macOS 26.xでも発生:シミュレータターゲットでxctrace recordが動作しません。 上記のtask_for_pidのリグレッションとは別に、iOSシミュレータのプロセスに対するxcrun xctrace record --time-limit Nsは、制限時間を過ぎても停止せず、強制終了されるとようやく終了します。生成される.traceバンドルにはテンプレートのメタデータがありません。そのため、xctrace export --tocはDocument Missing Template Errorで失敗します。2026-05-15にXcode 26.5(ビルド17F42、xctrace 16.0)で再検証しましたが、アップデート後もリグレッションは解消されていません。これは、xctraceベースのエコシステム全体に同じように影響します(memorydetective.recordTimeProfile、XcodeTraceMCP、xcrun xctrace recordの直接呼び出しは、いずれも同じように失敗します)。回避策: (1)recordViaInstrumentsAppを使用します(v1.16で導入、v1.17で強化)。このツールはInstruments.appを開き、記録して.traceを保存するよう促した後、バンドルが現れると自動的にinspectTraceを実行します。v1.17では、Instruments.appのAppleScriptによるドキュメント照会を使って監視ディレクトリ外への保存も検出し、savedOutsideWatchDir: trueと実際のパスを返します。(2)可能であれば、Xcode 26.0を使っている古いmacOSホストから記録します。(3)実機を対象に記録します(このリグレッションはシミュレータ固有のようです)。v1.17では、recordTimeProfileに実行可能性プローブ(ディスク上のバンドルが52Kのスタブの場合はbundleStatus: "wedged")を、inspectTraceにもプローブを追加しました(例外を投げず、診断テキストとともにok: trueを返します)。手順についてはUSAGE.md > Troubleshootingをご覧ください。

クイックスタート

npm install -g memorydetective

MCP クライアントの設定に追加します(Claude Codeの例):

// ~/.claude/settings.json
{
  "mcpServers": {
    "memorydetective": { "command": "memorydetective" }
  }
}

または、コマンドラインから直接使用します:

memorydetective analyze   ~/Desktop/myapp.memgraph
memorydetective classify  ~/Desktop/myapp.memgraph

→ チャット主導のフローについては例、ツールの全リファレンスについてはAPI、Claude Desktop/Cursor/Clineの設定については設定をご覧ください。診断からコードベースへの修正反映までを含む全手順についてはUSAGE.mdをご覧ください。


例

実際の利用を想定したチャット例です。エージェントはAPIに記載されたMCPツールを呼び出します。

memgraphからリークを診断する

あなた: ~/Desktop/example.memgraphにメモリグラフをエクスポートしたところです。詳細画面を閉じた後に何かがリークしています。原因は何ですか?

Claude: (analyzeMemgraph → classifyCycleを呼び出し) 60,436件のリークのうち、ROOT CYCLEブロックが4件見つかりました。最も多いものは、高い信頼度でswiftui.tag-index-projectionに一致します。写真カルーセルのForEachで.tag()に紐づけられたクロージャが、_viewModel.wrappedValueを介してselfを強参照しています。そのため、画面を閉じた後もDetailViewModelとナビゲーションコーディネーターが解放されません。

修正案: タップハンドラーの[weak self]キャプチャを静的ヘルパーに置き換えるか、[weak coord = self.coordinator]でビューモデルを弱参照します。該当するファイルを探しましょうか?

修正が実際に機能したか確認する

あなた: 修正をリリースしました。~/Desktop/before.memgraphと~/Desktop/after.memgraphを比較して、DetailViewModelの数が減ったか教えてください。

Claude: (diffMemgraphs → countAliveを呼び出し) DetailViewModel:12 → 0(差分-12)。swiftui.tag-index-projectionのサイクルは解消されています。リーク総数は60,436件から55,576件に減少しました(−4,860)。ほかに3件のROOT CYCLEが残っています。これらはSwiftUIの内部要因であり、あなたのコードが原因ではありません。

自己完結型の検証・修正ループ(v1.8)

macOS 26.x で leaks --outputGraph が失敗する場合(Failed to get DYLD info for task)、通常は MallocStackLogging=1 を設定してアプリを起動していないことが原因です。新しいオーケストレーションツールを使えば、xcodebuild + simctl + axe を自分で組み合わせることなく、エンドツーエンドで処理できます。

あなた: MyApp でメモリリークを再現してください。ビルドし、適切な環境変数を設定して起動し、フォトカルーセルの操作を5回繰り返してリークを増幅させてから、修正前をキャプチャしてください。その後、修正をリリースしたら、修正後もキャプチャしてください。

Claude: (bootAndLaunchForLeakInvestigation を呼び出します) iPhone 15 をビルドして起動しました(UDID ABCD-...)。MyApp を MallocStackLogging=1 で起動しました(PID 49581)。バンドル ID は com.example.MyApp です。

(replayScenario を呼び出し、カルーセルのタップと戻るボタンの操作を5回実行します) 12.3秒で25個のアクションを実行しました。失敗はありません。

(captureScenarioState({label:"before"}) を呼び出します) before.memgraph(63,201件のリーク)、before.png、before.ui.json を書き込みました。MallocStackLogging は有効で、workaroundNotice はありません。

(修正をリリースして再ビルドします)

(bootAndLaunchForLeakInvestigation + replay + captureScenarioState({label:"after"}) を呼び出します)

(diffMemgraphs → verifyFix を呼び出します) DetailViewModel:15 → 0。swiftui.tag-index-projection PASS。解放されたバイト数:28.4 MB。

実機で遅い処理経路を見つける

あなた: iPhone で DemoApp を90秒間プロファイルし、ハングが発生している箇所を教えてください。

Claude: (listTraceDevices → recordTimeProfile → analyzeHangs を呼び出します) ~/Desktop/run.trace を記録しました(90秒間、iPhone 17 Pro Max 上の DemoApp に接続)。ユーザーに見えるハングが23件見つかりました(各500 ms超)。最長は1.16秒、平均は769 msです。負荷は深刻です。すべてメインスレッドで発生しています。サンプルレベルのホットスポットはまだシンボリケートされていません。この手順では Instruments でトレースを開いてください(xctrace でシンボリケートできない場合、analyzeTimeProfile は構造化された回避策の通知を返します。既知の制限については CHANGELOG を参照してください)。

実ユーザーのクラッシュから MetricKit ペイロードを分析する(v1.18)

あなた: 過去30日間の TestFlight から取得した .mxdiagnostic ファイルのフォルダーが ~/Downloads/metrickit-may/ にあります。実ユーザーで何が起きていますか?

Claude: (analyzeMetricKitPayload({ payloadDir: "~/Downloads/metrickit-may/" }) を呼び出します) ペイロードは47件、期間は2026-04-15 → 2026-05-15です。最多の問題は、EXC_BAD_ACCESS のクラッシュが18件で、同じ最上位フレームに集中しています。すべてビルド456および457で発生し、458以前のビルドでは発生していません。パターンは retain-cycle の解放と一致しており、次の手順として findCycles が示されています。

次に、libsqlite3.dylib で 5.4秒のハングが5件あります(サンプル3件)。ローカルで再現する場合は、includeStackClassification: true を指定して analyzeHangs に連結し、mainThreadViolations[] の分類器を使用してください。

v1.18 ではシンボリケートされたフレームはありません(未加工の binaryUUID + offset が出力されます。dSYM の検索は別のツールとして今後リリース予定です)。ローカライズされたハング時間の文字列にも対応しています。入力は "5.4 sec" で、5400ms に正規化されました。診断データの1件には日本語で "20秒" とあり、20000ms に正規化されました。

複数の TestFlight ビルドをまたいだ検証・修正ループに analyzeMetricKitPayload を組み込む方法を含む、エンドツーエンドの手順については、USAGE.md § MetricKit production post-mortem を参照してください。

エンドツーエンド:リーク → ファイル → 修正案

メモリーグラフの分析と Swift ソースのブリッジを組み合わせ、メモリーグラフからコード編集までを一貫して行います。

あなた: リークが発生しています。メモリーグラフは ~/Desktop/example-leaks.memgraph にあります。サイクルは DetailViewModel を指しています。プロジェクト ~/Development/myapp/ 内の場所を見つけて、修正案を提示してください。

Claude: (analyzeMemgraph → classifyCycle → reachableFromCycle を呼び出します) ROOT CYCLE ブロックが 4 個見つかりました。最も顕著なものは、高い確度で swiftui.tag-index-projection に一致します。reachableFromCycle により、4 個の DetailViewModel インスタンスがそれぞれ約 1100 個の NSURLSessionConfiguration を保持していることが確認できました。原因は VM で、ネットワークスタックは巻き添えです。

(swiftSearchPattern を呼び出し、~/Development/myapp/Sources/ 内の .tag( + onImageSliderTap パターンを検索します) MyApp/Views/MediaCarousel.swift:142 に 1 件見つかりました。

(swiftGetSymbolDefinition({ symbolName: "DetailViewModel", projectRoot: "...", candidatePaths: ["MyApp/ViewModels/"] }) を呼び出します) MyApp/ViewModels/DetailViewModel.swift:18 で宣言されています。class DetailViewModel: ObservableObject。

(swiftFindSymbolReferences を呼び出して、修正の影響範囲を確認します。呼び出し箇所は 7 件です)

MediaCarousel.swift:142 の修正案:

// 修正前
.tag(index)
.onImageSliderTap { index in
    self.viewModel.handlePhotoTap(at: index)
}

// 修正後。静的ヘルパーと weak キャプチャを使用
.tag(index)
.onImageSliderTap { [weak vm = _viewModel.wrappedValue,
                     weak coord = self.coordinator] index in
    Self.handlePhotoTap(index: index, viewModel: vm, coordinator: coord)
}

適用して、新しい .memgraph で検証しましょうか?


削減できるコスト

要点を一言でいうと、memorydetective は 50~500 MB のバイナリ memgraph(または 200 KB の leaks(1) テキストダンプ)を、AI エージェントが実際に推論できる 2~5 KB の構造化サマリーに変換します。 これにより、iOS のパフォーマンス調査に LLM を活用する際のコスト構造が変わります。

トークン数(Claude/Cursor/Cline などの AI エージェントと併用する場合)

実際の保持サイクル調査を 2 回実施しました。1 回は memorydetective を使用し、もう 1 回はエージェントが生の leaks(1) 出力を直接読み取りました。

手順MCP なし(エージェントが生の出力を読む場合)memorydetective を使用
leaks のテキストダンプ(約 280 KB)を読み込む約 70,000 入力トークン該当なし
analyzeMemgraph のサマリー該当なし約 750 入力トークン
classifyCycle + 修正のヒント追加のやり取りのたびにエージェントがダンプを再推論(さらに 3~4 ターン)1 ターン。構造化された patternId + fixHint
findRetainers / reachableFromCycleエージェントがダンプを再スキャン約 500 トークン。範囲を絞ったクエリ
調査ごとの合計約 85,000 トークン、約 6 ターン約 3,000 トークン、約 2 ターン

モデル(Claude Opus/Sonnet/Haiku)に応じて、調査 1 回あたりおよそ 0.40~1.20 ドルに相当します。 ファイルサイズと調査の深さに応じて、コストは線形に増加します。

開発者の作業時間

同じ調査にかかった時間を開発者が計測しました。

手順MCP なしmemorydetective を使用
メモリーグラフを取得して leaks を実行5 分5 分(同じ)
leaks のテキストダンプを読んで解釈15~30 分(繰り返しのフレームが含まれる 200 KB をざっと読む)30 秒(3 KB のサマリーを読む)
原因となるパターンを特定10~20 分(経験をもとにサイクルの形状を認識)即時(分類器が patternId + 修正のヒントを返す)
ソース内で疑わしい型を特定10~15 分(grep + 手動で移動)30 秒(swiftGetSymbolDefinition が file:line を返す)
修正の影響範囲を把握するため、すべての呼び出し箇所を見つける5~10 分(Xcode/grep)10 秒(swiftFindSymbolReferences)
合計所要時間45~80 分約 10 分

数値は、タグ付き ForEach による SwiftUI の保持サイクルが約 28 MB のネットワークスタックの状態を保持していた、匿名化済みの実際の調査 1 件をもとに丸めています。サイクルの複雑さやコードベースの規模によって、結果は異なります。

効果が限定的な場合

効果があまりないケースについても、正直にお伝えします。

  • ごく小さなメモリーグラフ(単一サイクル、raw データが 50 KB 未満):MCP のオーバーヘッドは、Raw 読み込みと比べてトークン数にほとんど差がありません。開発時間の短縮効果は変わりません(サイクルを手動で解析する必要がなくなります)が、トークン削減効果は小さくなります。
  • リーク情報が紐づいていない単発のシンボル検索:grep を使えば十分です。これは必要ありません。
  • 新しいコードベースでの初回調査:MCP を使っても、エージェントには状況を把握するためのやり取りが必要です。効果が積み重なるのは、プロジェクトの構造がキャッシュされた後の、2 回目以降の調査です。

効果は、(a) ファイルサイズ、(b) 調査の深さ(複数回のやり取り)、(c) 四半期ごとに調査するリークの数に応じて積み重なります。年に 1 件のリークを修正する開発者 1 人の場合、主な価値は開発時間の短縮です。一方、すべての PR で verifyFix を使った CI ゲートを実行するチームでは、数百回にわたる実行でトークンと時間の節約が積み重なります。


設定

memorydetective バイナリは、stdio 経由で MCP を通信します。MCP 対応クライアントからこのバイナリを指定してください。

Claude Code
// ~/.claude/settings.json (global) or .mcp.json (per-project)
{
  "mcpServers": {
    "memorydetective": { "command": "memorydetective" }
  }
}
Claude Desktop
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "memorydetective": { "command": "memorydetective" }
  }
}

編集後、Claude Desktop を再起動してください。

Cursor
// ~/.cursor/mcp.json
{
  "mcpServers": {
    "memorydetective": { "command": "memorydetective" }
  }
}
Cline (VS Code)
// VS Code settings.json
{
  "cline.mcpServers": {
    "memorydetective": { "command": "memorydetective" }
  }
}
Kiro

Kiro はグローバル設定を通じて MCP サーバーに対応しています。設定ブロックは Claude Desktop のものと同じです。

{
  "mcpServers": {
    "memorydetective": { "command": "memorydetective" }
  }
}

お使いのシステムでの正確な設定ファイルのパスについては、Kiro の MCP セットアップドキュメントを参照してください。

GitHub Copilot(実験的機能)

GitHub Copilot はエージェントモード(VS Code 1.94 以降)で MCP に対応しています。リポジトリ内の .vscode/mcp.json に追加してください。

{
  "servers": {
    "memorydetective": {
      "type": "stdio",
      "command": "memorydetective"
    }
  }
}

Copilot の MCP 統合は頻繁に更新されています。このスニペットが古くなっている場合は、VS Code の MCP ドキュメントを参照してください。

### 環境変数

以下の各ブール値 MEMORYDETECTIVE_* フラグは、strtobool の真値セット(大文字と小文字を区別しない)を受け付けます:1 / true / t / yes / y / on(真)および 0 / false / f / no / n / off(偽)。認識されない値が指定されると、変数ごとに標準エラーへ一度だけ警告が出力され、文書化されたデフォルト値にフォールバックします。v1.17 より前はパーサーが 1 のみを受け付けていたため、オペレーターが =true または =yes をエクスポートしても何も起きない状態が黙って発生していました。警告は MEMORYDETECTIVE_SUPPRESS_PLATFORM_ADVISORY によって抑制できます。

変数デフォルト効果
MEMORYDETECTIVE_REDACTIONbalancedすべてのツール応答に適用される出力の秘匿処理です。balanced はホームディレクトリのパスを ~/... に短縮し、トークン形式のシークレット(AWS キー、GitHub PAT、Stripe、Slack、Bearer 認証)をマスキングします。strict はホスト名、IPv4、バンドル識別子のマスキングも追加します。off は秘匿処理を無効にします(ローカルのみのデバッグに便利です)。モードはサーバー起動時に一度ログへ記録されます。
MEMORYDETECTIVE_ALLOW_LAUNCH未設定ブール値(strtobool)。bootAndLaunchForLeakInvestigation を許可します。このツールは呼び出し元が指定したパスとバンドル ID に対して xcodebuild および xcrun simctl launch を実行するため、明示的な許可が必要です。この設定がない場合、ツールは ok: false と state: launchNotAllowed を返し、明確な説明を示します。エージェントが生成する入力を信頼できる場合に限り、設定してください。
MEMORYDETECTIVE_MAX_RECORDING_SECONDS300recordTimeProfile.durationSec の上限です。上限を超えるリクエストは、明確なエラーとともに拒否されます。環境変数の設定ミスで制限が無効にならないよう、内部では 3600s(1h)のハード上限が適用されます。
MEMORYDETECTIVE_TRACE_ROOT~/Library/Application Support/memorydetective/tracesrecordTimeProfile.output が相対パスの場合に使用するディレクトリです。v1.8 との後方互換性のため、絶対パスにはこのデフォルトは適用されません。cleanupTraces のデフォルトのスキャンパスとしても使用されます。ディレクトリは初回の書き込み時に自動作成されます。
MEMORYDETECTIVE_ALLOW_EXTERNAL_CLEANUP未設定ブール値(strtobool)。cleanupTraces が MEMORYDETECTIVE_TRACE_ROOT の外部にある .trace バンドルをスキャンして削除することを許可します。この設定がない場合、設定済みのルート外に解決されるリクエストは、失敗理由とともに ok: false を返し、何も削除しません。設定された境界の外で行われる破壊的なディスク操作は、デフォルトで拒否されます。
MEMORYDETECTIVE_SUPPRESS_PLATFORM_ADVISORY未設定ブール値(strtobool)。macOS 26.x に関するプラットフォーム警告のうち、captureMemgraph、captureScenarioState、bootAndLaunchForLeakInvestigation が初回使用時に出力するものを抑制します。また、認識されないブール値(すべての MEMORYDETECTIVE_* フラグ)や schemaDiscovery の TOC 取得失敗時に出力される v1.17 の標準エラー警告も抑制します。iOS 18 のシミュレーターランタイムをインストール済みで、通知が不要な場合に便利です。
MEMORYDETECTIVE_AUTO_OPEN_INSTRUMENTS未設定ブール値(strtobool)。xctrace がタイムアウトしたとき(macOS 26.x のリグレッション)、recordTimeProfile が open -a Instruments <tracePath> を呼び出すようにします。これは結果を待たずに実行する回避策です。v1.17 では、開く前に MANIFEST.plist の有効性チェックが追加され、自動オープン処理では、Instruments.app に「Document Missing Template Error」ダイアログを表示してしまう 52K のスタブバンドル(応答しない状態のもの)がスキップされます。応答の openedInInstrumentsApp フィールドはオープン処理が呼び出されたかどうかを示し、bundleStatus(v1.17)はディスク上のバンドルの状態が unknown/salvageable/wedged のいずれかを示します。
MEMORYDETECTIVE_PREFLIGHT_XCTRACE未設定(自動)ブール値(strtobool)と auto。recordTimeProfile の事前チェックを制御します。このチェックは、ユーザーの durationSec に加えて 30s の猶予時間を費やす代わりに、約 3~5 秒で macOS 26.x の xctrace の応答停止を検出します。真値を指定すると、プラットフォームやターゲットにかかわらず有効になります。偽値を指定すると無効になります。未設定の場合は、macOS 26.x のシミュレーターへのアタッチ(既知の不具合がある組み合わせ)で自動的に有効になり、それ以外では無効のままです。アプリの二重起動を避けるため、--launch モードでは事前チェックがスキップされます。自動有効化の副作用として、本番の記録開始前に 2 秒間のチェックが実行されます。

API

目的別にグループ化された 42 個の MCP ツール + 34 個のリソース + 7 個のプロンプトを備えています。関連するツールがひと目でわかるように、ツールの説明にはカテゴリプレフィックス([mg.memory]、[mg.trace]、[mg.build]、[mg.scenario]、[mg.code]、[mg.log]、[mg.render]、[mg.ci]、[mg.discover]、[ops]、[meta])が付いています。

多くのツールは、レスポンスに suggestedNextCalls フィールドを含みます。これは、現在の結果をもとにあらかじめ値が設定された { tool, args, why } の型付きリストです。これにより、オーケストレーションを行う LLM は、あらためて推論することなく呼び出しを連鎖できます。標準的なシーケンスを確認するには、getInvestigationPlaybook(kind) から始めてください。または、MCP のスラッシュコマンドに対応する任意のクライアントで、/investigate-leak(プロンプトのひとつ)を入力してください。

サイクル分類器には、SwiftUI(Swift 6 / @Observable / SwiftData / NavigationStack の時代のパターンや、v1.9 の swiftui.observable-write-on-every-render の形を含む)、Combine、Swift Concurrency(AsyncSequence-on-self と新しい Observations API を含む)、UIKit(Timer/CADisplayLink/UIGestureRecognizer/KVO/URLSession/WebKit/DispatchSource や、v1.9 の uikit.viewcontroller-retained-after-pop の形を含む)、Core Animation、Core Data、Coordinator パターン、そして人気のサードパーティライブラリである RxSwift と Realm にまたがる 36 個の名前付きアンチパターンが含まれています。各パターンには、次の情報が含まれます。

  • テキスト形式の 1 行の fixHint
  • 信頼度の段階(high / medium / low)
  • 実行時の証拠を補完する SwiftLint ルールを示す staticAnalysisHint(ルールがない場合は、その旨を明示します。これにより、パース時にリンターが見逃すものを memorydetective が検出できるという差別化要素を強調します)
  • エージェントが SourceKit-LSP のソースブリッジングツールを使ってユーザーのコードに直接適用できる、具体的な Swift の変更前/変更後のスニペットを含む fixTemplate(v1.7 で追加)
読み取りと分析(14)

以下のトレース側アナライザー 9 個はすべて、オプションの第 2 引数 AnalyzeTraceOptions を受け取ります(v1.18 D-02)。summarizeTrace から呼び出される場合(最初にスキーマ探索を 1 回実行します)、キャッシュが引き継がれるため、各アナライザーによる xctrace --toc の呼び出しがスキップされます。直接呼び出す場合はオプションを省略し、動作は v1.17 と同じです。 | ツール | 内容 | |---|---| | analyzeMemgraph | .memgraph に対して leaks を実行し、概要(合計、ROOT CYCLE ブロック、平易な言葉での診断)を返します。 | | findCycles | ROOT CYCLE ブロックのみをフラット化したチェーンとして抽出します。必要に応じて className の部分文字列で絞り込めます。 | | findRetainers | 「<class> を保持しているのは誰か?」を調べます。トップレベルのノードから一致するものまでの保持チェーンのパスを返します。 | | countAlive | クラスごとにインスタンス数をカウントします。1 つの数値を得るには className を指定し、リーク数が多い上位 N クラスを得るには省略します。v1.17:調整可能なノイズフィルター(excludeFrameworkNoise、additionalNoisePatterns、unsuppressClassPatterns、noiseAuditMode)により、アプリごとに実用的な表示を調整できます。可変サイズのクラスでは instanceSizeBytesMin / Max / Median を報告します(v1.17 より前は最初に観測された値でした)。 | | reachableFromCycle | サイクル単位の到達可能性を調べます。「<Y> をルートとするサイクルから、到達可能な <X> インスタンスはいくつか?」を確認できます。実際の原因と、その原因によって保持されている依存対象を区別します。 | | diffMemgraphs | 2 つの .memgraph スナップショットを比較します。合計の差分、クラス数の変化、新規/消失/継続中のサイクルを返します。 | | analyzeAbandonedMemory | ヒープ参照ツリーのクラス数(サイクル一覧ではありません)に基づいて 2 つの .memgraph スナップショットを比較し、増加した各クラスを kvo-observer-orphaned、notificationcenter-observer-leaked、cache-too-aggressive、singleton-retains-payload、unknown-growth に分類します。厳密なサイクルが存在しないために leaks(1) が leakCount: 0 と報告する種類のバグを明らかにします。v1.10 では actionableGrowth[] と actionableShrinkage[](フレームワークノイズを除外した表示)が追加され、outputFormat: "verify-fix-table" をサポートします。この形式では、絞り込んだ Class | Before | After | Delta の Markdown テーブルを直接出力します。 | | verifyFix | サイクルの意味に基づく差分を調べます。パターンごとの PASS/PARTIAL/FAIL 判定と解放されたバイト数を返し、CI のゲートとして使用できます。expectedAliveClasses ホワイトリスト(v1.14)を使うと、シングルトン/キャッシュ/OS によって保持されるウィンドウを除外し、FAIL 判定に影響しないようにできます。v1.17 では、各エントリーで照合モード({ pattern, mode: "exact" \| "substring" \| "regex" })を個別に指定できるようになりました。文字列のみの場合は、引き続きデフォルトの部分文字列照合が使用されます。 | | classifyCycle | 各 ROOT CYCLE を、36 種類の名前付きアンチパターン(SwiftUI/Combine/Concurrency/UIKit/Core Animation/Core Data/Coordinator/RxSwift/Realm)の組み込みカタログと照合します。確信度、テキスト形式の fixHint、どの SwiftLint ルールが補完するか(または明示的な未対応項目)を示す staticAnalysisHint、Swift の修正前/修正後のスニペットである fixTemplate を返します。 | | analyzeHangs | xctrace の potential-hangs スキーマを解析し、Hang と Microhang の件数、および最長のものを上位 N 件返します。topFramesByHangStartNs(通常は analyzeTimeProfile を連鎖させて得られる関連データ)を渡すと、各上位ハングに mainThreadViolations[] を追加し、ブロッカーを sync-io、db-lock、network、lock-contention に分類します。 | | analyzeAnimationHitches | xctrace の animation-hitches スキーマを解析し、種類ごとの件数と、Apple がユーザーに知覚可能とする 100ms のしきい値を超えたヒッチの数を報告します。 | | analyzeTimeProfile | xctrace の time-profile スキーマを解析し、サンプル数に基づくシンボルの上位を返します。xctrace でシンボルを解決できない場合は、回避策とともに SIGSEGV を報告します。 | | analyzeAllocations | xctrace の allocations スキーマを解析し、カテゴリごとの集計(累積バイト数、割り当て数、ライフサイクル=一時的/永続的/混在)と、割り当て元の上位を返します。 | | analyzeAppLaunch | xctrace の app-launch スキーマを解析し、コールド/ウォームの起動タイプと、フェーズごとの内訳(process-creation、dyld-init、ObjC-init、AppDelegate、first-frame)を返します。 | | logShow | log show --style compact を使用し、述語/プロセス/サブシステムのフィルターを指定して、macOS の統合ログを一度だけ照会します。解析済みのエントリー(タイムスタンプ、タイプ、プロセス、サブシステム、カテゴリ、メッセージ)を返します。 |

キャプチャ/記録(4)
ツール内容シムデバイス
recordTimeProfilexcrun xctrace record --template "Time Profiler" --attach ... --time-limit Ns --output ... をラップします。bundleStatus: "unknown" | "salvageable" | "wedged"(v1.17)を返すため、タイムアウト後に tracePath を無条件に信用せず、ディスク上の実際の状態に応じて呼び出し元で処理を分岐できます。自動オープンの経路(MEMORYDETECTIVE_AUTO_OPEN_INSTRUMENTS)では、Instruments.app の起動前に MANIFEST.plist を確認し、使用不能な 52K のスタブをスキップします。✅✅
recordViaInstrumentsAppmacOS 26.x の回避策(v1.16)です。open -a Instruments で Instruments.app を開き、ユーザーが選ぶテンプレートと Record/Stop/Save を押すタイミングを伝える instructions[] 配列を返した後、5 秒ごとに watchDir を確認し、新しい .trace バンドル(mtime が 10 秒間安定)を探します。v1.17:ポーリングのたびに AppleScript で起動中の Instruments.app も照会し、watchDir の外に保存されたドキュメントがないか確認します。一致するものが見つかると、savedOutsideWatchDir: true とともにパスを返すため、Save を押してデスクトップの既定の保存先を選んだ場合でもタイムアウトしなくなります。成功時は inspectTrace につなぎます。✅✅
captureMemgraphleaks --outputGraph <path> <pid> をラップします。pgrep -x を使って appName → pid を解決します。macOS 26.x の Failed to get DYLD info for task のリグレッションに対し、安定した課題 ID(minimal-corpse、permission-denied、leaks-not-found、transient)を含む構造化された workaroundNotice と、recordTimeProfile(Allocations)+ analyzeAllocations へのフォールバック経路を返します。✅❌。Xcode を使用してください
logStream制限時間(≤ 60 s)にわたって log stream --style compact をラップします。その時間内に収集された解析済みエントリーを返します。該当なし該当なし
修正検証のオーケストレーション(3、v1.8)

これら 3 つのツールを組み合わせると、決定論的な修正検証ループを実行できます。MallocStackLogging=1 を設定してアプリを起動し、リークの調査に leaks を使用できるようにします。疑わしいリークを増幅させるよう UI を操作し、修正前のスナップショットを取得して、修正を適用し、修正後のスナップショットを取得した後、diffMemgraphs を実行します。

ツール内容
bootAndLaunchForLeakInvestigationSIMCTL_CHILD_* を介して MallocStackLogging=1 を引き継いだ状態で、ビルド + 起動 + インストール + アプリ起動を 1 回の呼び出しで実行します。シミュレーター(udid、name+os、または起動済みのもの)を解決し、xcodebuild -showBuildSettings -json から BUILT_PRODUCTS_DIR/WRAPPER_NAME/EXECUTABLE_NAME/PRODUCT_BUNDLE_IDENTIFIER を検出して、captureMemgraph につなげられるホスト PID + UDID + バンドル ID を返します。macOS 26.x で leaks --outputGraph のリグレッションが発生し、対象が環境変数で malloc-stack-logging を有効にして起動された場合にしか動作しないため、必須です。
replayScenariorepeat 回数を指定したタップ/スワイプ/待機/入力アクションで iOS Simulator を操作し、N 回の繰り返し後にのみ発生するリークを増幅させます。タップ対象には label、elementId、coords を指定できます。Cameron Cooke の axe CLI にソフト依存します。
captureScenarioState修正検証用の複合スナップショットとして、.memgraph + .png スクリーンショット + .ui.json アクセシビリティツリーを outputDir に書き込み、すべてに label(通常は before/after)を付けます。各キャプチャはベストエフォートです。macOS 26.x で leaks が失敗しても、スクリーンショットと UI ツリーの取得は完了し、captureMemgraph の workaroundNotice は memgraphWorkaroundNotice 経由で通知されます。
検出(3)
ツール内容
listTraceDevicesxcrun xctrace list devices(デバイス + シミュレーター + UDID)を解析します。
listTraceTemplatesxcrun xctrace list templates(標準 + カスタム)を解析します。
inspectTrace.trace バンドルの概要を確認するツールです。含まれるスキーマ + 行数 + デバイス/OS/テンプレートのメタデータ + データが存在する各既知スキーマを対応するアナライザーに割り当てる suggestedNextCalls[] を返します。すべての .trace で最初に呼び出してください。v1.11 で追加。v1.17:xctrace export --toc が使用不能な 52K バンドルで失敗した場合、例外をスローせず、診断文字列と schemas: [] を含む ok: true を返すフォールトトレラントな動作に対応しました。
統合(1)
ツール内容
summarizeTraceinspectTraceと5つのアナライザーを並列で連結して一度に呼び出し、検出結果を相互に照合(重なっているハングとヒッチなど)し、コンパクト(<10 KB)なMarkdownサマリーカードを事前に生成します。カードには1文の見出し、領域ごとのサブセクション、suggestedNextCallsが含まれます。「トレースからサマリーカードを1回の呼び出しで生成する」機能です。5〜6個のアナライザーを手動で連結する代わりに、統合処理を1回実行したい場合に使用します。v1.13で追加。v1.18 D-02:最初にスキーマ検出を1回実行し、キャッシュを6つすべてのアナライザーで共有することで、実際のAppleトレースで経過時間を600〜3000ms短縮します。
本番環境の診断(1、v1.18)
ツール内容
analyzeMetricKitPayload実デバイスのTestFlight/App StoreビルドからApple MetricKitの.mxdiagnostic JSONペイロードを取り込みます(現時点でこの領域をカバーするMCP競合ツールはありません)。入力形式は3種類です:payloadPath(単一ファイル)、payloadDir(ディレクトリ内のすべての.mxdiagnosticファイルを集約)、payloadJson(メモリ内の生データ)。出力セクションは3つです:crashCluster[](exception-type/binary/top-frameでグループ化され、各エントリにはtopFrame、affectedBuilds[]、下流のdSYMシンボリケーション用の生のbinaryUUID + offsetを含む)、hangHotspots[]("5.4 sec"/"20秒"などのローカライズされた時間表記を解析し、hangDurationMs順にソート)、cpuExceptions[]およびdiskWriteExceptions[]。新しいSupportStatusKind値を4つ出力します。ツール間の連携ヒントが自動的に生成されます(objc_release形式のトップフレーム → findCycles、libsqlite3のトップフレーム → メインスレッド違反分類器を使用したanalyzeHangs)。v1ではシンボリケーションを行わず、生バイトのみを扱います。シミュレーターはMetricKitペイロードを生成しません(Apple側の制限)。ライブキャプチャではなく、事後分析用のアナライザーとして位置付けられています。v1.18で追加。
レンダリング(1)
ツール内容
renderCycleGraph.memgraphを読み込み、ROOT CYCLEを選択し、Mermaidグラフ(Markdownに埋め込み可能)またはGraphviz DOTを出力します。アプリレベルのクラスは赤色、CYCLE BACKの終端はアンバーで強調表示されます。
運用(1)
ツール内容
cleanupTracesMEMORYDETECTIVE_TRACE_ROOT配下の.traceバンドルをプレビューして削除します。既定ではdryRun: true(エージェントが削除を明示的に選択する必要があります)。.traceの境界で処理を停止し、バンドルの内部には入りません。外部ルートを対象にするにはMEMORYDETECTIVE_ALLOW_EXTERNAL_CLEANUP=1が必要です(既定では拒否)。recordTimeProfileセッションを数回実行し、トレースが数十〜数百MB蓄積した後の定期的な呼び出しに便利です。
CI/テスト連携(3)
ツール内容
detectLeaksInXCTestユニットテストのスキームをビルドし、任意の-only-testing:フィルターを指定して実行します。xctestランナー(またはアプリホスト型バンドルの場合はカスタムのprocessName)に対して、前後の.memgraphベースラインを取得して比較します。ユーザーの許可リストにない新しいROOT CYCLEが見つかった場合は、passed: falseを返します。outputHtmlPathを設定すると、自己完結型のHTMLレポートも出力できます。CIで実行可能です。
detectLeaksInXCUITestXCUITest版です。ワークスペースをビルドし、名前を指定したXCUITestを実行して、ホストアプリに対する前後の.memgraphベースラインを取得して比較します。ユーザーの許可リストにない新しいROOT CYCLEが見つかった場合は、passed: falseを返します。outputHtmlPathを設定すると、自己完結型のHTMLレポートも出力できます。CIで実行可能です。
compareTracesByPatternverifyFixに対応するトレース側の機能です。パフォーマンスカテゴリ(hangs、animation-hitches、またはapp-launch)について、2つの.traceバンドルを比較し、前後の統計値と差分とともにPASS/PARTIAL/FAILを返します。しきい値を適用します:ハングは最長時間がhangsMaxLongestMs未満ならPASS、ヒッチは最長時間がhitchesMaxLongestMs未満ならPASS(既定値は100ms。Appleが定める、ユーザーが知覚できるしきい値)、アプリ起動は合計時間がappLaunchMaxTotalMs未満ならPASS(既定値は1000ms)。
5 分で memorydetective を CI に追加する

detectLeaksInXCTest と outputHtmlPath は、PR ごとのリーク検出ゲートを構築するための基本要素です。以下のジョブは、すべての push と PR で指定したユニットテストのスキームを実行し、HTML レポートをワークフローのアーティファクトとしてアップロードします。また、許可リストにない新しい ROOT CYCLE が見つかると失敗します。このファイルを .github/workflows/leaks.yml にコピーし、workspace、scheme、test identifier を調整してください。

name: leaks
on: [push, pull_request]
jobs:
  detect-leaks:
    runs-on: macos-14
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      - run: sudo xcode-select -s /Applications/Xcode_15.4.app
      - run: npm install -g memorydetective
      - run: |
          xcrun simctl boot "iPhone 15" || true
          xcrun simctl bootstatus "iPhone 15" -b
      - run: |
          cat > leaks.json <<EOF
          {
            "workspace": "DemoApp.xcworkspace",
            "scheme": "DemoAppTests",
            "destination": "platform=iOS Simulator,name=iPhone 15,OS=18.0",
            "testCaseFilter": "DemoTests/LeakSensitiveCase",
            "outputHtmlPath": "${GITHUB_WORKSPACE}/leak-report.html",
            "allowlistPatterns": ["SwiftUI", "_TtC"]
          }
          EOF
          memorydetective tool detectLeaksInXCTest --input leaks.json
      - if: always()
        uses: actions/upload-artifact@v4
        with:
          name: leak-report
          path: leak-report.html
          retention-days: 14

同じファイルは examples/ci/github-actions-leaks.yml にもあります。そのままコピーしたい場合にご利用ください。注意点:

  • シミュレーターのランタイム: macos-14 ランナーでは iOS 18 を指定してください。macOS 26.x のカーネルのリグレッション(task_for_pid)により、iOS 26 シミュレーターに対する leaks の実行が妨げられます。iOS 18 は標準的な回避策です(上記の「Highlights」コールアウトを参照)。
  • 許可リストのパターン: リークしている ROOT CYCLE のルートクラスに対して照合される部分文字列です。バックログに取り組む間、既知の既存リークを除外するために使用します。_TtC は、SwiftUI の内部でときどき現れる、Swift のマングルされたクラスのプレフィックスに対応します。
  • HTML アーティファクト: レポートは自己完結型(CSS をインラインで含み、外部アセットはありません)なので、PR コメントボットやレビュアーはアーティファクトの URL から直接プレビューできます。
  • ビルドキャッシュ: Package.resolved と *.xcconfig をキーにした actions/cache@v4 を追加すると、実行をまたいで build-for-testing の再ビルドを省略できます。そのうえで、同じジョブ内で複数の detectLeaksInXCTest 呼び出しを連続して実行する際、2 回目の呼び出しに --skipBuild を渡してください。
Swift ソースのブリッジ(5)

メモリーグラフによる診断と SourceKit-LSP によるソースコード検索を組み合わせます。「このサイクルでリークが見つかった」から「プロジェクト内のファイル/行を特定する」までをつなげます。

ツール内容
swiftGetSymbolDefinitionSwift のシンボルが宣言されているファイルと行を特定します。まず candidatePaths(または hint.filePath)を高速な正規表現で事前スキャンし、その後 SourceKit-LSP に定義へ移動するよう要求します。
swiftFindSymbolReferencesSourceKit-LSP の textDocument/references を使って、Swift のシンボルへのすべての参照を検索します。ファイルをまたぐ検索結果には IndexStoreDB が必要です。インデックスがない場合、応答には needsIndex のヒントが含まれます。
swiftGetSymbolsOverviewdocumentSymbol を使って、Swift ファイル内のトップレベルのシンボル(クラス、構造体、列挙型、プロトコル、グローバル関数)を一覧表示します。エージェントが新しいファイルを開いたときに、手軽に概要を把握できます。
swiftGetHoverInfo指定した位置(行、文字)にある型情報やドキュメントを取得します。self のキャプチャを見分けるのに役立ちます。クロージャ内のクラスの self はリークする可能性がありますが、構造体の self はリークしません。
swiftSearchPatternSwift ファイルを正規表現だけで検索します(LSP とインデックスは使用しません)。LSP が見逃す、クロージャのキャプチャリスト、Task { ... self ... } ブロック、リークチェーンから導かれたカスタムパターンを検出します。

これらのツールには macOS と Xcode(Command Line Tools だけではなく、完全な Xcode)が必要です。xcrun sourcekit-lsp が利用可能でなければなりません。プロジェクトのルートごとに sourcekit-lsp のサブプロセスを起動し、呼び出し間で再利用します。サブプロセスは 5 分間アイドル状態が続くと終了します。

captureMemgraph が実機の iOS デバイスで動作しない理由:leaks(1) が接続できるのは、ローカルの Mac 上で動作するプロセスだけです(iOS シミュレーターを含みます)。実機からのメモリーグラフの取得には、USB/lockdownd 経由の Xcode デバッガーを使用します。これは別の仕組みであり、同等の公開 CLI はありません。

リソース(34)

サイクルパターンのカタログは MCP リソースとしても公開されており、memorydetective://patterns/{patternId} から閲覧できます。各リソースは、パターン名、詳しい説明、修正のヒントを含む Markdown 本文です。これを使うと、classifyCycle を呼び出さなくても、エージェント(または UI 対応の MCP クライアントを使う人)がカタログを閲覧できます。

memorydetective://patterns/swiftui.tag-index-projection
memorydetective://patterns/concurrency.async-sequence-on-self
memorydetective://patterns/webkit.wkscriptmessagehandler-bridge
memorydetective://patterns/swiftdata.modelcontext-actor-cycle
…

resources/list は 34 件すべてを返します。resources/read は任意の memorydetective://patterns/{id} URI を対応する Markdown 本文に解決します。

プロンプト(7)

調査プレイブックは MCP プロンプトとして公開されます(対応クライアントのスラッシュコマンド。例:Claude Code)。

スラッシュコマンド機能引数
/investigate-leakmemgraph-leak の標準的な6ステップの調査を実行します:analyzeMemgraph → classifyCycle → reachableFromCycle → swiftSearchPattern → swiftGetSymbolDefinition → swiftFindSymbolReferences。memgraphPath
/investigate-hangs.trace から、ユーザーに見えるメインスレッドのハングを診断します。tracePath
/investigate-jank.trace から、フレーム落ち/アニメーションのカクつきを診断します。tracePath
/investigate-launch.trace から、コールド/ウォーム起動の遅さを診断します。tracePath
/verify-cycle-fix修正が反映されたことを確認するため、修正前後の .memgraph スナップショットを比較します。before、after
/summarize-trace.trace のスキーマを横断するサマリーカードを1回の呼び出しで生成します。summarizeTrace をラップします。v1.13 以降。tracePath
/investigate-metrickitTestFlight/App Store ビルドの Apple MetricKit .mxdiagnostic ペイロードを対象とした事後分析フローです。crashCluster + hangHotspots + cpuExceptions + 優先度順の diskWriteExceptions の読み取りと、ツール横断チェーンのヒント(objc_release → findCycles、sqlite → analyzeHangs)を含む analyzeMetricKitPayload をラップします。v1.18 以降。payloadPath

各プロンプトは、ユーザー指定の値で標準プレイブックの引数テンプレートを埋め、エージェントに実行準備済みのブリーフを渡します。読み取りと分析に記載されているものと同じツールを呼び出します。プロンプトはオーケストレーションを簡略化するものであり、別個のエンジンではありません。

CLI モード

同じバイナリは、スクリプト作成や CI に使えるシンプルな CLI としても動作します。

memorydetective analyze   <path-to-.memgraph>          # totals, ROOT CYCLEs, diagnosis
memorydetective classify  <path-to-.memgraph>          # match patterns + render fix hint
memorydetective tool      <toolName> --input <json>    # generic dispatcher for any MCP tool
memorydetective --help
memorydetective --version

引数なしで呼び出すと、バイナリは stdio 経由の MCP サーバーとして起動します。

tool サブコマンドは、JSON ファイルから入力を読み込み、名前で任意の登録済み MCP ツールを実行します。終了コードは、ツールが ok && passed !== false を返した場合は 0、それ以外は 1 です。そのため、CI ゲートに簡単に組み込めます。現在サポートされているツール名は detectLeaksInXCTest、detectLeaksInXCUITest です(上記の5分で完了する CI への memorydetective の追加手順で使用しています)。


必要条件

  • Xcode Command Line Tools をインストールした macOS(xcode-select --install)
  • Node.js ≥ 20

開発

git clone https://github.com/carloshpdoc/memorydetective
cd memorydetective
npm install
npm test                  # 758 unit tests
npm run build             # build → dist/
npm run dev               # tsx, stdio mode (dev mode)
./scripts/demo.sh         # full demo against a real .memgraph (set MEMGRAPH=path)

コントリビューション

コントリビューションを歓迎します。バグ報告、機能リクエスト、新しいサイクルパターンなど、どんなものでも歓迎です。

  • バグ/機能リクエスト:issue を作成してください。
  • PR:フォーク → ブランチ作成 → npm install → 変更 → npm test(758件のテストすべてが成功し続ける必要があります)→ 変更内容と理由を簡潔に説明した PR を作成してください。
classifyCycle へのサイクルパターンの追加

classifyCycle には、SwiftUI(Swift 6/@Observable/SwiftData/NavigationStack/v1.9 の observable-write-on-every-render と viewcontroller-retained-after-pop のパターンを含む)、Combine、Swift Concurrency(AsyncSequence-on-self と Observations を含む)、UIKit(Timer/CADisplayLink/UIGestureRecognizer/KVO/URLSession/WebKit/DispatchSource)、Core Animation、Core Data、Coordinator パターン、RxSwift、Realm を対象とした36個の組み込みパターンが含まれています。追加するには、次の手順に従います。

  1. src/tools/classifyCycle.ts を編集します。id、name、fixHint、match 関数を含むエントリーを PATTERNS に追加します。
  2. src/tools/readTools.test.ts にテストを追加し、代表的な memgraph フィクスチャに対して新しいパターンが検出されることを確認します。
  3. src/runtime/staticAnalysisHints.ts に staticAnalysisHint エントリーを追加します(このファイルのテストで PATTERNS との1対1の対応が検証されます)。
  4. src/runtime/fixTemplates.ts に fixTemplate エントリーを追加します(同じく1対1の対応チェックがあります)。
  5. PR を作成します。

このプロジェクトを支援する

memorydetective が時間の節約に役立った場合は、継続的な開発をご支援いただけます。

すべてのご支援が、このプロジェクトの保守とドキュメント整備に役立ちます。

ライセンス

Apache 2.0 です。LICENSE と NOTICE をご覧ください。

商用利用、変更、配布、特許の使用が許可されています。NOTICE ファイルによる帰属表示条項が含まれます。

なぜ「memorydetective」なのか?

SwiftUI のリテインサイクルを探す作業は、探偵の仕事に似ています。被害者(リークしたインスタンス)、現場(.memgraph)、容疑者の連鎖(リテインチェーン)がそろっています。このツールは証拠を読み解き、犯人を特定する手助けをします。ブランドは、その仕事にちなんでいます。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。