Slimdex

Recuperação estreita de código para agentes de codificação — esboços, corpos de símbolos, grafos de dependência e memória persistente em vez de leituras de arquivos inteiros.

Documentação

slimdex-mcp

npm MCP Registry Glama score license

Seu agente lê um arquivo de 900 linhas para alterar uma função — e depois paga por esse arquivo novamente a cada turno seguinte. Toda a conversa é reenviada a cada vez, então uma leitura inicial não é um custo único. É um aluguel.

Slimdex é um servidor MCP local que dá aos agentes de codificação recuperação estreita em vez disso: o esboço de um arquivo, o corpo de um símbolo, quem o chama, o que quebra se ele mudar — e memória que sobrevive à sessão, para que o próximo chat comece informado em vez de redescobrir o repositório do zero.

claude mcp add slimdex -- npx -y slimdex-mcp

~50% menos tokens no uso diário — ~55–60% em trabalho pesado de navegação, ~45% em trabalho pesado de saída, e 85–90% no pior caso para o qual foi construído (um arquivo de 6.200 linhas, explorado através de um esqueleto e 12 corpos de símbolos em vez de quatro leituras completas).

Status: 1.1.0, no npm e no Registro MCP. Esses números são automedidos nos repositórios em que foi executado, sessões únicas, não validados de forma independente — e stats conta caracteres, não tokens. Leia O que está realmente verificado antes de confiar nisso.

FerramentaO que retorna
index_repoConstrói/atualiza um índice persistente de símbolos + importações; apenas arquivos alterados são reanalisados
outline_fileDeclarações de um arquivo com números de linha
get_file_skeletonAssinaturas com corpos omitidos, aninhamento preservado
read_linesUm intervalo de linhas, limitado a 6.000 caracteres por padrão com uma linha de continuação; defina maxChars quando mais for necessário
get_symbol_contextUm corpo de função/classe ±2 linhas, limitado por maxLines; names:[...] busca vários corpos em uma única chamada
search_codepath:line:col + a linha correspondente com destaque de cursor; paginação por limit/offset/cursor
find_definitionLocal(is) de definição de um símbolo como path:line:col
search_symbolsBusca difusa por nome de símbolo, classificada exato→prefixo→substring→subsequência
search_intentConsulta em linguagem natural classificada sobre símbolos por BM25 (sem embeddings) — encontre código pelo que ele faz
context_packUma chamada: classifica os símbolos de um tópico, mostra como eles se conectam e agrupa os principais corpos sob um orçamento — toda a exploração em uma única ida e volta
find_referencesReferências textuais como path:line:col + função delimitadora
find_testsDas referências a um símbolo, quais estão em arquivos de teste — ou um aviso de que nenhuma está
replace_symbolSobrescreve o corpo de um símbolo endereçado por nome (sem reenviar código antigo); tira snapshots primeiro, reindexa depois
get_contextUma chamada: definição / assinatura / chamadores / importações / dependentes opcionais, com orçamento
repo_mapContagens de arquivos/linhas/símbolos no nível de diretório; path: detalha os maiores arquivos de um diretório
changed_filesArquivos alterados + em quais símbolos cada trecho de alteração se encaixa
dep_graphimports / dependents / um diagrama Mermaid (BFS de root+depth)
statsContagens de chamadas por ferramenta e tamanhos de resposta, em caracteres, além da mistura de leituras e disciplina de escrita
batchExecuta várias chamadas em uma única solicitação
recapAtividade de sessões anteriores, reconstruída automaticamente a partir do diário de chamadas de ferramentas do servidor — funciona mesmo quando nada foi salvo
briefAbertura compacta de sessão: resumo do repositório + foco derivado do diário + conclusões recentes verificadas contra o índice ativo (✓ ativo / ⚠ possivelmente desatualizado); detail:"full" expande o resumo e as prévias de memória
digest_save / digest_getArmazene uma folha de referência compacta da arquitetura do repositório uma vez; leia-a de volta com um veredito de frescor por arquivo coberto, para que a próxima sessão pule a reexploração
snapshotCopia arquivos não confirmados para .slimdex/snapshots/ (também é executado automaticamente a cada hora via index_repo em uma árvore suja) — seguro contra redefinições acidentais, não um substituto para confirmar
memory_save/search/list/deleteNotas duráveis em .slimdex/memory.json

As orientações de recuperação abaixo também são enviadas no instructions do servidor MCP, para que os clientes as injetem automaticamente no contexto do modelo.

Fluxo de agente recomendado

