Skip to main content

datatool

Diagnostica, perfila, limpa e converte arquivos de dados pela linha de comando: CSV, Excel, JSON, Parquet e outros. Aponta valores nulos, duplicidades, datas em formatos diferentes, números guardados como texto e CPF/CNPJ inválido, e sugere o comando que corrige cada problema. Entende nativamente CSV exportado pelo Excel em português (;, cp1252), CPF/CNPJ e valores em R$.

pip install datatool-cli
datatool info clientes.csv

O roadmap completo, com o status de cada funcionalidade, está em specs/README.md.

Status

  • Implementado: convert, info, profile (+ --columns/--max-columns), clean (diagnóstico + --trim/--lowercase/--uppercase/--normalize-case/--remove-duplicates/--fill-null/--drop-null/--normalize-dates/--fix-types/--rename-columns/--remove-columns/--normalize-documents), saída em JSON (--format json) em info/profile/clean/convert, --redact-values em info/profile/clean, detecção de delimitador/encoding de CSV (--sep/--encoding), log de execução (no diretório de logs do usuário, configurável), validação de CPF/CNPJ, servidor MCP (datatool-mcp) para agentes de IA
  • Ainda não implementado: relatório HTML de profiling, pipelines YAML, inspeção e limpeza de planilhas Excel, IA opcional, licenciamento Pro — veja specs/README.md para o detalhamento spec a spec

Requisitos

  • Python >= 3.10

Instalação

pip install datatool-cli

O pacote se chama datatool-cli, mas o comando é datatool. datatool --version mostra a versão instalada, e datatool --help lista os comandos.

Para o servidor MCP, usado por agentes de IA (ver a seção própria), que traz dependências a mais:

pip install "datatool-cli[mcp]"

Para instalar a partir do código-fonte, veja Desenvolvimento.

Comandos disponíveis

convert — converter arquivo entre formatos

datatool convert vendas.csv vendas.parquet
datatool convert vendas.xlsx vendas.csv
  • Formatos suportados: CSV, JSON, JSONL, Excel (xlsx), Parquet, SQLite, além de Feather e Avro.
  • SQLite: na leitura, --table escolhe a tabela. Sem ele, é lida a tabela com o nome do arquivo (vendas.db → tabela vendas) ou, se o banco tem uma só, essa; com várias tabelas e nenhuma com esse nome, o comando lista as tabelas e pede --table (exit code 2). O JSON traz table e tables no resumo do arquivo. Na gravação, a tabela tem o nome do arquivo. Com --overwrite num .db que já existe, a tabela é substituída numa única transação: se a gravação falhar, a tabela original fica intacta. As demais tabelas do arquivo não são tocadas. Booleanos, datas e data-hora são gravados com o tipo declarado (BOOLEAN, DATE, TIMESTAMP) e voltam com o mesmo tipo na leitura. Data-hora com fuso volta em UTC, no mesmo instante.
  • Colunas só de inteiros com valores que não cabem em 64 bits, como a chave de acesso da NF-e (44 dígitos) ou o código de barras de um boleto, são lidas como texto: são identificadores, e como texto não perdem nenhum dígito.
  • Os tipos das colunas são inferidos com o arquivo inteiro, não só com as primeiras linhas: um valor como N/D numa coluna numérica, em qualquer posição, faz a coluna ser lida como texto, sem perder nenhum valor, em vez de impedir a leitura ou virar nulo. O info aponta a coluna.
  • O formato de entrada e saída é inferido pela extensão do arquivo. Use --from-type/--to-type para sobrescrever quando a extensão não é reconhecida ou é ambígua.
  • Com to_filename, uma linha de confirmação vai para o stderr: Gravado vendas.parquet (parquet): 1.500 linhas, 8 colunas.
  • Se to_filename for omitido, o dataset inteiro é impresso no stdout em CSV, pronto para pipe (datatool convert vendas.xlsx | head).
  • Se o destino já existir, o comando recusa (exit code 2) e não altera nada; use --overwrite para substituí-lo.
  • --show-stats imprime (linhas, colunas) da origem e do destino; sem to_filename, vai para o stderr, para não se misturar ao CSV.
  • --format json imprime um documento com source e target (exige to_filename; não combina com --show-stats).
