CLI zero-dependência para as APIs públicas do PNCP (Portal Nacional de Contratações Públicas)
Project description
pncp-cli
CLI e biblioteca Python para as APIs públicas do PNCP (Portal Nacional de Contratações Públicas). Sem dependências além da stdlib.
Cobre os endpoints GET públicos das duas APIs REST oficiais (specs OpenAPI em
/api/consulta/v3/api-docs e /api/pncp/v3/api-docs) e a API de busca do
portal. Inclui uma skill de Claude Code para uso
assistido.
Instalação
uv tool install pncp-cli # ou: pipx install pncp-cli
pncp --version
# a partir do código-fonte
git clone https://github.com/AnxietyLab/pncp-cli
cd pncp-cli
uv tool install -e .
Comandos
| comando | descrição |
|---|---|
search |
busca textual/facetada (editais, atas, contratos) |
filtros |
facetas e tabelas de IDs da busca |
consulta contratacoes |
contratações por período de publicação ou atualização |
consulta propostas |
contratações com propostas em aberto |
consulta atas / contratos |
atas de registro de preço e contratos por período |
consulta cobranca |
instrumentos de cobrança por período |
consulta pca |
Plano de Contratações Anual (geral, por usuário ou atualização) |
contratacao / itens / arquivos / historico |
detalhe de uma contratação |
resultados |
fornecedor vencedor e valores homologados por item |
ata |
atas de uma contratação (detalhe, arquivos, partes, contratos) |
contrato |
contratos e sub-recursos (termos, empenhos, arquivos) |
orgao |
órgãos por CNPJ, id ou razão social; unidades |
pca |
PCA de um órgão (consolidado, itens, valores, CSV) |
dominio |
tabelas de referência (modalidades, amparos legais etc.) |
controle |
decompõe um número de controle PNCP |
Exemplos
# descoberta
pncp search "notebook" --tipo edital --status recebendo_proposta --uf SP --table
# coleta por período (NDJSON: um registro por linha, em streaming)
pncp consulta contratacoes --de 2026-01-01 --ate 2026-06-30 \
--modalidade 6 --all --ndjson > pregoes.ndjson
# da busca ao detalhe
pncp search "ambulância" --tipo edital --all --limit 50 --ndjson \
| jq -r .numero_controle_pncp \
| while read c; do pncp itens --controle "$c" --ndjson; done
# documentos de uma contratação
pncp arquivos 07424905000138 2026 212 --baixar ./docs
# quem venceu cada item, por quanto
pncp resultados 80881915000192 2026 44 --ndjson
# demanda futura declarada de um órgão
pncp pca valores 00394452000103 2026
# filtro local com --limit contando após o filtro
pncp consulta contratacoes --de 2026-06-01 --ate 2026-06-30 --all \
--incluir "armazenamento de dados" --incluir storage --excluir locacao \
--limit 100 --ndjson --link
Flags globais
| flag | efeito |
|---|---|
--output json|ndjson|table |
formato de saída (--ndjson/--table são atalhos) |
-q, --quiet |
suprime o progresso no stderr; avisos continuam |
--timeout S, --retries N |
ajustes por requisição (padrão 60s / 5) |
--pausa SEG |
espera entre requisições consecutivas |
--version |
versão instalada |
Saída no stdout é sempre JSON válido (seguro para jq); progresso e avisos
vão para o stderr.
| exit code | significado |
|---|---|
| 0 | sucesso |
| 1 | erro |
| 3 | sucesso parcial: stdout válido porém truncado; o stderr indica como retomar |
Coletas grandes
Janelas automáticas
A API /consulta rejeita períodos maiores que 365 dias (HTTP 422). Os
comandos de período dividem o intervalo em janelas válidas automaticamente.
Streaming
Em NDJSON, cada registro é emitido assim que a página chega. Nada é acumulado
em memória, e uma falha no meio preserva o que já saiu: exit code 3, página de
retomada indicada no stderr e, no JSON agregado, os campos
incompleto/proximaPagina.
Checkpoint
consulta contratacoes --checkpoint arquivo.json grava o
progresso após cada página, por unidade de trabalho (modalidade × janela), e
retoma coletas interrompidas do ponto exato — inclusive varreduras
--modalidade all sobre períodos longos. Regras:
- exige saída NDJSON (em
json/tableos registros só saem no fim, e uma interrupção perderia dados já registrados como coletados); - o arquivo guarda a identidade da consulta (datas, filtros,
--all,--link); reutilizá-lo com parâmetros diferentes é recusado; --limitfica fora da identidade: atingido o limite, o checkpoint é mantido e uma execução posterior com limite maior continua de onde parou;- a retomada é at-least-once com granularidade de página: uma interrupção
abrupta pode re-emitir registros da página em andamento. Ao carregar em
banco, deduplique por
numeroControlePNCP(contratações) ou pela chave composta comnumeroItem/sequencialDocumento(itens, resultados, arquivos); - incompatível com
--incluir/--excluir(colete sem filtro e filtre depois).
Filtros locais
search e consulta contratacoes aceitam uma etapa de filtro aplicada
localmente sobre os registros:
| flag | semântica |
|---|---|
--incluir TERMO |
mantém registros que casam (repetível) |
--excluir TERMO |
descarta registros que casam (repetível) |
--match any|all |
--incluir exige qualquer termo (padrão) ou todos |
--link |
acrescenta _link_pncp (URL da contratação no portal) |
Um termo de uma palavra casa token inteiro ("rede" não casa "credenciamento");
um termo com espaços casa como frase. A comparação ignora caixa e acentos.
Com filtros, --limit conta registros após o filtro.
Comportamentos da API tratados pela CLI
Comportamentos conhecidos dos servidores do PNCP tratados pela CLI:
- O WAF recusa conexões sem
User-Agentde navegador; a API/consultaexigeAccept: application/json. A CLI envia ambos. - Rate limit se manifesta como HTTP 429 ou como página HTML em resposta 200;
os dois casos são retentados com espera (respeitando
Retry-After). - Endpoints de coleção do
pncp-apipaginam comtamanhoPagina=10por padrão e truncam sem qualquer indicação. A CLI sempre pagina até o fim. - Coleção vazia é sinalizada como 404 com mensagem descritiva; a CLI converte em lista vazia. O 404 de um recurso de detalhe continua sendo erro.
tamanhoPaginamáximo varia por endpoint (50 em contratações, 100 em cobrança, 500 em atas/contratos);--tamé validado antes da requisição.- Períodos maiores que 365 dias retornam 422; ver janelas automáticas acima.
- Resposta vazia no meio de uma paginação (após a API indicar páginas restantes) é tratada como truncagem, não como fim normal.
- Instabilidades do lado do servidor (5xx intermitente) são retentadas; se persistirem, a coleta termina como sucesso parcial (exit 3), sem descartar os registros já obtidos.
Uso como biblioteca
O núcleo não depende de argparse. iter_consulta, iter_cru e
iter_envelope são generators com parâmetros explícitos; filtrar e
com_link compõem sobre qualquer iterável:
from pncp_cli import iter_consulta, filtrar, CONFIG
CONFIG["pausa"] = 0.5
registros = iter_consulta(
"/api/consulta/v1/contratacoes/publicacao",
{"dataInicial": "20260101", "dataFinal": "20260630",
"codigoModalidadeContratacao": 6},
seguir=True)
for r in filtrar(registros, incluir=["storage", "armazenamento de dados"]):
...
Skill de Claude Code
O pacote embute uma skill para Claude Code que ensina o assistente a operar esta CLI: quando usar busca ou consulta, vocabulário de modalidades e códigos, receitas de coleta e as armadilhas da API. Para instalar:
pncp skill instalar # copia para ~/.claude/skills/pncp
Respeita CLAUDE_CONFIG_DIR; use --dir para outro destino. A fonte fica em
src/pncp_cli/skill/SKILL.md.
Desenvolvimento
uv run --with pytest --no-project pytest tests/ -q
Os testes simulam o transporte HTTP; nenhum toca a rede. A estrutura do
pacote separa transporte (client.py), paginação (pagination.py), domínio
(filtros.py, controle.py), apresentação (output.py) e comandos
(commands/).
Licença
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pncp_cli-2.0.0.tar.gz.
File metadata
- Download URL: pncp_cli-2.0.0.tar.gz
- Upload date:
- Size: 41.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18885115c43e43b2879a307a80a212b0b778df13a8a4a4fce0bbb237582e120c
|
|
| MD5 |
cd5ba46d85bc4e4363180cff53cea665
|
|
| BLAKE2b-256 |
20d2cba91f879e79e5ceeac5bc521d80f9012c1aa99b7861459c2ed254307b87
|
File details
Details for the file pncp_cli-2.0.0-py3-none-any.whl.
File metadata
- Download URL: pncp_cli-2.0.0-py3-none-any.whl
- Upload date:
- Size: 35.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59a36f0d80020f0dc7793ad7124c3e21022ae04865019f74db03ddbe21a87f65
|
|
| MD5 |
a689e94cba2b7b8c21361b4a0a3ec917
|
|
| BLAKE2b-256 |
7ac9475cd5f170725648608da4824fb2202ea8c4df2b9650074ae625573901bc
|