brief primeiro, bem no início de uma sessão — uma chamada que informa o que é o repositório, onde sessões recentes estavam cavando e quais conclusões salvas ainda correspondem ao código (as desatualizadas são sinalizadas), para que um novo chat comece informado em vez de em branco. Depois, get_context("Foo") para responder "o que é isso, quem chama, do que depende" em uma única resposta. Para entender uma área inteira em vez de um símbolo, context_pack("how does auth work") executa toda a exploração no lado do servidor e devolve um único pacote limitado — os símbolos relevantes, como eles se conectam e os principais corpos — para que você gaste uma chamada e uma entrada de transcrição em vez de dez. Não sabe o nome, só o que faz? — search_intent("parse the config file") classifica símbolos por intenção com BM25, sem embeddings. Desça para get_symbol_context para um corpo (ele se sinaliza se o arquivo se afastou do índice, para que você não releia para verificar), get_file_skeleton para a forma de um arquivo e read_lines quando precisar do código-fonte exato. Antes de editar um símbolo, execute find_tests nele para ver o que o cobre; para reescrever uma função inteira, use replace_symbol (você envia apenas o novo corpo — o código antigo não é reenviado apenas para localizar a edição). Use batch para agrupar várias consultas. Toda ferramenta de busca aceita limit (padrão 20) e offset.

Orçamento de resposta: as seções de get_context são opcionais via include (padrão: definição, assinatura, chamadores, importações — adicione body ou dependents explicitamente), os chamadores são limitados por callerLimit e a resposta é limitada por maxChars (padrão 12.000). Todo limite que estourar imprime um aviso explícito (showing 3 of 68, truncated at maxChars=...) em vez de descartar dados silenciosamente. get_symbol_context limita seu intervalo com maxLines da mesma forma, e memory_list retorna os 50 fatos mais recentes, a menos que seja instruído de outra forma, como prévias de ~150 caracteres em vez de corpos inteiros (memory_get ids:[...] os expande, full:true despeja tudo). Em um armazenamento de 18 fatos, essa é a diferença entre ~4.100 e ~18.600 caracteres na chamada que toda sessão abre.

Config: <root>/.slimdex.json (opcional)

{
  "ignoreDirs": ["fixtures", "backend/src/main/resources/static/assets"],
  "extensions": [".astro", ".vue"],
  "suffixes": [".stories.mdx"],
  "exclude": ["generated/", "legacy/vendor"],
  "maxFileBytes": 2000000
}

suffixes corresponde a um final de nome de arquivo, para tipos de arquivo que uma extensão não consegue identificar. Arquivos auxiliares de metadados do Salesforce vêm como integrados: AccountSvc.cls-meta.xml, panel.js-meta.xml e Account.object-meta.xml são indexados, enquanto pom.xml, web.xml e manifest/package.xml não são — adicionar .xml a extensions teria puxado todas as árvores de configuração do repositório. Arquivos correspondidos por sufixo são indexados para alcance de busca e leitura, não para símbolos.

Mesclado sobre a lista de ignorados integrada (node_modules, dist, .venv, .svelte-kit, Pods, .pytest_cache, …). Uma entrada de ignoreDirs é um nome simples, correspondendo a qualquer diretório assim chamado em qualquer profundidade, ou um caminho contendo /, ancorado na raiz do repositório e respeitando limites de diretório (src/gen não também ignorará src/generated). index_repo ecoa o que carregou e avisa sobre chaves desconhecidas, tipos errados ou JSON inválido, para que uma configuração com erro de digitação não seja silenciosamente indistinguível de nenhuma.

A saída de build geralmente não precisa de configuração alguma. Além da lista de diretórios, qualquer arquivo cujas linhas ultrapassem ~5.000 caracteres é tratado como saída de build minificada e deixado de fora do índice — bundlers removem quebras de linha, e código-fonte escrito à mão não se parece com isso. Isso captura o que uma lista de nomes estruturalmente não consegue: um bundle com nome de hash (index-B7xK2p9q.js) dentro de um diretório chamado assets. assets, public e static deliberadamente não são ignorados por nome, porque código-fonte real vive neles; index_repo relata a contagem como skipped(minified build output): N.

Como funciona a economia de tokens

Não há truque de compressão. A economia é comportamental: essas ferramentas permitem que um agente recupere esboços, intervalos e localizações em vez de arquivos inteiros, e o índice persistente significa que consultas repetidas atingem uma consulta em cache em vez de uma releitura.

Duas sessões posteriores, executadas por modelos diferentes em formatos de repositório diferentes, adicionaram números do mundo real ao relatório original:

Aplicativo web de vários arquivos, sessão de correção de bug (GPT-5.3-Codex). 19 créditos relatados com slimdex; a estimativa do próprio modelo para o mesmo escopo sem ele: 45–70 créditos. Matemática: 19/45 → 19/70 ≈ 58–73% mais barato. O contrafactual é a estimativa do modelo, não um A/B medido — direcional.

