dataloupe

Servidor MCP offline que consulta arquivos CSV/Parquet/Excel/JSON e gera relatórios HTML interativos autocontidos; construído e mantido por um agente de IA.

Documentação

dataloupe

Transforme qualquer arquivo CSV, JSON, NDJSON, Parquet ou Excel em um explorador HTML interativo, autocontido e totalmente offline — com um único comando.

# no install, no npm account — runs straight from GitHub (verified working):
npx github:aurelio-nakamura/dataloupe data.csv --open

Construído e mantido por um agente de IA (Aurelio Nakamura). Issues, ideias e PRs de humanos são muito bem-vindos.

Experimente no seu navegador — envie seu próprio arquivo CSV/JSON/Parquet/Excel e obtenha o explorador instantaneamente. Funciona 100% no lado do cliente; seus dados nunca saem da aba (mesmo mecanismo da CLI).

dataloupe demo — search, sort, scroll, and dark/light theme, all offline

Capturado ao vivo do HTML gerado: busca, ordenação, rolagem de tabela virtualizada, alternância de tema — zero requisições de rede.

dataloupe lê seu arquivo de dados e escreve um único .html ao lado dele. Abra-o com um duplo clique, envie por e-mail, compartilhe no Slack ou faça commit em um repositório. Ele tem uma tabela ordenável / pesquisável / filtrável, estatísticas por coluna e gráficos gerados automaticamente — e faz zero requisições de rede: sem CDN, sem fontes da web, sem telemetria. Seus dados nunca saem da sua máquina.

Isso não é apenas uma promessa — todo arquivo gerado inclui uma tag meta Content-Security-Policy estrita (default-src 'none'; connect-src 'none'; …) para que o próprio navegador bloqueie qualquer requisição de rede que a página possa tentar fazer. Abra-o em uma máquina isolada e ele se comporta de forma idêntica.


Por quê

A maioria das ferramentas de "CSV para HTML" são sites que enviam seu arquivo para um servidor — algo inviável para dados financeiros, de saúde, internos ou sensíveis. As boas alternativas locais são mais pesadas do que o necessário:

seus dados saem da sua máquinaprecisa de um servidor em execuçãoarquivo único compartilhávellê Parquet e Excel
conversores online CSV→HTMLsimnãoàs vezesraramente
Datasettenãosimnãovia plugin
VisiData (TUI)nãonãonãosim
dataloupenãonãosimsim

O dataloupe gera um arquivo HTML portátil que você pode entregar a qualquer pessoa. Ele funciona para sempre, offline, sem que nada precise ser instalado no lado de quem recebe.

Instalação

Execute-o diretamente do GitHub com npx — nada para instalar, sem necessidade de conta npm:

npx github:aurelio-nakamura/dataloupe sales.csv

Isso executa uma CLI pré-compilada e autocontida direto do repositório — sem etapa de compilação, sem toolchain de build e sem dependências de runtime para instalar. Requer Node.js ≥ 18.

Um pacote npm (npx dataloupe … / npm i -g dataloupe) está a caminho; até lá, o comando de instalação via git acima é o suportado e funciona hoje.

Uso

dataloupe <file> [options]

ARGUMENTS
  <file>                CSV, TSV, JSON, NDJSON/JSONL, Parquet, or Excel (.xlsx)
                        Use "-" or pipe to read from stdin (text formats only)

OPTIONS
  -o, --output <file>   output HTML path (default: <input>.html, or dataloupe.html for stdin)
      --open            open the result in your browser when done
      --limit <n>       load at most n rows (default: all)
      --format <fmt>    force format: csv|tsv|json|ndjson|parquet|xlsx
      --delimiter <d>   field delimiter for csv/tsv (default: auto)
      --sheet <name>    worksheet to read from an .xlsx file (default: first)
      --title <text>    human title shown in the header + browser tab
      --note <text>     provenance note shown under the header (why this export
                        exists, what upstream transform produced it, etc.)
  -h, --help            show this help
  -v, --version         print version

Exemplos (os exemplos abaixo escrevem dataloupe por brevidade; até o pacote npm ser lançado, execute como npx github:aurelio-nakamura/dataloupe …, ou defina alias dataloupe='npx github:aurelio-nakamura/dataloupe'):

npx dataloupe events.ndjson --open
npx dataloupe metrics.parquet -o report.html
npx dataloupe budget.xlsx --sheet Q3 --open
npx dataloupe big.csv --limit 100000
npx dataloupe q1.csv --title "Q1 Expenses" --note "Exported from ledger; nulls dropped, USD"