datatool convert vendas.csv vendas.parquet --show-stats

Arquivos inexistentes, formatos não suportados ou diretórios sem permissão de escrita retornam uma mensagem clara e exit code diferente de zero.

info — diagnóstico automático de um arquivo

datatool info clientes.csv

Mostra linhas, colunas e tamanho do arquivo, além de detectar automaticamente:

  • valores nulos por coluna
  • linhas duplicadas
  • colunas com múltiplos formatos de data
  • colunas numéricas armazenadas como texto
  • colunas quase numéricas com alguns valores que não são números (N/D, a combinar), sem sugestão: o --fix-types não as converte, para não apagar esses valores. Se eles querem dizer "sem dado", clean --null-values "N/D" --fix-types os troca por nulo e converte a coluna

Para cada problema que tem correção, sugere o comando datatool clean correspondente. Todas as sugestões (--fix-types, --remove-duplicates, --normalize-dates, --drop-null) já estão implementadas. Funciona para CSV, JSON, Excel e Parquet.

Arquivo: clientes.csv
Linhas: 10
Colunas: 6
Tamanho: 711 bytes

Problemas encontrados:
  ⚠ 3 valores nulos em "email"
  ⚠ 1 linhas duplicadas
  ⚠ "data_nascimento" contém 4 formatos de data diferentes
  ⚠ 10 CPFs com dígito verificador inválido
  ⚠ "idade" parece numérica, mas 1 valores não são números

Sugestões:
  1. Remover duplicidades → datatool clean clientes.csv --remove-duplicates
  2. Normalizar datas → datatool clean clientes.csv --normalize-dates
  3. Tratar valores nulos → datatool clean clientes.csv --drop-null

Um arquivo de exemplo que dispara todos esses problemas está em examples/clientes.csv.

profile — profiling estatístico de um dataset

datatool profile vendas.csv
datatool profile vendas.csv --key cpf

Para cada coluna, mostra contagem e percentual de nulos, e:

  • colunas numéricas: min, max, média, mediana, desvio padrão, percentis (25/50/75) e outliers (método IQR)
  • colunas categóricas/texto: cardinalidade e top 5 valores mais frequentes (com percentual)

Também reporta a quantidade de linhas totalmente duplicadas e, com --key coluna1,coluna2, a quantidade de duplicidades considerando apenas essas colunas como chave.

Arquivo: clientes.csv
Linhas: 10
Colunas: 6
Linhas duplicadas: 1
Linhas duplicadas (chave: cpf): 1

Coluna "cpf" (numérica)
  Nulos: 0 (0.00%)
  Min: 11122233344.00  Max: 99900011122.00  Média: 52222222221.70  Mediana: 50011122232.50  Desvio padrão: 30544672345.70
  Percentis: p25=25011122232.75  p50=50011122232.50  p75=75011122149.75
  Outliers (IQR): 0

Coluna "cidade" (categórica)
  Nulos: 0 (0.00%)
  Cardinalidade: 9
  Top 5 valores:
    Rio de Janeiro: 2 (20.00%)
    São Paulo: 1 (10.00%)
    ...

Em datasets largos, --columns e --max-columns restringem o tamanho da saída:

datatool profile vendas.csv --columns preco,quantidade
datatool profile vendas.csv --max-columns 50
  • --columns col1,col2 perfila só essas colunas (a contagem de linhas duplicadas continua do dataset inteiro); coluna inexistente é erro claro, igual a --key
  • --max-columns N perfila só as N primeiras colunas na ordem do dataset (mesmo que --columns peça outra ordem); o que ficou de fora aparece no fim do texto, ou em columns_returned/columns_total/truncated_columns no JSON
  • Sem --max-columns, nada muda — a flag é só um limite opcional