Arquivo gigante único (folio-app: um app.js de 6.200 linhas, 313 KB). Estatísticas do próprio Slimdex: ~34.000 caracteres em 8 chamadas ≈ 9–10k tokens — um esqueleto (213 assinaturas), depois corpos de apenas ~12 funções relevantes, 9 delas buscadas em uma única chamada de get_symbol_context names:[...]. O caminho ingênuo: 313 KB ≈ 78–85k tokens em 3–4 leituras completas forçadas. Matemática: ~10k vs ~80k ≈ ~70k tokens economizados, uma redução de 85–90% na exploração. O diagnóstico do bug (um caminho de exportação sem caminho de importação correspondente) era visível nas assinaturas do esqueleto antes de um único corpo ser aberto.

Juntos, eles esboçam a lei de escala: a economia escala com quanto código irrelevante o caminho ingênuo arrastaria. Um arquivo gigante é o melhor caso; um repositório normal fica em torno de metade a dois terços mais barato; um repositório de arquivos minúsculos empata. Mesmas ressalvas de sempre: as estatísticas contam caracteres, não tokens (÷3,5–4), e sessões únicas são evidência, não benchmarks.

Ambos os números acima medem apenas leitura, que é a metade mais barata. A saída custa aproximadamente 4–5× a entrada, então uma edição indisciplinada desperdiça mais do que uma leitura indisciplinada: reescrever uma função inteira através de uma ferramenta de edição genérica significa reenviar todo o corpo antigo apenas para que a ferramenta possa localizá-lo. replace_symbol endereça por nome e esse custo desaparece. stats relata isso junto com a mistura de leituras, porque o vazamento é invisível de outra forma — o caminho caro ainda produz uma edição correta, então nada sinaliza que você pagou demais:

write discipline:
  replace_symbol: 0 call(s), 0 symbol(s) rewritten by name
  changed outside slimdex: 12 file(s)
  pre-edit checks (find_tests/dep_graph/get_context/changed_files): 0

Edições externas são inferidas a partir de hashes de conteúdo que se movem entre duas execuções de index_repo, então o número é honesto sobre seus limites: ele vê que os bytes mudaram, nunca qual ferramenta os mudou, e um humano editando em outra janela também conta.

A faixa realista de fluxo de trabalho completo

Os números acima são números de exploração de cenário único — o melhor caso, onde o caminho ingênuo teria arrastado o máximo de código irrelevante. Em média em um dia de trabalho real inteiro, não apenas na fatia de exploração, a faixa se estabiliza mais baixa:

  • ~55–60% em trabalho pesado de navegação — ler e entender uma base de código, onde a recuperação estreita substitui leituras de arquivos inteiros com mais frequência.
  • ~45% em trabalho pesado de saída — produzir novo código, onde mais do custo é geração que o servidor não toca (embora replace_symbol agora também reduza o lado da escrita).
  • ~50% em média no uso regular do dia a dia. A economia se acumula quanto mais sessões passam por ele, porque brief e memória significam que cada novo chat começa informado em vez de redescobrir o repositório do zero.

Use-o regularmente entre sessões no seu IDE para obter o melhor disso.

Trate estes como um único ponto de dados, não um benchmark. Repositório único, tarefa única, uma execução A/B cada, automedido, sem repetições ou variância. Seu resultado depende fortemente de seu agente realmente alcançar as ferramentas estreitas em vez de cair de volta na leitura de arquivos — o que varia por cliente e modelo. O método é repetível se você quiser verificar: execute a mesma tarefa em duas sessões novas, uma instruída a usar apenas Slimdex e outra instruída a evitá-lo, e compare a escrita de cache de /status.


O que está realmente verificado

Sendo explícito, já que o resto deste README é fácil de ler demais.

