memorydetective: dando a agentes de IA 31 ferramentas para debugar leaks de iOS
Como funciona o memorydetective, MCP server open source que conecta Claude Code, Cursor e Cline aos artefatos binarios da Apple para debugar leaks e perf no iOS.

memorydetective: dando a agentes de IA 31 ferramentas para debugar leaks de iOS
Tese central
LLMs são ótimos para raciocinar sobre código Swift e ruins para debugar memória no iOS. O motivo não é falta de inteligência do modelo. É falta de acesso. As evidências do problema vivem em arquivos binários que o modelo não consegue ler. memorydetective é a ponte que faltava: 31 ferramentas MCP que embrulham as CLIs da Apple e devolvem summaries estruturados que o agente consegue de fato processar.
Para quem é este artigo
- Engenheiros iOS que já sentiram a frustração de pedir a um LLM para consertar um retain cycle no SwiftUI e receber um wholesale
[weak self]que não resolve - Pessoas construindo agentes ou MCP servers e curiosas sobre patterns de bridging entre LLM e ferramentas binárias
- Quem usa Claude Code, Cursor ou Cline e quer estender o agente para perf investigation
Contexto
Quando tu pede a um agente para diagnosticar um leak de memória no iOS, ele não tem como olhar para o heap. O .memgraph que o Xcode exporta é binário, tem 50 a 500 MB e não cabe em janela de contexto. O dump textual do leaks(1) chega a 200 KB de frame chains repetitivas. O .trace do Instruments é um bundle estruturado que o agente não consegue navegar. Sem acesso aos artefatos, o modelo recorre ao que conhece de treinamento: pattern matching em shapes de cycle. O resultado mais comum é o refactor wholesale de [weak self] que parece bom no diff, mas não consertou o leak, quebrou duas closures não relacionadas e silenciosamente perdeu trabalho assíncrono.
A solução não é usar um modelo melhor. É dar ao modelo as ferramentas certas. MCP fez isso virar coisa que se constrói como side project.
O que memorydetective faz
memorydetective é um MCP server open source (Apache 2.0) que expõe 31 ferramentas para Claude Code, Claude Desktop, Cursor, Cline e qualquer cliente MCP. As ferramentas embrulham as CLIs nativas da Apple (leaks, heap, vmmap, malloc_history, xctrace, SourceKit-LSP) e devolvem summaries estruturados de 2 a 5 KB no lugar dos dumps brutos.
O ganho não é marginal. Em uma investigação real, o agente que precisava ler 280 KB de dump textual em ~70.000 tokens de input para tentar entender o leak agora consome ~3.000 tokens em duas chamadas de tool. A redução de ~25x em token usage por investigação também se traduz em wall clock: o que era uma sessão de 60 minutos no Instruments vira ~10 minutos no chat.
As 31 ferramentas se agrupam em buckets:
- Read & analyze de
.memgraph:analyzeMemgraph,findCycles,findRetainers,countAlive,reachableFromCycle,diffMemgraphs,verifyFix,classifyCycle(matcheia contra 34 antipatterns nomeados de SwiftUI, Combine, Concurrency, UIKit, Core Data, RxSwift, Realm e devolve umfixTemplateSwift before/after) - Read & analyze de
.trace:analyzeHangs,analyzeAnimationHitches,analyzeTimeProfile,analyzeAllocations,analyzeAppLaunch. Embrulham os schemas que a Apple ship mas não expõe programaticamente - Capture:
captureMemgraph,recordTimeProfile,logShow,logStream - Verify-fix orchestration (novidade da v1.8):
bootAndLaunchForLeakInvestigationfaz build, boot, install e launch comMallocStackLogging=1em uma chamada só.replayScenariodirige o iOS Simulator através de tap, swipe, wait e type comrepeatcount para amplificar leaks que só aparecem depois de N iterações.captureScenarioStateescreve snapshots labeled de.memgraph+.png+.ui.jsonpara diff determinístico antes e depois - Swift source bridging: 5 ferramentas que embrulham SourceKit-LSP. O agente vai de “o cycle root é DetailViewModel” para “declared at Sources/ViewModels/DetailViewModel.swift:18, 7 callsites” sem abrir o Xcode
- CI gating:
compareTracesByPatternpara regressão de hangs, animation hitches e app launch.detectLeaksInXCUITest(experimental) para gating no PR
Como parece em chat
Um exemplo concreto, no Claude Code:
You: Acabei de exportar um memgraph em
~/Desktop/example.memgraph. Algo está vazando depois que eu fecho a tela de detalhe. O que é?Claude: (chama
analyzeMemgraph+classifyCycle) Encontrei 4 ROOT CYCLE blocks em 60.436 leaks. O dominante matcheiaswiftui.tag-index-projectioncom alta confiança. Uma closure aplicada via.tag()em umForEachde carrossel de fotos está capturandoselfatravés de_viewModel.wrappedValue, prendendo aproximadamente 28 MB de network state.(chama
swiftSearchPatternno projeto) 1 match:MyApp/Views/MediaCarousel.swift:142.Sugestão de fix: substituir
[weak self]no tap handler por um helper estático, ou weak capture do view model via[weak coord = self.coordinator]. Quer que eu aplique e verifique com um memgraph fresco?
Tudo isso em duas chamadas de chat. Sem Instruments aberto.
O que ficou claro construindo
Três decisões de design ficaram mais importantes do que a lista de tools em si.
A primeira foi devolver o que o agente precisa fazer a seguir, junto da resposta. Cada tool response carrega um campo suggestedNextCalls com uma lista tipada de { tool, args, why }. Isso reduz drasticamente os turns em que o agente precisa re-raciocinar sobre o resultado para descobrir o próximo passo. É pequeno em código e grande em token economy.
A segunda foi não engolir falhas do sistema. Quando uma CLI da Apple regride, como aconteceu no macOS 26.x onde leaks --outputGraph passou a exigir MallocStackLogging=1 no launch, o tool não finge que funcionou. Ele devolve um workaroundNotice estruturado com issue ids estáveis (minimal-corpse, permission-denied, leaks-not-found, transient) e um caminho de fallback para o agente chainear. Para outros agentes que vão chainear essas chamadas em CI, isso muda completamente a robustez do pipeline.
A terceira foi matar o ciclo de vida do output. Cada tool entrega summaries pequenos e nomeados, não stream cru. O agente nunca precisa parsear o output da leaks(1) linha por linha. Isso é o que torna possível uma investigação de leak custar centavos em vez de dólares por turn.
Limites honestos
memorydetective só funciona em macOS porque depende das CLIs da Apple. Memgraph capture funciona em apps Mac e iOS Simulator, não em devices físicos: leaks(1) só attacha a processos locais, e capture de device real passa por Xcode debugger via USB sem equivalente em CLI pública. analyzeTimeProfile devolve um workaroundNotice estruturado quando o xctrace dá SIGSEGV em traces pesados unsymbolicated, que é uma limitação Apple-side que decidi expor explicitamente em vez de mascarar. replayScenario tem dependência soft do CLI axe do Cameron Cooke para drive de UI. O resto roda sem axe instalado.
O que vem depois
A versão 1.8.0 é o que eu publiquei na semana passada na npm. Os próximos passos do roadmap incluem mais cycle patterns no classifier, especialmente da era Swift 6 com @Observable e Observations, cobertura dos schemas restantes do xctrace (network, energy, file IO) e um verify-fix loop alternativo que não requer axe, usando só APIs do simulador.
Roadmap está no GitHub. Issues e PRs são bem-vindos.
Como instalar
Em qualquer Mac com Xcode Command Line Tools e Node 20+:
npm install -g memorydetective
Aponta o teu cliente MCP. Para Claude Code:
// ~/.claude/settings.json
{
"mcpServers": {
"memorydetective": { "command": "memorydetective" }
}
}
O mesmo bloco serve para Claude Desktop, Cursor, Cline, Kiro e GitHub Copilot agent mode (full configs no README).
Conclusão
memorydetective é o que acontece quando tu para de pedir a um LLM para adivinhar e começa a dar a ele as ferramentas que faltam. A premissa do projeto cabe em uma frase: turn a 50 a 500 MB binary memgraph (or a 200 KB leaks(1) text dump) into a 2 a 5 KB structured summary your AI agent can actually reason about. Isso muda a economia de usar LLM para investigação iOS de “marginal” para “default”.
Apache 2.0. Open source. Roda em qualquer cliente MCP.
CTA
Se você trabalha com iOS e usa Claude Code, Cursor ou Cline, dá uma chance ao memorydetective em uma investigação real. Se for útil, a melhor forma de apoiar o projeto é abrir issue quando algo não funcionar e me contar qual cycle pattern você gostaria que o classifier pegasse.
Referências
- memorydetective no GitHub
- memorydetective na npm
- Article B: An afternoon of iOS perf work with Claude in the loop (case study real de produção que drovou as features v1.7 e v1.8)
- Apple Developer: Gathering information about memory use
- WWDC21: Detect and diagnose memory issues
- Model Context Protocol spec
Gostou do artigo?
Curta e deixe um comentário. Isso me ajuda a saber o que escrever a seguir.
Comentários