clean — detectar e corrigir problemas de qualidade

datatool clean clientes.csv

Sem nenhuma flag, é somente leitura/diagnóstico — não grava nenhum arquivo. Detecta, por coluna:

  • valores inválidos (ex.: e-mail fora do formato)
  • variação de formato (ex.: telefone em formatos diferentes)
  • espaços extras nas bordas dos valores
  • duplicidade por chave (coluna majoritariamente única com alguns valores repetidos, ex.: CPF)
  • inconsistência de capitalização (ex.: "Porto Alegre" / "PORTO ALEGRE" / "porto alegre")
  • nome de coluna com espaços nas pontas (ex.: " email ", comum em exportações do Excel), com o --rename-columns que os tira
Arquivo: clientes_sujos.csv
Linhas: 20
Colunas: 5

nome
  1 registros com espaços extras

email
  1 valores inválidos

telefone
  3 formatos diferentes

cpf
  1 valores duplicados

cidade
  "PORTO ALEGRE"
  "Porto Alegre"
  "porto alegre"

Um arquivo de exemplo que dispara todos esses problemas está em examples/clientes_sujos.csv.

Com pelo menos uma flag de operação, o comando passa a transformar os dados (só em colunas de texto — colunas numéricas, por exemplo, não são alteradas) e mostra o resultado: grava em --output arquivo (formato inferido pela extensão, igual ao convert) ou, se omitido, imprime o dataset inteiro em CSV no stdout, com o relatório das operações no stderr. Nada é gravado por padrão, e um --output que já existe só é substituído com --overwrite. Ao gravar, uma linha de confirmação vai para o stderr, depois do relatório: Gravado clientes_limpo.csv (csv): 20 linhas, 5 colunas.

Opções que só configuram uma operação exigem essa operação: --key precisa de --remove-duplicates, --drop-null-columns de --drop-null, --document-columns de --normalize-documents, --date-columns de --normalize-dates e --decimal-separator de --fix-types. Sem ela, o comando falha (exit code 2) em vez de ignorar a opção. Pelo mesmo motivo, --output/--overwrite sem nenhuma operação é erro: sem operação, o clean só faz o diagnóstico e não grava nada.

datatool clean clientes.csv --trim --normalize-case --output clientes_limpo.csv
datatool clean clientes.csv --lowercase --output clientes_limpo.csv
datatool clean clientes.csv --uppercase --output clientes_limpo.csv
  • --trim remove espaços extras nas bordas
  • --lowercase / --uppercase convertem a caixa de todo o texto da coluna
  • --normalize-case unifica variações de capitalização em title case ("PORTO ALEGRE"/"porto alegre" → "Porto Alegre")
  • --trim combina com qualquer uma das outras e roda primeiro; --lowercase, --uppercase e --normalize-case são mutuamente exclusivas (passar duas é erro, exit code 2)
nome,email,telefone,cpf,cidade
Pessoa 1,Pessoa1@Example.Com,(11) 91234-5678,10000000001,Porto Alegre
Pessoa 2,Pessoa2@Example.Com,11 91234-5678,10000000002,Porto Alegre
Pessoa 3,Invalido-Sem-Arroba,11912345678,10000000003,Porto Alegre

--remove-duplicates remove linhas duplicadas, mantendo a primeira ocorrência, e reporta quantas foram removidas:

datatool clean clientes.csv --remove-duplicates
datatool clean clientes.csv --remove-duplicates --key cpf --output clientes_limpo.csv
  • Por padrão considera a linha inteira (todas as colunas iguais); --key coluna1,coluna2 deduplica por um subconjunto de colunas
  • A quantidade de linhas removidas é sempre impressa, mesmo gravando em arquivo via --output
  • Combinável com as flags de texto acima — quando combinadas, --trim/--lowercase/--uppercase/--normalize-case rodam antes da remoção de duplicidades, então linhas que só diferiam por espaço ou capitalização também são deduplicadas