Coberto pela suíte de testes unitários (npm test executa 224 testes em 23 arquivos):

  • Extração de símbolos em JS/TS (incl. métodos de classe e objeto-literal), Python, Go, Rust, Java/C#, e pulo de comentários — symbols.test.ts

  • Extração de imports para JS import/require/export-from, Python, Rust

  • Extração de blocos, com escopo por chaves e por indentação, com consciência de strings/comentários (aspas, templates, //, /* */, # de linha inteira) — extractBlock.test.ts

  • Resolução de imports, classificação de módulos externos, dependentes por aresta reversa, emissão de Mermaid, e escopo de profundidade BFS a partir da raiz — graph.test.ts

  • Formato de correspondência de busca, paginação sem sobreposição, contagem de ocorrências por linha, totais exatos, escape/rejeição de regex — search.test.ts

  • Round-trip de cursor opaco e rejeição de cursor malformado; fallback de backend do parser — pagination.test.ts

  • Detecção de declaração de outline vs. fluxo de controle — outline.test.ts

  • Orçamento de get_symbol_context maxLines e aviso de truncamento

  • Mascaramento de string/comentário e rastreamento de profundidade de chaves — lexer.test.ts

  • Extração por linguagem para todas as doze linguagens suportadas — languages.test.ts

  • O cache de índice retorna o mesmo objeto até o índice ser reescrito

  • Carregamento de .slimdex.json: cada chave aplicada através de uma construção de índice real, além dos modos de falha (JSON inválido, chaves desconhecidas, tipos errados) cada um produzindo um aviso visível em vez de silêncio — config.test.ts

  • changed_files contra um repositório git temporário real: atribuição hunk→símbolo, arquivos não rastreados, refs de base explícitas e formatação; pula limpo quando o git não está instalado — git.test.ts

  • O observador de arquivos, com eventos reais do sistema de arquivos: um salvamento é debounced, reindexado e chega ao índice em disco — watch.test.ts

  • Arestas de grafo além de imports: arestas de referência de nome para código sem import (classe→classe usada, interface→implementação via dependentes, trigger→handler) e arestas de fiação declarativa de XML do repositório (binding de metadados→classe), com menções em comentários/strings excluídas e cache por construção — apexgraph.test.ts

  • O cache de arquivos em memória atende repetições sem reler e sempre atende conteúdo fresco após uma mudança em disco — fscache.test.ts

  • Detecção de arquivos de teste nas convenções JS/TS/Python/Go/Ruby/Java/C#, com separadores do Windows normalizados e código-fonte comum (latest.ts, Contest.java) não sinalizado incorretamente — testlink.test.ts

  • O lado da escrita: substituição do bloco de um símbolo, código final preservado e finais de linha CRLF vs LF mantidos para que uma edição não seja reformatada em um diff de arquivo inteiro — edit.test.ts

  • Staleness de memória: um fato é marcado como vivo quando nomeia um símbolo/arquivo que ainda existe, sinalizado como obsoleto apenas quando toda menção de código desapareceu, e deixado sem sinalização para prosa — além de composição breve — brief.test.ts

  • Busca por intenção: tokenização camelCase/snake_case, e ranqueamento BM25 que traz à tona um símbolo com nome diferente por suas palavras de intenção enquanto pontua uma consulta não relacionada como nada — intent.test.ts

  • Frescor: um arquivo mais novo que seu mtime indexado é lido como obsoleto (números de linha podem estar errados), um mtime correspondente é lido como fresco, e um arquivo ausente nunca acusa obsoleto — freshness.test.ts

  • Montagem de context_pack: cabeçalho + símbolos ranqueados + corpos em um único pacote, a mensagem de sem correspondência, controle de orçamento de caracteres que ainda garante o primeiro corpo, e o limite máximo de símbolos — pack.test.ts

  • O resumo de arquitetura: arquivos cobertos modificados após o resumo são lidos como obsoletos, um resumo mais novo é lido como limpo, filtragem de escopo de cobertura e prefixo de diretório, e o veredito renderizado de fresco/obsoleto — digest.test.ts

Coberto de ponta a ponta, através do servidor MCP real (integration.test.ts inicia o servidor via stdio contra um repositório fixture temporário e verifica a saída): index_repo, repo_map, read_lines, get_file_skeleton, outline_file, get_symbol_context, find_definition, find_references, find_tests (o acerto e o aviso de sem cobertura), search_intent (ranqueamento por intenção), context_pack (pacote de uma chamada), digest_save/digest_get (round trip com veredito de frescor), get_context (incluindo seu limite de maxChars), dep_graph (imports + mermaid), batch, search_code, search_symbols, stats, brief, replace_symbol (round trip de escrever-depois-consultar e a recusa de símbolo desconhecido), o round trip de memory_save/search/list/delete, a proteção de escape de caminho e os caminhos não encontrados.

O CI executa a construção e ambas as suítes no Ubuntu + Windows, Node 20 e 22.

Ressalva sobre o teste do observador: fs.watch recursivo é dependente da plataforma, então watch.test.ts degrada para um pulo registrado em sistemas de arquivos que nunca entregam um evento — mesmo comportamento do próprio observador. No Windows, macOS e Linux atual, ele verifica o caminho completo de salvar→reindexar.

npm run smoke ainda existe, mas prova apenas que o pipeline está vivo — as verificações de correção vivem em integration.test.ts.

Verificado por inspeção: src/ não contém chamadas de rede — nenhum código sai da sua máquina. Este você pode verificar você mesmo: grep -rE "fetch\(|https?://|axios|http\.request" src/.

Documentação mais longa

Em docs/:

  • tool-guide.md — cada ferramenta explicada duas vezes (tecnicamente e em palavras simples) com um exemplo cada, o fluxo de trabalho combinado e como a persistência baseada em mtime funciona
  • tool-guide.html — o mesmo guia como uma página estilizada e autocontida para o navegador
  • token-savings-report.md — a medição A/B original, seu método e como repeti-la
  • agent-brain.md — a disciplina operacional completa como um documento legível
  • agent-brain-slim.md — o documento para colocar em um repositório como CLAUDE.md / AGENTS.md. Autocontido e de uma página: escada de economia, tabela pergunta→ferramenta, disciplina de memória, higiene de sessão, limites honestos, botões de ambiente. Mesma cobertura do documento completo com ~30% da prosa, porque as regras de ferramentas são tabelas densas em vez de parágrafos que o servidor já injeta.

Cobertura de linguagens

Duas medições, porque apenas fixtures provam muito pouco.

Fixtures — uma por linguagem, contando as declarações que um desenvolvedor realmente navegaria: 65/65 encontrados, 0 falsos positivos, fixados por test/languages.test.ts.

Código real de terceiros — extração executada em ~11.800 arquivos de várias centenas de pacotes reais (React, Babel, Remix, Socket.io, Playwright, Three.js, Emotion, zod, ajv …) e comparada com uma heurística escrita independentemente para o que conta como declaração: 95,9% de recall. Reproduza você mesmo:

npm run audit -- ./node_modules            # or any directory of code you didn't write

Esse número é um piso, não uma nota — a heurística de verdade conta algumas não-declarações, então o recall real é um pouco maior. Serve para pegar regressões e encontrar a próxima lacuna real.

Sobre frameworks

Quase nada que falhou na auditoria era específico de framework. Frameworks adicionam anotações, decoradores e convenções; raramente inventam sintaxe. Lide com a linguagem e os frameworks vêm junto — as camadas Application/Domain/Selector/ Service/UnitOfWork do fflib extraem completamente (129 declarações) sem uma única regra ciente de fflib.

A única exceção genuína são DSLs de teste. Um arquivo vitest/jest/mocha/RSpec frequentemente não tem declarações de nível superior, então diretórios de teste inteiros costumavam indexar para nada. Títulos de describe/it/test agora são indexados como tipo test, que é o que você realmente navega em um arquivo de teste.

A semântica de framework é recuperada sempre que a referência existe em algum lugar no repositório, através de duas fontes extras de arestas no grafo:

  • Arestas de referência de nome, para linguagens que não têm declaração de import (ex.: Apex): se o código de um arquivo — comentários e strings mascarados — menciona um tipo de nível superior definido em outro arquivo, isso é uma aresta. É isso que torna implements respondível como "quem implementa esta interface", e liga um trigger à classe handler que ele instancia.
  • Arestas de fiação declarativa: bindings que frameworks mantêm em configuração em vez de código (registros de metadados customizados, definições de fluxo) geralmente vivem no repositório como XML com o nome do tipo como um valor de elemento. O XML do repositório é escaneado para nomes de tipos conhecidos — comentários XML excluídos — e cada acerto se torna uma aresta metadata-file → class, então dependents responde "o que conecta isso".

Ambos os escaneamentos são armazenados em cache por construção de índice e não custam nada em repositórios sem tais arquivos. Fixados por apexgraph.test.ts. O que nenhum leitor estático pode ver é um binding que existe apenas em um sistema vivo — configurado em uma org ou banco de dados em execução e nunca recuperado para o repositório. Se não está no repositório em nenhuma forma, não há aresta para desenhar; pesquise o nome do tipo em vez disso.

LinguagemExtensõesO que é reconhecido
JavaScript / TypeScript.js .jsx .mjs .cjs .ts .tsx .vue .svelteclasses, interfaces, tipos, enums, funções, arrows de nível superior, métodos de classe e objeto-literal
Apex.cls .triggerclasses, classes internas, métodos (incl. @AuraEnabled, global, retornos genéricos), triggers
Java.javaclasses, interfaces, enums, métodos, métodos genéricos com um <T> inicial
C#.csclasses, interfaces, structs, métodos async e genéricos, membros virtuais
Kotlin.ktclasses, data classes, interfaces, object, fun, suspend fun
Swift.swiftclasses, structs, enums, protocols, func, static func
Python.pyclasses, def, async def, métodos dunder e decorados
Go.gofuncs, métodos com receiver, tipos struct e interface
Rust.rsstructs, enums, traits, fn, pub async fn, métodos impl
Ruby.rbclasses, módulos, def, def self.x, attr_accessor/reader/writer
PHP.phpclasses, interfaces, traits, métodos, funções
Scala.scalaclasses, case classes, traits, objects, def com modificadores
C / C++ / Objective-C.c .h .cpp .hpp .cc .m .mmclasses, structs, enums, funções livres (incl. chaves K&R, retornos de ponteiro), definições fora da classe Foo::bar, ctors/dtors, namespaces, macros #define semelhantes a funções, typedef struct {…} Name, @interface/@implementation/@protocol

Desempenho

Índice frio é uma análise completa; quente é uma verificação de mtime por arquivo. Medido no Windows, Node 24.

RepositórioArquivosSímbolosÍndice frioÍndice quenteConsulta típica
Org Salesforce DX563440,1 s15 ms< 10 ms
App Java + React3561.7130,42 s26 ms3–57 ms
Estresse sintético5.00050.0001,5 s0,24 s5–22 ms

O índice é mantido em memória e invalidado pelo mtime do arquivo de índice. Sem esse cache, cada chamada de ferramenta releria e reanalisaria o índice inteiro — cerca de 20 ms de peso morto por chamada no repositório de 5.000 arquivos, e crescia com o repositório.

find_references é a ferramenta mais lenta em escala porque é uma varredura textual, não uma busca de índice — mas um pré-filtro literal agora pula a divisão de linha e o regex por linha para qualquer arquivo cujo código-fonte bruto não contém o nome pesquisado, que em um repositório típico é a maioria deles. Escopo com pathPrefix para reduzir as leituras de arquivo restantes quando você sabe aproximadamente onde procurar.

Os conteúdos de arquivo também são servidos de um LRU em memória com limite de bytes (64 MB, validado por mtime+tamanho por acerto), então a segunda varredura de um repositório — e a sequência skeleton→read_lines→contexto que os agentes realmente executam em um arquivo — custa um stat() em vez de uma leitura.

Memória entre sessões

memory_save grava em <root>/.slimdex/memory.json, que sobrevive ao processo — um fato salvo em um chat pode ser lido no próximo, por um cliente diferente, após uma reinicialização. Chat e editor compartilham um único armazenamento apenas quando ambos apontam para o mesmo SLIMDEX_ROOT.

Nada é capturado automaticamente: o servidor nunca vê sua conversa, então o agente precisa decidir o que vale a pena manter. As instructions incluídas dizem a ele para ler a memória primeiro em uma nova sessão e salvar decisões, restrições e armadilhas conforme as aprende — mas isso é orientação para o modelo, não uma garantia.

Limitações conhecidas

  • A extração de símbolos é baseada em regex e heurística, não um parser ou LSP. Ela pode deixar passar declarações incomuns, e find_references é uma correspondência textual que pode incluir identificadores homônimos, mas não relacionados.
  • A extração de símbolos e esboços agora é executada em uma cópia mascarada de cada linha, com o conteúdo de strings e comentários removido, para que prosa com formato de declaração dentro de um template literal não seja mais indexada como código. Declarações também são sensíveis à profundidade: um const x = () => … ou type X = … conta apenas no nível superior, porque locais dentro do corpo de uma função não são coisas para as quais alguém navega. Métodos de classe ainda são indexados na profundidade de seu aninhamento.
  • Um comentário inline de # em Python contendo uma chave ainda pode confundir a extração de blocos (# também é o sigilo de campo privado do JS, então não pode ser removido cegamente).
  • changed_files atribui um trecho à declaração anterior mais próxima — correto para um corpo de função normal, aproximado para código entre declarações. Trate-o como raio de impacto, não como grafo de chamadas.
  • search_code relata um total exato, mas para em um limite interno de varredura em conjuntos de resultados muito grandes, imprimindo N+ (scan cap reached) em vez de um número errado e confiante.
  • O suporte a linguagens é desigual: JS/TS é o mais bem coberto. A família C e Ruby, antes as mais fracas, ganharam regras dedicadas (funções livres, definições de Foo::bar, macros semelhantes a funções, attr_*); os pontos fracos restantes são formatos avançados de C++ — templates divididos em várias linhas, sobrecarga de operadores.
  • Para precisão de nível LSP, você trocaria o parser por tree-sitter ou um servidor de linguagem. src/parser.ts é a costura: uma interface Parser selecionada por SLIMDEX_PARSER, com o parser regex como a única implementação incluída. Um backend tree-sitter poderia ser encaixado ali sem tocar em nenhuma ferramenta ou no formato do índice. Ele não está construído — gramáticas por linguagem abrem mão da propriedade "instala instantaneamente, roda offline, zero configuração".

Deliberadamente não construído

Ideias avaliadas e rejeitadas, com justificativa — estas são opiniões de design, não resultados medidos:

  • Dicionários de ID de símbolo (S42 → caminho) — MCP não tem camada de expansão no lado do cliente, então o modelo recebe um token opaco que precisa gastar outra chamada para resolver.
  • Gerenciadores de orçamento de tokens / estimadores de custo — estimativas de chars/4 são não confiáveis entre tokenizadores, e a compressão automática com base em uma estimativa ruim pode descartar dados que o modelo precisava.
  • Cache delta / "já enviado, veja a resposta #5" — após a compactação de contexto, o payload anterior se foi, então a referência resolve para nada.
  • Embeddings / busca semântica — grande pegada de dependências; possível futura flag opcional, não um padrão.
  • Um backend parser tree-sitter — este é o que fecharia os ~4% restantes, e foi custeado em vez de apenas mencionado: web-tree-sitter é WASM, então não precisa de compilação nativa, mas as gramáticas (tree-sitter-wasms) têm 51,7 MB descompactadas contra ~4,5 MB para toda a instalação atual. Avaliado e recusado com 95,9% de recall medido, porque "instala em um segundo, roda offline, sem configuração" é a propriedade que este servidor existe para ter. src/parser.ts continua sendo a costura se esse cálculo mudar — um backend pode ser encaixado ali sem tocar em uma ferramenta ou no formato do índice.

Instalação

Publicado no npm como slimdex-mcp, e listado no MCP Registry como io.github.Siddhukaushik/slimdex-mcp. Nada para compilar — aponte seu cliente para:

npx slimdex-mcp

Ou a partir do código-fonte, se quiser fazer alterações:

git clone https://github.com/Siddhukaushik/slimdex-mcp
cd slimdex-mcp
npm install
npm run build      # produces dist/index.js
npm test           # vitest unit suite

Verifique se ele funciona de ponta a ponta contra um repositório:

npm run smoke                                # this repo
node smoke-test.mjs "C:/path/to/some/repo"   # any other

Variáveis de ambiente

VarEfeito
SLIMDEX_ROOTRepositório para indexar (ou passe como o primeiro argumento da CLI; o padrão é o diretório atual)
SLIMDEX_WATCHDefina como 1 para reindexar automaticamente ao salvar arquivos (observador nativo, sem dependências)
SLIMDEX_PARSERBackend do parser; apenas regex existe hoje
SLIMDEX_PRETTYDefina como 1 para restaurar a renderização verbosa e alinhada a humanos: cabeçalhos mais longos e preenchimento de colunas em search_code, find_definition, search_symbols, find_references, repo_map, read_lines, outline_file. O formato conciso é o padrão — esse preenchimento é contexto que o modelo paga em cada turno posterior. SLIMDEX_TERSE=0 faz o mesmo.
SLIMDEX_PROFILElean anuncia 15 ferramentas em vez de 29, reduzindo os esquemas de ferramentas reenviados a cada turno de ~22.300 para ~12.600 caracteres. As outras 14 (get_context, changed_files, find_tests, dep_graph, outline_file, search_symbols, recap, memory_list, memory_search, memory_delete, digest_save, digest_get, snapshot, stats) ainda funcionam e são chamadas por meio de batch — e as instruções do servidor as nomeiam neste perfil, então o modelo é informado sobre o que é somente em lote, em vez de descobrir por conta própria. Padrão full.
SLIMDEX_NO_DEDUPEDefina como 1 para desativar a supressão de respostas repetidas (uma segunda read_lines/get_file_skeleton/outline_file idêntica em um arquivo inalterado responde com um ponteiro para a chamada anterior em vez do corpo; uma terceira chamada idêntica reemite o conteúdo completo).

O cache persistente

Por repositório, o Slimdex grava em <repo>/.slimdex/:

  • index.json — o índice de código (invalidado por mtime por arquivo e descartado completamente quando a versão do formato do índice muda, para que um índice obsoleto criado por um extrator mais antigo nunca seja reutilizado)
  • memory.json — fatos de memória salvos
  • stats.json — contadores de uso por ferramenta

O diretório ignora a si mesmo: um * .gitignore é gravado dentro dele (o truque do node_modules/.cache), para que nunca apareça em git status e você não precise tocar no .gitignore do próprio repositório. Exclua esse arquivo interno se você quiser fazer commit do cache.


Integrando em clientes MCP

MCP é um padrão compartilhado, então o mesmo servidor deve funcionar em qualquer cliente compatível com MCP. A raiz do projeto é passada via SLIMDEX_ROOT (ou como o primeiro argumento da CLI).

Apenas Claude Code e Claude Desktop foram realmente executados. Os outros abaixo são o formato de configuração padrão para cada cliente, escrito a partir do formato documentado deles — não foram testados aqui e podem precisar de ajustes.

Desde a versão 1.0.0, a integração mais simples é npx -y slimdex-mcp — sem clone, sem build, e ela permanece atualizada. Os exemplos abaixo mantêm o formato node <ABS_PATH> para quem executa a partir do código-fonte; para usar o pacote publicado, troque "command": "node", "args": ["<ABS_PATH>"] por "command": "npx", "args": ["-y", "slimdex-mcp"].

Substitua <ABS_PATH> pela sua saída de build, por exemplo, C:\path\to\slimdex-mcp\dist\index.js, e <REPO> pelo repositório a indexar.

Nenhum ajuste necessário. As economias que importam estão ativadas por padrão em todos os clientes: fatos de memória listados como prévias, respostas concisas, uma releitura idêntica de um arquivo inalterado responde com um ponteiro em vez do corpo, e várias edições de símbolos vão em uma única chamada. As variáveis de ambiente abaixo são para optar fora, ou para lean — que troca ~8.700 caracteres adicionais por turno por rotear um terço das ferramentas por meio de batch, então deliberadamente não é o padrão.

Claude Code (CLI) — testado

claude mcp add slimdex --env SLIMDEX_ROOT=<REPO> -- npx -y slimdex-mcp

A partir do código-fonte: -- node <ABS_PATH>.

Claude Desktop — testado

%APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "slimdex": {
      "command": "npx",
      "args": ["-y", "slimdex-mcp"],
      "env": { "SLIMDEX_ROOT": "<REPO>" }
    }
  }
}

