From financeiro
Processa extrato bancário em lote e lança no FIN App. Aceita 5 formatos (preferência: OFX > CSV > CNAB 240 > texto colado > PDF). Garante idempotência (FITID pra OFX, hash pros outros). Categoriza automaticamente via Estabelecimentos.md, mostra tabela pra revisão, lança em batch e atualiza memória + Status Conciliação.md. Use quando a pessoa colar/anexar o extrato de uma conta corrente, poupança ou conta digital.
How this skill is triggered — by the user, by Claude, or both
Slash command
/financeiro:extrato [caminho-do-arquivo OU 'colado'][caminho-do-arquivo OU 'colado']This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
- Pessoa quer processar **um extrato bancário inteiro** (várias transações de uma vez)
/financeiro:lancar/financeiro:fatura (fluxo diferente, lança via fin_fatura_transacoes)/financeiro:instalar-fin-mcp/financeiro:onboarding primeiro~/.fin-plugin/config.json existe → leia financeiro_pathFinanceiro/ existemfin://docs/guia nessa sessão3 formas de receber:
Forma A: Caminho de arquivo em $ARGUMENTS
.ofx, .csv, .txt, .pdf) e/ou pelo conteúdo (primeiras linhas)Forma B: Pessoa colou o conteúdo na conversa
OFXHEADER: ou <OFX> → OFXForma C: Pessoa anexou um PDF
Pergunta a conta de destino (se não estiver óbvio do arquivo):
Esse extrato é de qual conta? (lista de contas existentes em
Contas e Cartões.md)
Parse XML padrão. Pra cada <STMTTRN>, extrai:
FITID (ID único da transação no banco — chave de idempotência)DTPOSTED → dataTRNAMT → valor (negativo = débito, positivo = crédito)MEMO → descriçãoNAME → nome do estabelecimento (se houver)TRNTYPE → tipo (DEBIT, CREDIT, XFER, etc.)OFX é o melhor formato porque o FITID é um ID único do banco — você nunca duplica.
Parse com detecção de cabeçalho. Tenta identificar colunas:
dd/mm/yyyy, yyyy-mm-dd, dd-mm-yyyy)Se as colunas não tiverem nomes claros, mostra as primeiras 3 linhas pra pessoa e pergunta qual coluna é qual:
Não consegui detectar as colunas automaticamente. Olha as primeiras linhas:
[conteúdo]Qual coluna é a data? E o valor? E a descrição?
Padrão Febraban posicional. Parse byte por byte conforme spec do banco. Avisa que CNAB pode variar entre bancos e pede pra confirmar se algo parecer estranho.
Best-effort. Tenta achar padrões:
Mostra o que parseou pra confirmação antes de seguir.
Avisa primeiro:
Detectei PDF. Parse de PDF é frágil porque cada banco tem layout diferente. Vou tentar, mas é importante tu revisar com atenção depois. Se tu tiver outro formato (OFX, CSV, CNAB), prefere mandar.
Tenta extração de texto do PDF (Bash com pdftotext ou similar se disponível). Aplica heurísticas pra achar linhas de transação. Mostra resultado pra pessoa.
Depois do parse, normaliza tudo num formato interno:
[
{
chave_idempotencia: "FITID:abc123" ou "hash:xyz",
data: "2026-03-15",
valor: -45.00,
descricao_original: "MERCADO XYZ LTDA",
descricao_normalizada: "mercado xyz",
tipo: "debito",
conta: "[nome da conta]"
},
...
]
Geração de hash (formatos não-OFX):
hash = sha1(data + "|" + valor + "|" + descricao_normalizada + "|" + conta)
Lê Estabelecimentos.md. Pra cada transação:
Resultado:
ANTES de lançar qualquer coisa, busca no FIN o que já existe no período:
fin_buscar_transacoes(
conta_id: <id da conta>,
data_inicio: <menor data do extrato>,
data_fim: <maior data do extrato>
)
Pra cada transação retornada do FIN, calcula a chave de idempotência (mesmo método: FITID se tiver, hash caso contrário).
Compara com a lista do extrato e separa em 3 grupos:
| Grupo | Definição |
|---|---|
| Já existe | Chave bate com algo já no FIN |
| Vai lançar | Chave nova, vai ser criada |
| Suspeito | Chave não bate exato mas tem transação muito próxima (mesmo dia, valor igual, descrição parecida) |
Suspeitos vão pra revisão manual. Você não decide sozinho.
Mostra UMA tabela com TUDO, organizada:
=== JÁ EXISTEM NO FIN (vão ser ignoradas) ===
| Data | Valor | Descrição | Categoria |
|------------|----------|--------------------|--------------------|
| 2026-03-01 | -45,00 | MERCADO XYZ | Alimentação > Mer |
... [N linhas]
=== CATEGORIZADAS AUTOMATICAMENTE (vou lançar com a regra) ===
| Data | Valor | Descrição | Categoria sugerida | Regra aplicada |
|------------|----------|--------------------|------------------------------|----------------|
| 2026-03-15 | -50,00 | UBER *TRIP | Transporte > App | uber → ... |
... [M linhas]
=== A CATEGORIZAR (preciso de tu) ===
| # | Data | Valor | Descrição | Categoria? |
|----|------------|----------|------------------------|------------|
| 1 | 2026-03-08 | -120,00 | LOJA NOVA SA | ? |
| 2 | 2026-03-12 | -89,00 | RESTAURANTE Y | ? |
... [K linhas]
=== SUSPEITOS DE DUPLICATA (revisar) ===
| # | Data | Valor | Descrição | Possível duplicata no FIN |
|----|------------|----------|------------------|-----------------------------|
| 1 | 2026-03-10 | -75,00 | POSTO X | "Posto X" R$75 em 2026-03-10|
... [J linhas]
=== RESUMO ===
- N já existem (vão ser puladas)
- M categorizadas (vou lançar direto se confirmar)
- K precisam de categoria
- J suspeitos pra ti decidir
- Total a lançar (max): M + K + J
Pergunta na ordem:
Pra cada uma das K transações novas, me diz a categoria. Pode responder em bloco, tipo:
- Lazer > Bar
- Alimentação > Restaurante ...
Se ela disser "Loja Nova SA é tudo Pessoal > Roupas", aprende.
Esses J parecem duplicatas. Pra cada um: lança mesmo (1) ou pula (0)?
Vou lançar [total final] transações no FIN, conta [X]. Confirma?
Use fin_criar_transacoes_batch pra lançar até 100 rows de uma vez (mix de expense/income/transfer). Bate em 1 chamada o que seria N chamadas sequenciais.
{
"transactions": [
{ "type": "expense", "amount_cents": 5000, "description": "Mercado XYZ", "account_name": "[conta]", "category_name": "Alimentação", "subcategory_name": "Mercado" },
{ "type": "income", "amount_cents": 500000, "description": "Salário", "account_name": "[conta]" },
{ "type": "transfer", "amount_cents": 20000, "description": "Saque 24h", "account_from": "[conta]", "account_to": "[conta dinheiro vivo]" },
...
]
}
Resposta: { total, created: [...], failed: [...] }. Partial success by design — rows que falham NÃO revertem as anteriores. Mostra progresso:
Lançando 47 transações em batch... ✓ 45 criadas, 2 falhas.
Pra cada row:
type: "expense" → fin_criar_despesa semantics.type: "income" → fin_criar_receita semantics.type: "transfer" → fin_criar_transferencia semantics.Se o batch tiver mais de 100 rows, quebra em múltiplas chamadas.
Se alguma row falhar, mostra a lista no fim: "Lançadas 45 de 47. Falhas: [{ index: 12, error: 'categoria não encontrada' }, ...]". Pergunta como tratar.
Estabelecimentos.mdPra cada estabelecimento NOVO categorizado pela pessoa, adiciona linha:
| LOJA NOVA SA | Loja Nova | Pessoal | Roupas | 2026-04-12 |
Status Conciliação.mdAdiciona linha pra esse processamento (use os nomes reais da pessoa):
| [conta] | YYYY-MM-DD a YYYY-MM-DD | Conciliado | YYYY-MM-DD | [lista de FITIDs ou hashes] |
Preferências.mdSe a pessoa deu uma regra explícita ("loja nova SA é sempre roupa"), adiciona em "Categorização padrão" ou "Decisões não-óbvias" conforme o caso.
✓ Extrato processado.
- Conta: [nome real]
- Período: YYYY-MM-DD a YYYY-MM-DD
- Total de linhas no arquivo: N
- Já existiam no FIN: M (puladas)
- Lançadas agora: K
- Falhas: F
- Aprendi X estabelecimentos novos.
- Status Conciliação atualizado.
Depois de importar todas as transações do extrato em lote, sempre reconcilia o saldo da conta no FIN com o saldo real do app bancário. Isso é o que fecha o lote — se pular, o saldo fica à deriva e toda sessão futura vai ter que lidar com número errado.
São conceitos diferentes e comparar o errado causa falso positivo de divergência de milhares de reais:
fin_saldos = inclui TUDO que está lançado, inclusive tx com tx_date no futuro (ex: Pix feito em fim de semana com crédito em D+1 útil).Sempre peça print da tela inicial do app do banco, não da linha de "saldo" dentro do extrato. Se a pessoa mandar só extrato, a última linha de saldo é só referência — o saldo real "agora" pode ser diferente.
Pix feito sábado/domingo/feriado é creditado com data D+1 útil no extrato (convenção bancária). Exemplo: Pix feito sábado 18/04 aparece no extrato com data = 20/04 (segunda). Ao lançar no FIN, use a data que o banco credita, não a data que a pessoa fez o Pix — pra bater com o extrato quando conciliar.
O saldo atual do banco já reflete o Pix mesmo antes da data de crédito (ele sai como "agendado/em processamento"). O saldo do FIN também reflete, porque o FIN soma todas as tx lançadas sem cutoff de data.
fin_saldos pra pegar o saldo exibido atual. Se já bater (dentro da tolerância de ruído, ver abaixo), nada a fazer — avisa "✓ Saldo já bate, R$X,XX" e fim.fin_ajustar_saldo_conta passando o saldo desejado direto em amount_cents. A tool retorna balance_cents_calculado — confere se bateu. Se bateu, segue. Se não bateu, investiga (tem transação faltando/sobrando que não é resolvida por ajuste de initial_balance sozinho).Vários bancos brasileiros têm aplicação automática diária (rendimento que pinga em micro-valores). Esse rendimento agregado nem sempre bate 1:1 com o extrato exportado, especialmente quando o lançamento individual é fração de centavo arredondada.
Use uma tolerância pequena (alguns reais ou ~0,5% do saldo, o que for menor) como ruído aceitável. Se a divergência cabe nessa tolerância e tu identifica que é só rendimento, nomeia como "divergência de rendimento residual" e segue. Se for maior, ou concentrada em uma data específica (não só rendimento agregado), aí sim investiga.
Se a pessoa quer um valor de tolerância fixo, pergunta uma vez e grava em Preferências.md (ex: "tolerância de rendimento residual: R$5/mês").
Sobre fin_ajustar_saldo_conta: você não precisa calcular nada manualmente. Passa o saldo desejado em amount_cents, a tool faz a conta initial_balance + Σ(tx) e devolve balance_cents_calculado no retorno. Se não bateu com o desejado, é sinal de problema de dados — investiga em vez de insistir.
Atualizar Status Conciliação.md: registra que o saldo foi reconciliado em DD/MM/AAAA e em qual valor, pra sessões futuras saberem o ponto de partida.
Em vez de fazer heurística client-side pra saque/pagamento de fatura/transferência cross-conta, use fin_classificar_linha_extrato. A tool recebe {description, amount_cents, account_id, trntype?, fitid?} e retorna {type, confidence, reason, details} onde type ∈ expense|income|transfer|payment_invoice|atm_withdrawal.
Fluxo recomendado: passa cada linha pelo classifier antes de decidir qual tool de lançamento usar. A resposta te diz o tipo e (quando possível) sugere a conta contraparte (conta de dinheiro vivo pra ATM, cartão pra PAG FATURA, outra conta pra XFER).
// Exemplo
classify({
description: "SAQUE 24H BANCO X",
amount_cents: -20000,
account_id: "uuid-conta",
trntype: "ATM"
})
→ { type: "atm_withdrawal", confidence: "high",
details: { suggested_cash_account_id: "uuid-dinheiro-vivo" } }
// → cria transferência [conta] → [conta dinheiro vivo] via fin_criar_transferencia
O classifier tem blocklist de palavras genéricas (PIX, TED, DOC, etc) pra não dar falso positivo. Se a resposta vier com confidence: "low", pergunta pra pessoa antes de lançar.
As seções abaixo ainda valem como referência semântica do que cada tipo significa, mas a detecção deve usar o classifier.
Algumas linhas do extrato são "saldo anterior" e "saldo final". Ignora como transação (não vira fin_criar_despesa/fin_criar_receita), mas guarda os valores — o "saldo final" vai servir de referência inicial pro passo de Reconciliação de saldo pós-import acima.
Tarifa bancária, IOF, anuidade são despesas normais. Categoriza em "Taxas, Juros & Impostos". Se a pessoa tiver subcategorias específicas (Tarifa bancária, IOF), aplica.
São receitas. Categoriza em "Rendimento" ou similar. Aprende como regra (todo banco X tem padrão de descrição "RENDIMENTO POUPANÇA", "JUROS S/SALDO", etc.) e da próxima vez aplica direto.
Se o extrato mostra "TED" / "PIX" / "TRANSFERÊNCIA" pra outra conta da pessoa, é uma fin_criar_transferencia. Identifica a conta destino pelo Contas e Cartões.md. Se não conseguir identificar, pergunta.
Atenção dupla contagem: se a pessoa processar o extrato da conta A E da conta B no mesmo período, a transferência pode aparecer dos 2 lados. Lança UMA vez só, não duas. Use o hash pra detectar duplicata cross-conta.
Linha tipo "PAGAMENTO FATURA [cartão]". Isso NÃO é despesa de R$X. É um pagamento de fatura. Use fin_pagar_fatura em vez de fin_criar_despesa. Identifica o cartão no Contas e Cartões.md pelo nome.
Linha tipo "SAQUE 24H BANCO X". É uma transferência da conta pra conta de dinheiro vivo (mesma regra de saque manual). Lança via fin_criar_transferencia.
Se a pessoa não tem conta de dinheiro vivo no FIN, oferece criar uma vez (igual em /financeiro:lancar).
Se for muito grande, processa em batches de 50:
Não tenta colocar 300 linhas numa tabela só.
Se o parser falhar (formato corrompido, encoding estranho, layout não reconhecido):
fin_pagar_fatura, não despesafin_criar_transferencia banco → conta de dinheiro vivoStatus Conciliação.md → todo lote processado vira linha láPT-BR informal, direto. Sem travessão (—). Mostra trabalho ("parseando...", "buscando duplicatas no FIN..."), tabelas claras, confirmações curtas.
npx claudepluginhub pe-menezes/fin-claude-plugin --plugin financeiroProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.