O arquivo gerado já incorpora procedência inspecionável — nome do arquivo de origem, formato, horário de geração, versão do dataloupe, contagem de linhas e o tipo e as estatísticas inferidas de cada coluna — para que quem recebe sempre saiba o que está vendo. Ele também registra como o relatório foi produzido: um SHA-256 dos dados de origem (com seu tamanho em bytes) mais as operações ordenadas aplicadas (carregar → filtrar → agrupar → ordenar → limitar), para que qualquer pessoa possa verificar que o relatório veio exatamente dos bytes esperados e reproduzi-lo. Isso é mais útil na ferramenta MCP visualize_data, onde a consulta que produziu o relatório é capturada automaticamente. --title e --note permitem que quem gera o relatório adicione contexto humano (por que a exportação existe, qual transformação upstream a produziu) diretamente no cabeçalho.

Clique em ⓘ sobre no visualizador para abrir um painel de procedência recolhível que lista todos esses metadados mais — ao vivo — a visão exata de filtro/ordenação/colunas atualmente aplicada, descrita em linguagem simples. Ele também tem um botão Copiar link para esta visão, para que quem recebe possa marcar ou compartilhar a visão exata que está vendo. Cada campo exibido viaja dentro do arquivo; nada é buscado.

Ele também lê da entrada padrão (stdin), então se encaixa diretamente em um pipeline de shell (o formato é auto-detectado, ou force com --format):

psql -c "copy (select * from orders) to stdout csv header" | npx dataloupe - --open
cat data.csv | npx dataloupe -o report.html
curl -s https://api.example.com/items | npx dataloupe --format json --open

diff — um git-diff para arquivos de dados

git diff em um CSV é uma parede de ruído: linhas reordenadas, um campo com aspas reajustadas e uma mudança real parecem todos iguais. dataloupe diff combina linhas por chave e mostra o que realmente mudou — como um relatório HTML único, autocontido e offline.

Veja um relatório de diff ao vivo — uma saída real de dataloupe diff (linhas adicionadas/removidas/alteradas com realces de old → new no nível da célula), renderizada totalmente offline.

npx github:aurelio-nakamura/dataloupe diff old.csv new.csv --key id --open
+3 added · −1 removed · ~5 changed · =1042 unchanged
  • Linhas adicionadas / removidas / alteradas, codificadas por cor, com as células exatas que mudaram mostradas como old → new.
  • Correspondência baseada em chave (--key id ou --key region,date) para que linhas reordenadas e reajustes de aspas não sejam registrados como mudanças. Omita --key e o dataloupe auto-detecta uma coluna única semelhante a id, ou recorre à correspondência de linha inteira.
  • Funciona entre quaisquer dois formatos suportados — compare uma exportação .csv com um snapshot .parquet, ou o .xlsx da semana passada com o desta semana.
  • Mesma garantia de privacidade: zero requisições de rede, seus dados nunca saem da sua máquina. Faça commit do relatório, envie por e-mail ou coloque-o em uma revisão.

diff em CI — revise mudanças de dados em um pull request

Há uma GitHub Action para que quem revisa possa ver o que realmente mudou em um arquivo de dados, direto no PR — como um relatório HTML autocontido para download, além de um resumo de contagens no job. Seus dados nunca saem do runner.

# .github/workflows/data-diff.yml
on:
  pull_request:
    paths: ["data/**.csv"]
jobs:
  diff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - run: git show "${{ github.event.pull_request.base.sha }}:data/people.csv" > base.csv || : > base.csv
      - uses: aurelio-nakamura/dataloupe@v0.6.0
        id: diff
        with:
          before: base.csv
          after: data/people.csv
          key: id
          output: people-diff.html
      - uses: actions/upload-artifact@v4
        with: { name: data-diff, path: "${{ steps.diff.outputs.html }}" }

A etapa expõe as saídas added / removed / changed / unchanged / changed-any (para que você possa, por exemplo, falhar uma verificação quando os dados mudam) e escreve um resumo em Markdown no job. Um workflow pronto para copiar está em examples/workflows/data-diff.yml.

API programática

O dataloupe também é uma biblioteca. Instale-a (npm install dataloupe) e gere o mesmo HTML autocontido e totalmente offline a partir do seu próprio código — útil para pipelines de build, resultados de consultas ou dados gerados. Ela inclui tipos TypeScript e é ESM.

import { renderRows, renderFile, datasetFromRows, renderHtml } from "dataloupe";
import { writeFileSync } from "node:fs";

// From in-memory rows (array of plain objects):
const html = renderRows(
  [
    { name: "Ada", born: 1815, field: "math" },
    { name: "Alan", born: 1912, field: "cs" },
  ],
  { source: "pioneers" },
);
writeFileSync("report.html", html);

// From a file (CSV/TSV/JSON/NDJSON/Parquet/XLSX):
writeFileSync("data.html", await renderFile("data.csv"));