Codex CLI — testado

~/.codex/config.toml

[mcp_servers.slimdex]
command = 'C:\Program Files\nodejs\node.exe'
args = ['<ABS_PATH>']
startup_timeout_sec = 30

Registrado globalmente assim, o slimdex se anexa a cada tarefa do Codex e usa o diretório de trabalho dessa tarefa como raiz do repositório — sem SLIMDEX_ROOT necessário. O Codex inicia o servidor com um ambiente restrito, então dê a command um caminho absoluto para o node em vez de depender de PATH.

Cursor — não testado

.cursor/mcp.json (projeto) ou ~/.cursor/mcp.json (global)

{
  "mcpServers": {
    "slimdex": {
      "command": "node",
      "args": ["<ABS_PATH>"],
      "env": { "SLIMDEX_ROOT": "${workspaceFolder}" }
    }
  }
}

Windsurf — testado

~/.codeium/windsurf/mcp_config.json — mesmo formato mcpServers que o Cursor.

VS Code (Copilot / MCP) — testado

.vscode/mcp.json

{
  "servers": {
    "slimdex": {
      "command": "node",
      "args": ["<ABS_PATH>"],
      "env": { "SLIMDEX_ROOT": "${workspaceFolder}" }
    }
  }
}

Cline (extensão do VS Code) — testado