--fill-null/--drop-null tratam valores nulos e reportam quantas células/linhas foram afetadas:

datatool clean clientes.csv --null-values "N/D,-"
datatool clean clientes.csv --fill-null "N/A"
datatool clean clientes.csv --fill-null "idade:0" --output clientes_limpo.csv
datatool clean clientes.csv --drop-null
datatool clean clientes.csv --drop-null --drop-null-columns email --output clientes_limpo.csv
  • --fill-null valor (sem :) preenche nulos só nas colunas de texto — evita converter uma coluna numérica inteira para texto ao preencher com um valor não numérico
  • --fill-null coluna:valor preenche só essa coluna, convertendo o valor para o tipo da coluna quando ela é numérica; um valor incompatível com o tipo (ex.: idade:abc) é erro, exit code 2, em vez de transformar a coluna em texto; é repetível (--fill-null "N/A" --fill-null "idade:0")
  • --null-values "N/D,-" troca por nulo, nas colunas de texto, os valores que querem dizer "sem dado". A comparação ignora os espaços nas pontas e diferencia maiúsculas de minúsculas. Roda antes das demais operações, então --null-values "N/D" --fix-types converte uma coluna de números com N/D, e --fill-null/--drop-null tratam os nulos que ela criou
  • --drop-null remove linhas com nulos em qualquer coluna por padrão, ou só nas colunas de --drop-null-columns coluna1,coluna2 (--columns continua aceito como nome antigo)

--normalize-dates converte datas em formatos variados para ISO 8601 (yyyy-mm-dd):

datatool clean clientes.csv --normalize-dates
datatool clean clientes.csv --normalize-dates --date-columns data_nascimento,data_cadastro --output clientes_limpo.csv
  • Sem --date-columns, detecta automaticamente as colunas de texto em que a maioria dos valores (≥ 60% de uma amostra) parece data
  • Formatos reconhecidos: yyyy-mm-dd, yyyy/mm/dd, yyyy.mm.dd, yyyy-mm-ddThh:mm:ss (a hora é descartada), dd/mm/yyyy, dd-mm-yyyy, dd.mm.yyyy, dd/mm/yy, dd-mm-yy e as variantes mm/dd
  • Datas ambíguas como 01/02/1990 são lidas como dd/mm; a coluna só é tratada como mm/dd quando tem valores que só fazem sentido assim (ex.: 12/31/1990) e nenhum que só faça sentido como dd/mm
  • Anos com 2 dígitos seguem a regra do Python: 00–68 → 2000–2068, 69–99 → 1969–1999
  • Valores não reconhecidos são mantidos como estão e listados na saída:
"data_nascimento": 6 datas normalizadas
"data_nascimento": 1 valores não reconhecidos como data, mantidos sem alteração:
  "20261301"

--fix-types converte para número as colunas numéricas armazenadas como texto, inclusive valores monetários em formato brasileiro:

datatool clean relatorio.csv --fix-types --output relatorio_limpo.parquet
datatool clean relatorio.csv --fix-types --decimal-separator , --output relatorio_limpo.parquet
  • Detecta automaticamente as colunas de texto em que ≥ 90% de uma amostra dos valores é numérica
  • Remove R$ e espaços antes de converter
  • --decimal-separator , ou --decimal-separator . define o separador decimal de todas as colunas; o de milhar é o outro caractere. Com ,: 1.234,56 → 1234.56 e 1.500 → 1500. Com .: 1,234.56 → 1234.56 e 1.500 → 1.5
  • Sem --decimal-separator, num CSV separado por ; (o do Excel em português) a vírgula é o decimal e o ponto, o milhar: 1.500 → 1500. Nos demais arquivos, decide por coluna: se algum valor tem vírgula ou R$, usa , como decimal; senão, ., e uma coluna só com valores como 1.500 é lida como 1.5 (informe --decimal-separator , para ler como 1500)
  • A coluna vira int quando nenhum valor tem parte decimal, senão float
  • Colunas com zeros à esquerda (01001000, típico de CEP/CPF) são ignoradas, porque a conversão perderia os zeros
  • Uma coluna com algum valor que não é número (N/D, a combinar, um código como A12) não é convertida: continua como texto, sem perder nenhum valor, e os valores aparecem na saída. As demais colunas são convertidas normalmente:
"valor": não convertida, 1 valores não são números (a coluna continua como texto):
  "a combinar"
"idade": não convertida, 1 valores não são números (a coluna continua como texto):
  "N/D"
"preco": convertida para float
Se esses valores querem dizer "sem dado", --null-values os troca por nulo antes da conversão (ex.: --null-values "N/D,-" --fix-types).

--rename-columns/--remove-columns ajustam o schema:

datatool clean vendas.csv --rename-columns old_name:new_name,foo:bar --output vendas_limpo.csv
datatool clean vendas.csv --remove-columns coluna_interna,coluna_temp --output vendas_limpo.csv
  • Coluna inexistente, entrada sem : em --rename-columns ou renomeação que geraria nomes repetidos são erro claro, sem gravar nada
  • Nomes de coluna com espaços nas pontas (" email ") podem ser referenciados sem os espaços, aqui e em --key, --columns, --drop-null-columns, --date-columns, --document-columns e --fill-null coluna:valor; --rename-columns email:email tira os espaços. Se duas colunas tiverem o mesmo nome sem os espaços ("email" e " email "), é erro (exit code 2)
  • São aplicadas antes das demais operações (primeiro remove, depois renomeia): --key, --drop-null-columns, --date-columns e --fill-null coluna:valor usam os nomes já renomeados, e colunas removidas não entram na deduplicação

--normalize-documents valida e padroniza CPF/CNPJ, inclusive o CNPJ alfanumérico (letras nas 12 primeiras posições, emitido pela Receita desde julho de 2026):

datatool clean clientes.csv                                    # diagnóstico passa a incluir CPF/CNPJ
datatool clean clientes.csv --normalize-documents digits       # 123.456.789-09 → 12345678909
datatool clean clientes.csv --normalize-documents masked        # 12345678909 → 123.456.789-09
datatool clean clientes.csv --normalize-documents masked --document-columns cpf,cnpj_empresa
  • Detecta colunas de texto ou numéricas que "parecem" CPF/CNPJ (formato batendo numa amostra e dígito verificador majoritariamente válido, máscara presente, ou cpf/cnpj/documento no nome da coluna) — sem --document-columns, aplica a todas elas
  • Diagnóstico (clean sem flags e info) reporta, por coluna: dígito verificador inválido, todos os dígitos iguais (ex.: 111.111.111-11), valores fora do formato, mistura de máscara/sem máscara e, em coluna numérica, zeros à esquerda perdidos na leitura
  • digits remove a máscara; masked aplica XXX.XXX.XXX-XX (CPF) ou XX.XXX.XXX/XXXX-XX (CNPJ), com letras sempre maiúsculas
  • Coluna numérica (CPF lido como Int64 perde zeros à esquerda) é completada com 0 e sempre vira texto
  • Normalizar não valida: documentos com dígito inválido são formatados do mesmo jeito, e o comando informa quantos continuam inválidos; só valores fora do formato (nem CPF nem CNPJ) ficam como estão
  • Nunca mostra o CPF/CNPJ no terminal fora do próprio dataset — o diagnóstico e o log só trazem contagens
"cpf": 1.180 documentos normalizados
"cpf": 23 com dígito verificador inválido (formatados, mas continuam inválidos)
"cpf": 2 valores fora do formato de CPF/CNPJ, mantidos sem alteração

CSV com ; ou em cp1252 (Excel em português)

