Communitygithub.com

exmergo/dex

Dex é o kit de ferramentas de engenharia analítica nativo para agentes de IA. Aponte para seu data warehouse e seu projeto dbt. Ele aprende o cenário, escreve suas transformações e informa exatamente o que corrigir quando o esquema deriva. Construído para engenheiros analíticos e de dados que desejam extrair mais de seu agente de codificação.

O que é dex?

Dex é um kit de ferramentas de engenharia analítica projetado para ser usado diretamente por agentes de IA (como Claude Code, Cursor e Codex). Ele permite que o agente entenda a estrutura e os dados de um data warehouse ou banco de dados local (como DuckDB), execute análises de perfil, inferência de relacionamentos, agrupamento semântico e consultas SQL arbitrárias com segurança. Suporta plataformas como BigQuery, Snowflake, Databricks, Postgres e Redshift, gerenciando credenciais automaticamente e realizando uma verificação de custo em duas etapas antes de executar varreduras em conectores com custo medido. O Dex é essencialmente um copiloto especializado que capacita o agente a agir como um engenheiro analítico experiente: ele prioriza tabelas e colunas relevantes, trata dados de forma responsável (evitando expor valores de colunas marcadas como PII), e oferece uma maneira estruturada e segura para o agente explorar, documentar e preparar dados para transformações. O resultado é uma interação mais eficiente e confiável com a infraestrutura de dados, onde o agente, em vez de cometer erros ou precisar de instruções detalhadas, pode tomar decisões informadas e executar tarefas complexas de engenharia analítica de forma autônoma, mas supervisionada.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add exmergo/dex

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Explorar (Explore)

Compreenda um data warehouse ou um banco de dados DuckDB local da mesma forma que um engenheiro analítico faz: classifique o que é importante, selecione seletivamente e persista um mapa inicial. Esta é a habilidade principal e totalmente somente leitura. Ela absorve a criação de perfis e a inferência de relacionamentos como capacidades; elas não são habilidades separadas.

Como usar

Execute o mecanismo através do wrapper. Ele imprime um envelope JSON higienizado e nada mais; leia o envelope e decida o próximo passo.

uv run "${CLAUDE_SKILL_DIR}/scripts/run.py" <subcomando> [flags]