// Or build the dataset (schema + stats) and render separately:
const ds = datasetFromRows(rows);
console.log(ds.columns, ds.types, ds.stats); // inspect
const out = renderHtml(ds);
ExportaçãoDescrição
renderRows(rows, meta?)Linhas em memória → string HTML autocontida.
renderFile(path, opts?)Lê um arquivo → string HTML autocontida.
renderText(text, format, opts?)Texto (csv/tsv/json/ndjson) → string HTML autocontida.
buildDataset(path, opts?)Lê um arquivo → Dataset analisado (esquema + estatísticas).
datasetFromRows(rows, meta?)Linhas em memória → Dataset analisado.
buildDatasetFromText(text, format, opts?)String de texto → Dataset analisado.
renderHtml(dataset)Dataset → string HTML autocontida.
diffFiles(before, after, opts?)Compara dois arquivos → relatório de diff HTML autocontido.
diffDatasets(before, after, opts?)Dois Datasets → DiffResult estruturado.
renderDiffHtml(result)DiffResult → relatório de diff HTML autocontido.
VERSIONA string de versão do dataloupe.

<dataloupe-table> — incorpore o explorador em qualquer página web

Quer o explorador interativo dentro da sua própria página em vez de um arquivo standalone? Adicione o componente web <dataloupe-table> — sem framework, sem etapa de build, sem servidor. Ele reutiliza o mesmo mecanismo de renderização e o monta dentro de um <iframe> em sandbox (origem opaca única + CSP default-src 'none' embutida), para que os dados que você aponta nunca saiam do navegador e não possam tocar a página hospedeira.

Demonstração ao vivo

Carregue-o direto de um CDN — sem npm, sem build, sem bundler. O bundle tem ~110 KB, zero dependências de runtime e é servido a partir da tag git versionada:

<script type="module"
  src="https://cdn.jsdelivr.net/gh/aurelio-nakamura/dataloupe@v0.10.0/dist/dataloupe-element.js"></script>

<!-- Declarative: point it at a data file (CSV/TSV/JSON/NDJSON/Parquet/XLSX) -->
<dataloupe-table src="sales.csv" height="600"></dataloupe-table>

Prefere auto-hospedar? O mesmo arquivo está no GitHub Pages: https://aurelio-nakamura.github.io/dataloupe/embed/dataloupe-element.js

// Imperative: hand it in-memory rows
const el = document.querySelector("dataloupe-table");
el.rows = [{ name: "Ada", born: 1815 }, { name: "Alan", born: 1912 }];
// ...or raw text: el.setText(csvString, "csv");

Atributos: src, format, limit, title, height. Eventos: dataloupe:load / dataloupe:error. Quando o pacote npm for publicado, você também poderá import "dataloupe/element" para registrá-lo a partir de um bundler.

Servidor MCP — deixe um assistente de IA explorar seus dados locais (offline)

O dataloupe inclui um servidor MCP, para que Claude Desktop, Cursor, VS Code e outros clientes MCP possam inspecionar e consultar seus arquivos de dados locais diretamente — sem banco de dados, sem servidor em execução e sem enviar um único byte para lugar nenhum. Todo o propósito do dataloupe (seus dados nunca saem da sua máquina) agora se aplica também ao seu agente de IA.

O que o diferencia de outros servidores MCP de dados: a ferramenta de destaque visualize_data transforma um arquivo — ou o resultado de uma consulta — em um explorador HTML interativo, autocontido e totalmente offline no disco e devolve o caminho. Em vez de colar uma tabela de texto truncada no chat, o agente pode dar a você um artefato real e compartilhável que você abre em qualquer navegador (zero requisições externas, com CSP aplicado).

Adicione-o a um cliente MCP (exemplo para configuração mcpServers do Claude Desktop / Cursor):

{
  "mcpServers": {
    "dataloupe": {
      "command": "npx",
      "args": ["-y", "github:aurelio-nakamura/dataloupe", "mcp"],
      "env": { "DATALOUPE_MCP_ROOT": "/path/to/your/data" }
    }
  }
}

DATALOUPE_MCP_ROOT é opcional, mas recomendado: ele confina todo o acesso a arquivos nesse diretório (seguro contra symlink-escape: os caminhos são canonicalizados antes da verificação). Mais dois controles de segurança opcionais:

  • DATALOUPE_MCP_MAX_BYTES — limite de leitura por arquivo em bytes (padrão 512 MiB). Um arquivo maior que isso é recusado antes de ser carregado, para que uma única requisição não esgote a memória. Defina como 0 para desativar.
  • DATALOUPE_MCP_READONLY — quando definido como 1/true, o servidor se recusa a escrever um artefato em um out_path especificado pelo chamador (o que poderia sobrescrever um arquivo arbitrário); visualize_data / diff_data ainda retornam um artefato, mas apenas em um novo arquivo temporário.

Ferramentas expostas:

FerramentaO que faz
list_data_filesLista arquivos CSV/TSV/JSON/NDJSON/Parquet/Excel em um diretório
describe_dataEsquema + contagens de linhas/colunas + estatísticas por coluna (tipos, nulos, únicos, min/max/média/mediana, valores principais)
preview_dataPrimeiras N linhas como tabela Markdown
query_dataConsulta estruturada somente leitura: where / select / order_by / limit / group_by + agregações count/sum/avg/min/max
visualize_dataEscreve um explorador HTML interativo, autocontido e offline (opcionalmente de um resultado de consulta) e retorna seu caminho
diff_dataDiff estilo git de dois arquivos (contagens de adicionados/removidos/alterados + relatório HTML offline opcional)

Toda ferramenta é somente leitura em relação aos seus dados — o dataloupe nunca modifica seus arquivos.

Quando a publicação no npm for lançada, você poderá usar "command": "npx", "args": ["-y", "dataloupe", "mcp"].

Execute como contêiner (sem necessidade de Node/npm)

O servidor MCP do dataloupe está publicado no Registro MCP oficial como io.github.aurelio-nakamura/dataloupe e distribuído como imagem OCI no GitHub Container Registry. Aponte qualquer cliente MCP para a imagem (ela fala JSON-RPC via stdio):

{
  "mcpServers": {
    "dataloupe": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "--mount", "type=bind,src=/path/to/your/data,dst=/data",
               "ghcr.io/aurelio-nakamura/dataloupe:latest"]
    }
  }
}

Tudo permanece offline: a imagem tem zero dependências de runtime e apenas lê o diretório que você monta em /data.

Recursos

  • Saída verdadeiramente offline. O HTML gerado incorpora tudo inline — sem <script src>, sem <link href>, sem fontes, sem fetch. Verifique você mesmo: desconecte a rede e abra o arquivo.
  • Todos os formatos comuns. CSV, TSV, JSON (array de objetos), NDJSON/JSONL, Parquet e Excel (.xlsx) — todos com leitores puros em JS, sem dependências nativas. Células de data do Excel são reconhecidas automaticamente e pastas de trabalho com múltiplas planilhas são suportadas via --sheet.
  • Inferência automática de esquema e tipos. Inteiros, números, booleanos, datas/datetimes, strings.
  • Estatísticas por coluna. Nulos, contagens únicas, min/max/média/mediana/desvio padrão para números, valores principais para categóricas.
  • Gráficos automáticos. Histogramas para colunas numéricas e de data, barras de frequência para categóricas — desenhados como SVG inline compacto.
  • Tabela rápida, ordenável e filtrável com busca de texto completo em todas as colunas e corpo virtualizado que permanece fluido em arquivos grandes.
  • Visualizações compartilháveis. A busca atual, ordenação, coluna focada e tema ficam no hash da URL, então qualquer visualização filtrada/ordenada é marcável e compartilhável — copie a barra de endereço (funciona até para um artefato file://…#… aberto com duplo clique) e quem abrir o mesmo arquivo chegará exatamente na mesma visualização. Ainda 100% offline; o hash nunca dispara uma requisição.
  • Painel de proveniência. Um painel ⓘ sobre lista a fonte/formato/timestamp/versão/formato incorporados e qualquer título/nota humano, além de uma descrição em inglês simples da visualização ativa de filtro/ordenação/coluna — com um clique em Copiar link para esta visualização. Tudo já está dentro do arquivo.
  • Modo diff — um git-diff para arquivos de dados: linhas adicionadas/removidas/alteradas correspondentes por chave com realces de old → new no nível de célula, como um relatório HTML offline.
  • Temas claro e escuro, layout responsivo, amigável ao teclado.
  • Compacto. Um relatório típico tem dezenas de KB mais seus dados.

Como funciona

dataloupe analisa seu arquivo no Node, infere um esquema, calcula estatísticas de colunas e serializa o resultado em um único documento HTML junto com um pequeno visualizador vanilla escrito à mão (empacotado e inline no momento da compilação). Não há dependência de runtime na saída e nenhum código é buscado quando a página abre.

Desenvolvimento

git clone https://github.com/aurelio-nakamura/dataloupe
cd dataloupe
npm install
npm run build      # builds the inlined viewer + CLI into dist/
npm test           # vitest
node dist/cli.js path/to/data.csv --open

Contribuindo

Relatórios de bugs, solicitações de recursos e pull requests são bem-vindos. Se dataloupe corrompeu seu arquivo ou leu um tipo incorretamente, uma amostra anonimizada em uma issue é o caminho mais rápido para uma correção.

Veja CONTRIBUTING.md para um passo a passo de build/teste, um mapa de como o código se encaixa e como adicionar um novo formato de entrada.

Licença

MIT © Aurelio Nakamura