convert, info, profile e clean detectam sozinhos o delimitador (,, ;, tab ou |) e o encoding (UTF-8, com ou sem BOM, UTF-16 com BOM, como o "Texto Unicode" do Excel, ou cp1252) do CSV de entrada. Um CSV exportado pelo Excel em português funciona sem nenhuma opção. Para forçar:

datatool info vendas.csv --sep ";" --encoding latin-1
datatool convert vendas.csv vendas.parquet --sep "\t"
  • --sep aceita um caractere (ou \t para tab); --encoding aceita qualquer codec do Python (cp1252, latin-1, utf-16, ...)
  • Valem só para o arquivo de entrada e só para CSV; a saída CSV continua com , e UTF-8
  • Num CSV separado por ;, a vírgula é o separador decimal já na leitura: 10,5 é lido como o número 10,5. Valores com ponto de milhar (1.500, 1.234,56) chegam como texto, e o info aponta a coluna; datatool clean ... --fix-types os converte lendo o ponto como milhar (1.500 → 1500). Num CSV separado por vírgula, vale o padrão americano (1.500 é 1,5)

Planilhas Excel com várias abas (--sheet)

datatool info relatorio.xlsx --sheet "Vendas 2025"
datatool convert relatorio.xlsx clientes.csv --sheet 3
  • Sem --sheet, convert, info, profile e clean leem a primeira aba visível com dados: abas vazias (uma capa, por exemplo) e ocultas são puladas
  • Quando a planilha tem outras abas, um aviso no stderr diz qual foi lida: Aviso: relatorio.xlsx tem 3 abas (Resumo, Vendas 2025, Clientes); lida: "Resumo". Use --sheet para escolher outra.
  • --sheet aceita o nome da aba ou a posição a partir de 1, como no Excel; o nome tem prioridade, então uma aba chamada 2025 é encontrada pelo nome. Abas ocultas só são lidas quando pedidas com --sheet
  • O texto mostra Aba: Vendas 2025 (2 de 3) logo depois de "Arquivo:", e o JSON traz sheet e sheets no resumo do arquivo
  • As sugestões do info incluem a aba, para o comando sugerido corrigir a aba certa (datatool clean relatorio.xlsx --sheet 'Vendas 2025' --fix-types)
  • Aba inexistente é erro (exit code 2) com a lista de abas; aba vazia pedida com --sheet, ou planilha sem nenhuma aba com dados, é erro com exit code 1
  • Ao gravar em .xlsx, o resultado tem uma aba só, com o nome da aba lida. Por isso, gravar sobre a própria planilha de entrada quando ela tem mais de uma aba é recusado (exit code 2), mesmo com --overwrite, já que apagaria as outras abas: grave em outro arquivo

Log de execução

Toda execução registra em datatool.log, no diretório de logs do usuário (~/Library/Logs/datatool no macOS, ~/.local/state/datatool/log no Linux, %LOCALAPPDATA%\datatool\Logs no Windows), o que foi feito: comando e opções, delimitador/encoding usados, arquivos lidos e gravados, operações do clean com as contagens, erros, exit code e duração. O terminal não muda.

2026-09-25 15:40:46,811 INFO    [41227a] clean: início — args: filename=vendas.csv, fix_types=True, decimal_separator=,, output=limpo.csv, output_format=text
2026-09-25 15:40:46,811 INFO    [41227a] clean: encoding detectado: cp1252 (arquivo não é UTF-8 válido)
2026-09-25 15:40:46,812 INFO    [41227a] clean: delimitador detectado: ';'
2026-09-25 15:40:46,814 INFO    [41227a] clean: --fix-types: "valor" convertida para float
2026-09-25 15:40:46,815 INFO    [41227a] clean: gravado limpo.csv (csv) — 2 linhas, 2 colunas
2026-09-25 15:40:46,815 INFO    [41227a] clean: fim — exit code 0, 0,00 s
  • O log nunca contém valores das células (só caminhos, nomes de coluna, contagens e opções)
  • Rotação a cada 5 MB, mantendo até 3 arquivos antigos (datatool.log.1 a .3)
  • Se o log não puder ser gravado (ex.: diretório somente leitura), o comando roda normalmente, sem log
  • DATATOOL_LOG_DIR=caminho grava em outro diretório (relativo ao diretório atual, se não for absoluto; ex.: DATATOOL_LOG_DIR=logs volta ao comportamento antigo, em ./logs)
  • DATATOOL_NO_LOG=1 desliga o log