Subcomandos, na ordem usual:

  1. connect test --path <arquivo.duckdb> confirma uma conexão somente leitura e relata as capacidades.
  2. explore inventory --rank retorna um resumo de objetos classificados (contagens e tamanhos, nunca linhas).
  3. explore profile <objetos> (separados por espaço ou vírgula) retorna perfis de coluna, flags de PII registradas como (coluna, categoria, confiança) e nunca valores de exemplo, além de chaves candidatas, o grão provável e avisos de qualidade de dados (por exemplo, um id não único que se multiplicará em junções). A confiança de uma flag genérica *_name é refinada por evidências de forma de valor da mesma varredura, em ambos os sentidos: valores com forma de pessoa a corroboram, um vocabulário de referência fechado ou rótulos longos a reduzem abaixo do limite de bloqueio do firewall, e a falta de evidências não altera nada (a flag em si nunca é removida). Contagens distintas são aproximadas por questões de escala, mas qualquer coluna que pareça única dentro do ruído de aproximação é escalada para um COUNT(DISTINCT) exato (distinct_count_exact: true), para que as conclusões sobre exclusividade e grão se baseiem em prova; um prefixo ~ em um aviso marca uma contagem que ainda é aproximada. Um objeto solicitado cujo perfil em cache ainda está fresco (mesmo conector, esquema inalterado, dentro de profile_freshness_hours, padrão 24) é servido a partir do cache (cache_hit_count) em vez de ser reexaminado, portanto, criar o perfil de uma tabela que map acabou de escrever não custa nada; passe --refresh para forçar uma reexaminação quando a origem mudou de uma forma que a verificação de metadados gratuita não pode ver.
  4. explore relationships retorna junções inferidas e declaradas com confianças, além de notas explicando o que a inferência examinou (portanto, uma lista vazia é significativa). Adicione --verify para medir cada junção inferida com uma sonda de sobreposição agregada (fração órfã, confiança ajustada).
  5. explore map escreve ou atualiza o cache .dex/ e imprime um resumo (--verify também funciona aqui). Acima de 50 objetos, ele cria perfil apenas dos 25 principais por classificação e informa isso em notes (com skipped_count); passe --full para criar perfil de tudo. Em um novo mapeamento, os objetos ignorados nesta execução mantêm seus perfis anteriores (carried_forward_count), cada um carimbado com seu próprio profiled_at para que a desatualização seja visível em vez dos detalhes da coluna desaparecerem silenciosamente. Um objeto selecionado cujo perfil em cache ainda está fresco (mesmo conector, esquema inalterado, perfilado dentro de profile_freshness_hours, padrão 24) é reutilizado sem uma reexaminação (cache_hit_count), portanto, reexecuções não custam nada; passe --refresh para forçar uma reexaminação completa quando a origem mudou de uma forma que a verificação de metadados gratuita não pode ver (por exemplo, linhas mudaram, mas o esquema não). explore relationships e o explore profile independente reutilizam perfis frescos da mesma forma.
  6. explore diagram [--full] renderiza o mapa em cache como um diagrama ER Mermaid em data.mermaid. Gratuito e sem conexão (ele lê o cache, nunca o warehouse), portanto, é seguro reexecutar enquanto molda a imagem. Reproduza a string literalmente em um bloco ```mermaid cercado para que o humano possa vê-la, e escreva-a em um arquivo .mmd ou markdown quando ele quiser um em disco: o mecanismo deliberadamente não escreve nenhum arquivo. Nunca redesenhe ou "arrume" o diagrama manualmente. Os glifos são alegações que o mecanismo derivou de evidências, e uma cardinalidade de aparência plausível que você forneceu é exatamente a alegação excessiva que este comando existe para evitar: junções declaradas são sólidas, inferidas são pontilhadas, e uma inferência não verificada nunca diz "exatamente um". Leia notes antes de apresentá-lo, pois indica qualquer objeto ou coluna que foi omitido; --full amplia do padrão (objetos perfilados e unidos e seu grão, chave, junção e colunas PII) para tudo que é elegível.
  7. explore query "<SELECT ...>" ["<SELECT ...>" ...] responde a perguntas ad-hoc que os comandos fixos não cobrem: você escreve o SQL, o firewall de consulta do mecanismo recusa ou limita. Passe uma instrução por argumento, ou --sql-file <caminho> para uma lista mais longa, e faça uma cadeia inteira de perguntas em uma chamada em vez de uma chamada cada; cada instrução é julgada e respondida por conta própria, portanto, uma recusa em uma não custa as outras, e data.results carrega uma entrada por instrução. Uma tabela que você não perfilou, incluindo um modelo que você acabou de construir, é perfilada para você e a instrução então é executada, portanto, sondar algo novo é uma chamada em vez de três; o envelope informa o que perfilou, e em um conector medido, esse perfil é precificado na mesma confirmação que as instruções. Os resultados vêm no formato linha principal e são limitados; uma recusa nomeia a coluna ofensiva e a correção, portanto, uma reescrita é suficiente. Leia ${CLAUDE_SKILL_DIR}/references/probe-playbook.md antes de escrever uma sonda: ele mapeia perguntas comuns para formas de sonda eficazes.
  8. explore cluster <objeto> [--features a,b,c] [-k N] executa k-means em uma amostra limitada das colunas numéricas do objeto e retorna a estrutura do segmento: tamanhos e frações por cluster, centroides (cada coordenada é a média do cluster para esse recurso, um agregado), a pontuação de silhueta e, quando -k é omitido, o k que escolheu mais a varredura de silhueta da qual escolheu. Requer o cache .dex/ (execute map/profile primeiro) para que os recursos possam ser selecionados automaticamente a partir de colunas numéricas, não PII e não chave perfiladas; passe --features para escolhê-los você mesmo (nomear uma coluna PII ou uma chave a ativa deliberadamente, e apenas sua média é relatada). Uma chave nunca é um recurso: sua média não tem significado, e uma tabela fato é principalmente chaves mais um punhado de medidas, portanto, agrupá-las apenas particiona intervalos substitutos. Chaves são as colunas únicas, as colunas que se juntam (a partir das junções que map inferiu) e as colunas com nome de chave; prefira map a um profile simples aqui, porque sem junções inferidas uma chave estrangeira é capturada apenas se seu nome a denunciar. As notas nomeiam cada coluna excluída, portanto, verifique-as antes de confiar em um resultado. Duas coisas que a silhueta sozinha não lhe dirá, ambas as quais as notas dirão. Um cluster com menos de 1% da amostra é um bolsão de outlier, não um segmento, e ele aumenta a pontuação precisamente porque está tão distante: relate isso como detecção de outlier, ou execute novamente com -k para dividir o volume. E em conectores que não podem semear uma amostra, a extração muda a cada execução, portanto, duas execuções podem discordar sobre k; o envelope sample_repeatable informa em qual caso você está, e comparar execuções em diferentes extrações não tem sentido. Apenas agregados cruzam o limite: as linhas da amostra são agrupadas em processo e nunca entram no contexto. Em um conector medido, ele leva o mesmo handshake de custo que os comandos de varredura abaixo (apenas as colunas de recurso são varridas, e uma cláusula de amostra ciente do dialeto lê uma fração), portanto, apresente a estimativa e obtenha um orçamento primeiro. Precisa do extra [cluster] (scikit-learn); o wrapper o instala automaticamente para este subcomando.
  9. explore semantic list e explore semantic query acessam a camada semântica do dbt (métricas, dimensões, entidades). list é descoberta: quais métricas existem e por quais dimensões cada uma pode ser agrupada. query recebe uma métrica posicional após o modo explícito (com --metric mantido para compatibilidade) e um --group-by <entidade__dimensão> (mais --where, --grain e --limit opcionais) e retorna os valores de uma métrica como um resultado em colunas e limitado. Flags de nome recebem uma lista separada por vírgula ou uma flag repetida (--group-by a,b é --group-by a --group-by b); --where nunca é dividido. Dois backends respondem a estes, escolhidos por .dex/config.yml semantic.backend e substituíveis com --local / --api. --local renderiza o SQL com MetricFlow e o executa através do próprio conector do dex e handshake de custo, portanto, o custo é apresentado antes do gasto (precisa de um projeto dbt e, para query, do extra [semantic]; list é uma visualização de leitura do manifesto que não precisa de nenhum deles). --api envia a consulta para uma implantação hospedada do dbt Cloud (precisa apenas de um host, um id de ambiente e um DBT_SL_TOKEN, mais o extra [semantic-api], nenhum projeto local). O backend hospedado é o único lugar onde a proteção de custo não pode ser aplicada: o dbt Cloud executa no lado do servidor, portanto, o resultado carrega um aviso explícito de que o gasto é governado lá, não pelo dex, e nenhum --confirm é solicitado. De qualquer forma, uma dimensão agrupada ou filtrada com forma de PII (por exemplo, user__email) é recusada antes da consulta ser executada. Isso consulta a camada; criá-la é trabalho do transform.

Regras de engajamento para query: prefira os comandos fixos quando eles respondem à pergunta; uma sonda responde a uma pergunta; agrupe medidas relacionadas em uma única consulta em vez de emitir muitas; agregados sobre colunas sinalizadas como PII devem ser medidos (COUNT, APPROX_COUNT_DISTINCT, AVG(LENGTH(...))), nunca portadores de valor (MIN, ANY_VALUE, STRING_AGG). A cláusula FROM pode desaninhar colunas JSON e array no idioma nativo do conector, que é a maneira correta de explorar dados sem esquema (por exemplo, "quais chaves aparecem em cada linha desta coluna JSON"): BigQuery t, UNNEST(JSON_KEYS(doc)) AS k, Snowflake t, LATERAL FLATTEN(input => doc) f, Databricks t LATERAL VIEW EXPLODE(json_object_keys(doc)) x AS k, Postgres t, jsonb_object_keys(doc) AS k, Redshift t, UNPIVOT t.doc AS v AT k, DuckDB t, UNNEST(json_keys(doc)) AS u(k). O valor desaninhado deve vir de uma coluna de uma tabela na consulta (simples ou através de uma função JSON/array); desaninhar uma subconsulta, outra tabela, um literal ou um gerador é recusado, e as saídas do desaninhamento herdam as flags PII da coluna de origem. Uma coluna cuja flag foi reduzida abaixo do limite de bloqueio de 0.5 projeta normalmente, com um aviso no envelope nomeando-a; trate o aviso como informação para o usuário, não um erro a ser corrigido. Se o usuário disser que uma coluna recusada não é dados pessoais, recomende uma entrada pii_overrides em .dex/config.yml (coluna totalmente qualificada, motivo opcional): ela desbloqueia a consulta imediatamente, sobrevive a novos perfis e é revisável no git. Nunca edite manualmente .dex/cache.json para limpar uma flag. Nunca recorra a Python puro ou um CLI de banco de dados para executar SQL; o caminho do firewall é o único sancionado.

Destinos de nuvem e banco de dados (BigQuery, Snowflake, Databricks, Postgres, Redshift)

Um warehouse ou banco de dados remoto substitui --path pela configuração do conector. Comece com connect test --connector <nome> (ou defina connector: mais o bloco correspondente em .dex/config.yml: bigquery: com project e uma lista de permissões de datasets, snowflake: com o warehouse fixado e uma lista de permissões de databases, databricks: com o SQL warehouse fixado e uma lista de permissões de catalogs, postgres: com uma lista de permissões de schemas, redshift: com o workgroup Serverless e uma lista de permissões de schemas). As credenciais são descobertas, nunca solicitadas: se o envelope relatar credenciais ausentes ou expiradas, repasse a correção que ele nomeia (para BigQuery gcloud auth application-default login; para Snowflake uma entrada connections.toml ou variáveis de ambiente SNOWFLAKE_*; para Databricks databricks auth login ou variáveis de ambiente DATABRICKS_*; para Postgres DATABASE_URL, variáveis de ambiente PG*, ou uma entrada pg_service.conf; para Redshift a cadeia de credenciais AWS (aws configure, variáveis de ambiente AWS_*) ou variáveis de ambiente REDSHIFT_*) e nunca peça ao usuário para colar uma chave, token ou senha.

Em um conector medido, os comandos de varredura (profile, map, relationships, query) executam um handshake de duas etapas. A primeira chamada retorna needs_confirmation com uma estimativa em cost.estimate (e um detalhamento por tabela quando relevante): um valor exato de dry-run em bytes no BigQuery, um valor heurístico rotulado como estimate_quality: "heuristic" em segundos de warehouse no Snowflake (créditos junto), um piso rotulado como estimate_quality: "low" em segundos de warehouse no Databricks (DBUs junto; ele se ajusta dentro do orçamento confirmado), um valor heurístico em segundos de computação no Redshift (horas RPU junto; as estimativas Serverless carregam o mínimo de 60 segundos de ativação uma vez), e segundos de banco de dados no Postgres (sem dólares; a quantidade protegida é a carga no banco de dados operacional). Apresente a estimativa ao usuário em unidades humanas, obtenha um orçamento explícito deles e reexecute o mesmo comando com --confirm e --budget <magnitude> na unidade do paradigma. Nunca invente um orçamento com o qual o usuário não concordou e nunca tente novamente com um orçamento maior em uma recusa acima do teto sem perguntar. Metadados são gratuitos (connect test, inventory são executados imediatamente), e envelopes OK relatam o gasto real em data.spend.

No BigQuery, uma estimativa de perfil mantém um piso de 10 MB por tabela para cada consulta de escalação que um perfil ainda pode emitir após sua varredura agregada, portanto, em um warehouse de muitas tabelas pequenas, a maior parte do número pode ser reserva para trabalho que nunca acontece. Tanto o handshake quanto a recusa acima do teto relatam essa divisão (reserved_bytes e reserved_queries, e na prosa). Repasse-a quando você apresentar a estimativa: se um número é varredura ou reserva muda se aumentar o orçamento está comprando trabalho ou margem.

Quando uma estimativa é maior do que o trabalho merece, restrinja o escopo em vez de aumentar o orçamento. --scope (repetível) limita um comando a parte da lista de permissões de origem configurada, no próprio vocabulário do conector: um dataset no BigQuery, um schema ou database.schema no Snowflake, um catalog.schema no Databricks, um schema no Postgres ou Redshift. É gratuito de resolver, pode apenas reduzir

Habilidades Relacionadas