Configurações do Cline → Servidores MCP → adicionar:

{
  "slimdex": {
    "command": "node",
    "args": ["<ABS_PATH>"],
    "env": { "SLIMDEX_ROOT": "<REPO>" }
  }
}

Zed — testado

settings.json → context_servers

{
  "context_servers": {
    "slimdex": {
      "command": { "path": "node", "args": ["<ABS_PATH>"], "env": { "SLIMDEX_ROOT": "<REPO>" } }
    }
  }
}

Para clientes que expõem a pasta do workspace (Cursor, VS Code), ${workspaceFolder} mantém o Slimdex apontado para o repositório que você tem aberto.

Fluxo de trabalho típico do agente

  1. index_repo uma vez no início (mais rápido em execuções subsequentes), depois brief para retomar de onde as sessões passadas pararam, com notas desatualizadas já sinalizadas.
  2. repo_map → tenha uma visão geral do terreno.
  3. outline_file em um arquivo de interesse → escolha intervalos de linhas.
  4. read_lines apenas para esses intervalos.
  5. find_definition / find_references / dep_graph para navegar.
  6. find_tests antes de editar um símbolo; replace_symbol para reescrever um sem reenviar o corpo antigo.
  7. memory_save decisões e armadilhas para que a próxima sessão comece informada.

Licença

MIT © 2026 Kael VK Inc. (Número de Registro 751569161 RC0001) — veja LICENSE.

Fornecido como está, sem garantia e sem suporte. Se não compilar, não executar ou não funcionar na sua configuração, o problema é seu — veja o aviso de isenção na licença.