Saída em JSON (--format json)

info, profile, clean e convert aceitam --format json (o padrão é --format text, a saída descrita acima). O stdout passa a ser um único documento JSON, para uso em scripts, notebooks e CI:

datatool info clientes.csv --format json | jq '.problems[] | select(.category == "nulls")'
datatool profile clientes.csv --format json > perfil.json
datatool clean clientes.csv --fix-types --remove-duplicates --output limpo.parquet --format json
{
  "schema_version": 1,
  "command": "info",
  "status": "ok",
  "file": {"path": "examples/clientes.csv", "format": "csv", "rows": 10, "columns": 6, "size_bytes": 711},
  "problems": [
    {"category": "nulls", "column": "email", "count": 3, "message": "3 valores nulos em \"email\""}
  ],
  "suggestions": [
    {"category": "nulls", "label": "Tratar valores nulos", "command": "datatool clean examples/clientes.csv --drop-null"}
  ]
}
  • Em planilhas Excel, o resumo do arquivo (file, ou source no convert) traz sheet (a aba lida) e sheets (todas as abas, com "hidden": true nas ocultas); em bancos SQLite, table (a tabela lida) e tables (todas)
  • Cada problema traz count e count_unit (rows, values, formats, variants ou columns), que diz o que está sendo contado
  • Todo documento traz schema_version, command e status; info traz problems/suggestions, profile traz duplicates/columns, o clean traz problems (diagnóstico) ou operations/output (com operações), e o convert traz source/target
  • Números sem formatação pt-BR nem arredondamento; NaN vira null
  • Erros também saem em JSON ("status": "error"), com o mesmo exit code do modo texto
  • No clean com operações, --output é obrigatório, e no convert, o to_filename: o JSON é só o relatório, os dados vão para o arquivo
  • O formato completo, campo a campo, está em specs/019-saida-json.md

Ocultar valores de célula (--redact-values)

info, profile e clean aceitam --redact-values (padrão desligado), nos dois formatos, para tirar valores de célula do relatório sem perder as contagens — útil ao colar a saída num chat de IA, ticket de suporte ou log de CI:

datatool profile clientes.csv --redact-values
datatool clean clientes.csv --redact-values
  • Em profile, os valores mais frequentes viram <valor 1>, <valor 2>, ...; count/percent continuam reais
  • No diagnóstico, a inconsistência de capitalização passa a mostrar só a contagem ("3 variações de capitalização"), em vez de listar as variantes
  • Nas operações do clean (--normalize-dates, --fix-types, --normalize-documents), os valores não reconhecidos somem da lista — fica só a contagem e (valores ocultos por --redact-values)
  • Nunca muda o arquivo gravado por --output, só o que é impresso ou volta em --format json

Servidor MCP (datatool-mcp)

Expõe info, profile, clean (diagnóstico e operação) e convert como ferramentas MCP para um agente de IA (Claude Code, Claude Desktop, Cursor, ...) chamar diretamente, em vez de escrever código de análise do zero a cada conversa. Requer pip install "datatool-cli[mcp]" (ver Instalação) — quem só usa o CLI não precisa dessa dependência.

{
  "mcpServers": {
    "datatool": {
      "command": "datatool-mcp",
      "args": ["--root", "/caminho/do/projeto"]
    }
  }
}
  • Ferramentas: datatool_info, datatool_profile (+ columns/max_columns, padrão 50), datatool_clean_diagnose, datatool_clean_apply (grava em output) e datatool_convert (grava em to_filename) — cada uma devolve o mesmo JSON de --format json
  • Todo caminho de arquivo fica restrito ao diretório passado em --root; output/to_filename nunca pode ser o mesmo arquivo da entrada, e uma saída já existente exige overwrite: true
  • redact_values vem ligado por padrão nas ferramentas (diferente do CLI, onde vem desligado): os valores de célula não trafegam para o modelo de IA a menos que a pessoa configure a ferramenta com redact_values: false
  • Em planilhas Excel, todas as ferramentas aceitam sheet (nome ou posição), e o JSON devolvido lista as abas em file.sheets (source.sheets no convert), para o agente escolher a aba certa; em bancos SQLite, table, com a lista em file.tables
  • No datatool_clean_apply, drop_null_columns restringe o drop_null a essas colunas; columns, o nome antigo, ainda é aceito, mas será removido numa versão futura
  • Cada chamada é registrada em <root>/logs/datatool.log (ou onde DATATOOL_LOG_DIR apontar), com o nome prefixado (mcp info, mcp clean, ...)
  • Só ferramentas Community por enquanto — o detalhamento completo está em specs/020-mcp-server.md

Desenvolvimento

Instalar a partir do código-fonte, em modo editável (alterações em src/datatool/ valem sem reinstalar), com as ferramentas de teste, lint e checagem de tipos, que já incluem o servidor MCP:

git clone https://github.com/wvcode/cli-python.git
cd cli-python
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Para apenas rodar via módulo, sem instalar: PYTHONPATH=src python -m datatool.main <comando> ...

Rodar os testes (com cobertura; o CI exige pelo menos 95%):

pytest --cov

Rodar o lint, o formatador e a checagem de tipos:

ruff check src/ tests/
ruff format --check src/ tests/
pyright
  • Os testes ficam em tests/, um arquivo por comando/assunto; conftest.py e helpers.py têm o que é compartilhado
  • Durante os testes, o log vai para ./logs do diretório temporário de cada teste (DATATOOL_LOG_DIR, no conftest.py)
  • As versões mínimas declaradas em pyproject.toml são verificadas no CI (job test-minimum, com uv pip install --resolution lowest-direct)
  • A versão vem da tag do git (setuptools-scm): publicar uma release com a tag v0.2.0 gera o pacote 0.2.0

Estrutura do projeto

src/datatool/   código-fonte do CLI (comandos, leitura/gravação, heurísticas)
tests/          suíte de testes (pytest)
specs/          uma spec por user story, com critérios de aceite e status
examples/       arquivos de exemplo para testar os comandos manualmente

Metadata

Release files for datatool-cli 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for datatool-cli 0.1.3
File Size Uploaded Provenance Actions
datatool_cli-0.1.3.tar.gz 327.7 kB With provenance Details for datatool_cli-0.1.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for datatool-cli 0.1.3
File Interpreter ABI Platform Actions
datatool_cli-0.1.3-py3-none-any.whl Python 3 none any Details for datatool_cli-0.1.3-py3-none-any.whl

Total release size: 401.0 kB

Release files / datatool_cli-0.1.3.tar.gz

Download URL datatool_cli-0.1.3.tar.gz
Size 327.7 kB
Tags Source
SHA-256 checksum
How to use checksums
6763f06e12eec693fc55b3571d6ca5e87c1413afecac10391f48f0975e30abc5
BLAKE2b-256 checksum
How to use checksums
4d47063ed623d8f772eacfa00beb7934af9a57a1a65cd937ca921128b2f6b0dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release files / datatool_cli-0.1.3-py3-none-any.whl

Download URL datatool_cli-0.1.3-py3-none-any.whl
Size 73.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
321618311ac1a7a7d5fdeda1b70f4f5847d2ec8b2b2b70bd67259d4ffe7c6d8c
BLAKE2b-256 checksum
How to use checksums
7dee1858f89aa9766bf0d34cb9cf2f011bcd0cfac163e7916e5a933e766c043f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Security for datatool-cli 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for datatool_cli-0.1.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page