| name | lancar |
| description | Lançamento avulso de transação no FIN App. Entende instruções em linguagem natural ("lança 45 no mercado, débito [conta]", "20 conto no pão, dinheiro", "saquei 200 no Itaú", "recebi 4mil do cliente X", "vendi $100 e veio R$540", "tô com $487 na carteira"), aplica regras aprendidas de Estabelecimentos.md, trata dinheiro vivo, saque, câmbio USD/BRL e ajuste de saldo corretamente, sempre confirma em uma linha antes de criar. Aprende e atualiza memória.
|
| argument-hint | [descrição da transação em linguagem natural] |
| allowed-tools | Read Write Edit Glob Grep |
Quando usar
- Pessoa quer lançar uma única transação rapidamente
- Frases tipo "lança X reais em Y", "gastei X no Z", "recebi X do W", "transferi X de A pra B"
- Saque de dinheiro vivo
Quando NÃO usar
- Várias transações de uma vez (extrato, fatura, lista) → use
/financeiro:extrato ou /financeiro:fatura
- Pessoa quer lançar fatura inteira do cartão →
/financeiro:fatura
- MCP do FIN não tá instalado →
/financeiro:instalar-fin-mcp
- Plugin nunca rodou nessa máquina →
/financeiro:onboarding primeiro
Pré-requisitos (verificar antes de cada chamada)
- MCP do FIN responde (testa com
fin_listar_contas se ainda não fez na sessão)
~/.fin-plugin/config.json existe → leia financeiro_path
- Os 4 arquivos em
Financeiro/ existem (Preferências, Contas e Cartões, Estabelecimentos, Status Conciliação). Se não existem, dispara /financeiro:onboarding.
- Leu
fin://docs/guia nessa sessão (se não, leia agora)
Fluxo principal
Passo 1 — Parse da instrução
Pega $ARGUMENTS (ou a fala livre da pessoa) e extrai:
- Tipo: despesa, receita, transferência (+ caso especial: saque)
- Valor: sempre em reais (BRL)
- Estabelecimento/origem/destino: nome do lugar/pessoa/empresa
- Forma de pagamento / conta: débito, crédito, dinheiro, PIX, conta específica
- Data: hoje (default), ou data explícita se mencionada ("ontem", "dia 5", "10 de março")
- Observação: qualquer detalhe adicional
Exemplos de parsing (use os nomes reais de conta/cartão da pessoa, esses são só placeholders):
| Frase | Tipo | Valor | Estabelecimento | Conta |
|---|
| "lança 45 no mercado, débito [conta]" | despesa | R$45 | mercado | [conta] (débito) |
| "20 conto no pão, dinheiro" | despesa | R$20 | padaria/pão | dinheiro vivo |
| "120 no posto, crédito [cartão]" | despesa | R$120 | posto | [cartão] (crédito) |
| "recebi 4 mil do cliente X" | receita | R$4000 | cliente X | (perguntar conta destino) |
| "transferi 500 do [conta A] pro [conta B]" | transferência | R$500 | — | A → B |
| "saquei 200 no [conta]" | transferência | R$200 | — | conta → dinheiro vivo |
| "PIX 50 pra [pessoa]" | despesa OU transferência | R$50 | [pessoa] | (perguntar conta origem; perguntar se é despesa ou transfer entre contas próprias) |
| "vendi $100 e veio R$540" | câmbio (vender USD) | $100 / R$540 | — | Conta USD → Conta BRL |
| "comprei $50 por R$280" | câmbio (comprar USD) | R$280 / $50 | — | Conta BRL → Conta USD |
| "tô com $500 na carteira" | ajuste de saldo | $500 (absoluto) | — | Conta USD |
| "gastei $20 em [merchant]" | despesa USD | $20 | [merchant] | Conta USD |
| "ajusta a [conta] pra 1234,56" | ajuste de saldo | R$1234,56 (absoluto) | — | Conta BRL |
Notação numérica BR:
- "20 conto" / "20 mango" / "20 pila" = R$20
- "4 mil" / "4k" = R$4.000
- "500 reais" / "500" = R$500
- Vírgula é decimal: "45,50" = R$45,50
Notação USD:
- "$100" / "100 dólares" / "100 dolar" / "100 USD" = US$100
- "$1.5k" / "1500 dólares" = US$1.500
- Quando a pessoa só fala "100" sem moeda, assume BRL (default)
- Quando a pessoa usa
$ no início, assume USD
- Em caso de dúvida, pergunta ("100 reais ou 100 dólares?")
Passo 2 — Tratamento especial: dinheiro vivo
Se a pessoa mencionar "dinheiro", "vivo", "espécie", "carteira", "papel", "cash", o plugin mapeia pra conta "Dinheiro" (ou nome equivalente em Contas e Cartões.md).
Se a conta "Dinheiro" não existir ainda no FIN:
Vi que tu pagou em dinheiro mas tu não tem uma conta "Dinheiro" cadastrada no FIN. Quer que eu crie agora? (Dinheiro vivo é uma conta como qualquer outra: tem saldo, recebe lançamentos, e quando tu sacar do banco eu já registro como transferência banco → Dinheiro automaticamente.)
Se ela aceitar, cria via fin_criar_conta (tipo "Dinheiro" ou equivalente, saldo inicial 0 ou perguntado).
Passo 3 — Tratamento especial: saque
Saque NÃO é despesa. Se a pessoa disser "saquei X no banco Y", isso é uma fin_criar_transferencia da conta bancária pra conta "Dinheiro".
Confirmação:
Saque R$200 / Itaú → Dinheiro (transferência). Confirma?
Se ela disser "não, é despesa mesmo" (caso raro, tipo taxa de saque), aceita e lança como despesa.
Passo 4 — Tratamento especial: PIX pra pessoa
PIX pra alguém pode ser despesa (se for pagamento) ou transferência (se for entre contas próprias) — depende do contexto.
- "PIX 50 pra padaria" → despesa
- "PIX 100 pra [parente/amigo]" → pode ser despesa (presente, ajuda, divisão de conta) ou transferência (se a conta destino é da pessoa). Não assume categoria — segue regra de
Estabelecimentos.md se houver, ou pergunta.
- "PIX 500 do [conta A] pro [conta B]" (ambas próprias) → transferência
Se ambíguo, pergunta:
50 pra [destinatário] é despesa (vai gastar) ou transferência (entre tuas contas)?
Passo 4.5 — Tratamento especial: USD, câmbio e ajuste de saldo
Pré-requisito: se a pessoa tem alguma conta USD no FIN, leia a seção sobre USD em fin://docs/guia uma vez por sessão antes de operar qualquer coisa em USD. Sem isso, você comete erros de modelo.
Regras de negócio críticas
fin_criar_despesa aceita contas USD. amount sempre é gravado em BRL (fonte da verdade pra relatórios), mas a tool aceita original_amount_cents + original_currency: "USD" pra preservar o valor nativo. Dois modos:
- Modo BRL exato: passa
amount_cents (BRL que saiu) + original_amount_cents (US$) + original_currency: "USD". Use quando a pessoa sabe o valor real que saiu da conta (extrato/app da conta USD mostra).
- Modo via cotação: passa
original_amount_cents + original_currency: "USD" + exchange_rate (cotação em decimal BRL por 1 USD, ex: 5.1023 = R$5,1023/USD). Backend calcula o BRL. Use quando a pessoa só tem a cotação estimada.
- Nunca passa só
amount_cents numa conta USD. Retorna 422.
- O que perguntar: "Gastou US$X em [conta USD] — sabe quanto saiu em reais, ou prefere estimar com uma cotação?"
- Câmbio é uma operação atômica via
fin_cambio. Cria 2 transações vinculadas (uma despesa na origem, uma receita no destino), ambas com categoria "Câmbio" e um exchange_pair_id compartilhado. Se uma falhar, a outra é desfeita.
- O FIN nunca usa cotação automática ao gravar. Nem em
fin_cambio, nem em fin_criar_despesa USD. A pessoa informa valores manualmente porque a taxa real varia (spot da fintech ≠ casa de câmbio ≠ banco). Exceção: fin_patrimonio converte USD→BRL dinamicamente só na leitura pra responder "quanto eu tenho hoje em reais" — pergunta de balance, não de transação.
fin_ajustar_saldo_conta retorna balance_cents_calculado direto na resposta. Você passa o saldo absoluto desejado e confere no retorno se bateu. Se não bateu, investiga (tem tx faltando/sobrando).
- Câmbio só funciona entre 2 contas cash de moedas diferentes (uma BRL, outra USD). Cartão de crédito não é suportado.
- Cartão de crédito em USD não é suportado no v0.
Caso A — Câmbio (vender ou comprar dólar)
Padrões de fala:
- "Vendi $100 e veio R$540" → vender USD (USD → BRL)
- "Comprei $50 por R$280" → comprar USD (BRL → USD)
- "Cambiei R$1000 em $185" → comprar USD
- "Troquei $200 e veio R$1080" → vender USD
Fluxo:
- Identifica direção (vender = USD→BRL, comprar = BRL→USD)
- Identifica as duas contas (
from_account_name, to_account_name):
- Vender: from = conta USD da pessoa, to = conta BRL
- Comprar: from = conta BRL, to = conta USD
- Se a pessoa não disser explicitamente qual conta, lê
Contas e Cartões.md e pergunta se houver mais de uma opção
- Captura as duas quantias (em centavos da moeda de cada conta):
amount_from_cents = quanto sai da origem
amount_to_cents = quanto entra no destino
- Se a pessoa só falou uma das duas (ex: "vendi $100" sem dizer quanto recebeu), pergunta a outra: "Vendeu $100 — quanto veio em reais?"
- Confirma em uma linha (use os nomes reais das contas da pessoa):
Câmbio: vender US$100 → R$540 / [conta USD] → [conta BRL] / hoje. Confirma?
- Chama
fin_cambio com os campos correspondentes (from_account_name, to_account_name, amount_from_cents, amount_to_cents, description).
- Sucesso: avisa que criou as 2 transações vinculadas em "Câmbio".
Avisos importantes:
- Nunca invente cotação. Se a pessoa só sabe uma das duas quantias, pergunta a outra. Não calcula.
- Confere a categoria "Câmbio" existe (criada automaticamente no primeiro uso pelo FIN, mas tu pode ver via
fin_listar_categorias)
- Não funciona com cartão de crédito — se a pessoa tentar câmbio envolvendo cartão, avisa e oferece operar conta cash equivalente
Caso B — Ajustar saldo manualmente (USD ou BRL)
fin_ajustar_saldo_conta retorna balance_cents_calculado e delta_liquido_cents direto na resposta. Você passa o saldo absoluto que a pessoa quer ver e confere no retorno.
Armadilha conceitual: a tool sobrescreve initial_balance, não o saldo exibido. Mas o backend calcula o saldo pós-ajuste e devolve. Se balance_cents_calculado não bater com o desejado, investiga — tem tx faltando/sobrando.
Padrões de fala:
- "Tô com $500 na carteira agora" → ajuste pra valor exibido final = $500
- "Agora tenho $1200 em [conta USD]" → ajuste pra $1200
- "Achei mais $50, total tá em $550" → ajuste pra $550
- "Ajusta a [conta] pra 1234,56" → ajuste pra R$1234,56
- "O saldo do [conta] tá errado, tá em R$2000 e devia ser R$2150" → ajuste pra R$2150
Fluxo simplificado (vale pra BRL e USD):
- Identifica a conta.
- Confirma com a pessoa em uma linha:
Ajustar saldo: [conta USD] → $500. Confirma?
- Chama
fin_ajustar_saldo_conta passando o saldo desejado em centavos da moeda da conta.
- Valida pelo retorno da tool: confere que
balance_cents_calculado bate com o desejado.
- Se bateu: avisa o saldo novo e segue.
- Se não bateu: a tool aceitou mas o saldo exibido ficou diferente porque a conta tem transações que fazem o cálculo
initial_balance + Σ(tx) não dar no valor que a pessoa quer. Não tenta de novo — explica pra pessoa e investiga (provavelmente tem tx faltando ou sobrando no FIN).
Se precisar de valor "delta" (ex: "achei mais $50" sem dizer total):
- Lê
fin_saldos pra pegar o saldo exibido atual.
- Calcula
saldo_desejado = atual + 50.
- Segue fluxo acima.
Gasto em USD não é caso de ajuste de saldo — use fin_criar_despesa direto com original_amount_cents + original_currency: "USD". Ver regra de negócio #1 acima.
Caso C — Ajustar saldo BRL pra correção
Mesmo fluxo do Caso B — fin_ajustar_saldo_conta funciona pra BRL igualzinho.
"Ajusta o saldo da [conta] pra R$1234,56"
- Confirma: Ajustar saldo: [conta] → R$1234,56. Confirma?
- Chama
fin_ajustar_saldo_conta com amount_cents: 123456.
- Confere
balance_cents_calculado no retorno.
Atenção: ajuste de saldo não cria transação, então não aparece em relatórios mensais como movimentação. É um ajuste contábil. Se a pessoa quiser que apareça como receita/despesa categorizada, oriente a usar fin_criar_receita/fin_criar_despesa.
Quando pedir leitura prévia de saldo
Você precisa ler o saldo atual ANTES do ajuste em 2 situações:
- Delta: "achei mais $50", "tirei $30", "somou X" — você precisa do saldo pra calcular o absoluto
- Confirmação visual: sempre que for útil mostrar antes/depois pra pessoa confirmar (basicamente sempre)
Use fin_saldos ou fin_listar_contas (a tool retorna os saldos junto com as contas).
Passo 5 — Aplicar regras de Estabelecimentos.md
Lê Estabelecimentos.md. Pra cada estabelecimento mencionado:
Se tem regra cadastrada:
- Aplica direto a categoria/subcategoria
- Mostra explicitamente: "apliquei tua regra: mercado → Alimentação > Mercado"
Se NÃO tem regra cadastrada:
- Pergunta a categoria: "Mercado vai em qual categoria? Ex: Alimentação > Mercado"
- Aceita a resposta e prepara pra aprender (vai gravar no fim)
Se tem regra mas a pessoa quer mudar dessa vez:
- Aceita a mudança pra essa transação específica
- Pergunta: "Isso é uma exceção dessa vez ou tu quer atualizar a regra pra todas as próximas?" — não atualiza a regra sem confirmação explícita
Passo 6 — Validar conta/cartão
Lê Contas e Cartões.md. Pra cada conta/cartão mencionado:
Se existe: segue.
Se NÃO existe:
- Pergunta: "Não tenho [conta] cadastrado. Quer que eu crie agora?"
- Se sim, faz
fin_criar_conta (com tipo, dados básicos), atualiza Contas e Cartões.md
- Se não, pede pra pessoa escolher uma conta existente da lista
Passo 7 — Confirmação em uma linha
Antes de qualquer mutação no FIN, sempre confirma em uma linha.
Formato (use os nomes reais das contas/cartões da pessoa):
Despesa R$45 / Mercado / Alimentação > Mercado / [conta] débito / hoje. Confirma?
Receita R$4000 / Cliente X / Trabalho > Avulsos / [conta] / hoje. Confirma?
Transferência R$500 / [conta A] → [conta B] / hoje. Confirma?
Saque R$200 / [conta] → dinheiro vivo (transferência) / hoje. Confirma?
A pessoa responde sim/não/ajuste. Se ajuste, ajusta e re-confirma.
Passo 8 — Executar no FIN
Conforme o tipo:
| Tipo | Tool |
|---|
| Despesa BRL | fin_criar_despesa |
| Despesa USD (categorizada) | fin_criar_despesa com original_amount_cents + original_currency: "USD" |
| Receita BRL ou USD | fin_criar_receita (mesma lógica multi-moeda) |
| Transferência (incluindo saque) | fin_criar_transferencia |
| Câmbio (vender ou comprar dólar) | fin_cambio |
| Ajuste de saldo (BRL ou USD) | fin_ajustar_saldo_conta |
| Estorno de cartão (já sabe o ID da original) | fin_criar_estorno |
| "Quanto eu tenho no total em reais?" | fin_patrimonio |
Confere se a tool executou OK. Se erro, mostra mensagem clara e tenta uma vez mais ou pergunta como proceder.
Passo 9 — Atualizar memória .md
Depois do lançamento bem-sucedido:
Se aprendeu um estabelecimento novo (não tava em Estabelecimentos.md):
Se a pessoa fez uma escolha não-óbvia (categorizou algo de um jeito que diverge da regra anterior, ou explicitou "isso aqui sempre vai em Y porque..."):
- Adiciona em
Preferências.md > Decisões não-óbvias
Se a pessoa criou conta/cartão novo:
- Adiciona em
Contas e Cartões.md
Passo 10 — Resposta final
Curta, direta:
✓ Lançado. R$45 em Mercado / Alimentação > Mercado / [conta] débito.
Aprendi: "mercado xyz" → Alimentação > Mercado.
Sem floreio. Pessoa quer saber que deu certo e seguir.
Casos especiais
Bills (recorrentes)
Se a pessoa lançar algo que parece gasto recorrente (luz, água, internet, aluguel, condomínio, plano de celular), depois de lançar pergunta uma vez:
Esse gasto é recorrente? Se for, posso transformar em "bill" no FIN pra ele aparecer todo mês automaticamente.
Se sim, cria via fin_criar_bill. Se não, segue com a despesa avulsa normal.
Não pergunta toda vez. Só na primeira ocorrência de cada estabelecimento. Depois que virou bill, lança automaticamente nas próximas.
Parcelamento
Se a pessoa disser "parcelado em N vezes" ou "X parcelas":
- O FIN tem suporte nativo a parcelamento. Passa
installments: N em fin_criar_despesa.
- NÃO crie N transações manualmente. O FIN gera as parcelas automaticamente.
- Confirmação especial (use os nomes reais):
Despesa R$1200 em 12x de R$100 / [merchant] / [Categoria] > [Sub] / [cartão] crédito. Primeira parcela cai na fatura que fecha em [data]. Confirma?
Parcelamento retroativo (compra antiga já em andamento):
"Comprei [coisa] em [mês passado] em N vezes, tô na X parcela agora"
O caminho intuitivo é passar original_purchase_date + installments + current_installment:
{
"description": "[merchant]",
"amount_cents": [valor TOTAL da compra em centavos],
"installments": [N total de parcelas],
"current_installment": [parcela em que a pessoa está],
"original_purchase_date": "[data REAL da compra original, YYYY-MM-DD]",
"account_name": "[nome do cartão]",
"category_name": "[Categoria]",
"subcategory_name": "[Sub]"
}
O backend lê o cutoff do cartão e calcula em qual fatura cada parcela (X, X+1, ..., N) cai. Sem precisar pensar em tx_date nem em invoice_cycle_end. Esse é o caminho preferido.
O workaround antigo (lançar cada parcela avulsa numerada manualmente com invoice_cycle_end forçado) ainda funciona mas fica como fallback — use só se original_purchase_date não conseguir resolver por algum motivo específico.
Estorno
Se a pessoa disser "foi estornado" ou "veio estorno de X":
- Estorno NÃO é receita. No banco vira despesa vinculada à original (coluna
reversal_of_id), mas a única forma de criar é via fin_criar_estorno — a rota fin_criar_despesa não aceita mais reversal_of_id no body (retorna 400).
- Se você já sabe o UUID da original (achou via
fin_buscar_transacoes ou fin_fatura_transacoes), usa fin_criar_estorno — tool atômica que valida ownership + 7 invariants e herda account/category/subcategory da original automaticamente. Só precisa passar original_transaction_id + amount_cents.
- Fluxo:
- Busca a original com
fin_buscar_transacoes (valor + estabelecimento próximos, janela de 3 meses).
- Mostra: "Achei a despesa original (R$100, Lojas X, dia Y). Vou criar o estorno apontando pra ela. Confirma?"
- Chama
fin_criar_estorno({original_transaction_id: "...", amount_cents: 10000}). Pode ser parcial.
- Se não achar a original, pergunta detalhes antes.
Múltiplas formas de pagamento na mesma transação
Tipo: "paguei 50 no PIX e 30 em dinheiro no almoço".
→ São 2 transações separadas. Lança uma de cada vez, mas confirma as duas juntas:
Vou lançar 2 despesas:
- R$50 / Restaurante / Alimentação > Restaurante / [conta PIX] / hoje
- R$30 / Restaurante / Alimentação > Restaurante / Dinheiro / hoje
Confirma as duas?
Data não-padrão
Se a pessoa mencionar data ("ontem", "anteontem", "dia 5", "10 de março"), parse pra ISO (YYYY-MM-DD) e usa no data da transação. Pra "hoje" (default), usa data atual.
Pra "essa semana" / "mês passado" / coisas vagas → pergunta o dia exato.
Pix em fim de semana / feriado (regra D+1 útil — opcional)
Use essa regra só se a pessoa concilia extrato com frequência. Pra quem só lança soltando data atual, o impacto é nulo.
Pix feito em sábado, domingo ou feriado costuma ser creditado no extrato bancário com data D+1 útil (convenção bancária brasileira). Exemplo: Pix feito sábado vai com data de crédito segunda.
Quando aplicar:
- Se a pessoa falar "acabei de fazer um Pix" num sábado/domingo/feriado e tem hábito de conciliar com extrato → lança com a data do próximo dia útil, não a data de hoje. Garante que bate com o extrato quando conciliar.
- Confirmação na linha deve deixar explícita: "...data [próximo dia útil] (padrão Pix fim de semana). Confirma?"
- Se a pessoa quiser lançar com a data real em que fez (sábado), ela pede explicitamente — e tu alerta que vai divergir do extrato.
Vale pra entradas também (Pix recebido sábado aparece no extrato segunda).
Regra não vale pra TED, débito automático, boleto — esses têm convenções próprias e o banco mostra a data certa.
Valor ambíguo
Se a pessoa não disser o valor claramente, pergunta. Não chuta.
Estabelecimento ambíguo
Se a pessoa disser só "lança um almoço" sem nome, pergunta:
Onde foi o almoço? (nome do lugar pra eu poder lembrar das próximas)
Se ela disser "qualquer lugar, sei lá", aceita "Almoço" como descrição genérica e categoriza em Alimentação > Restaurante (sem aprender estabelecimento).
Erros comuns que você deve evitar
- Lançar saque como despesa → saque é transferência banco → conta de dinheiro vivo
- Lançar estorno como receita → estorno em cartão é despesa. Use
fin_criar_estorno se já sabe o UUID da original.
- Criar parcelas manualmente → o FIN cria automático via
installments. Pra compra antiga em andamento (parcela X/N com X > 1), passa original_purchase_date junto.
- Aplicar regra aprendida sem mostrar → sempre diz "apliquei tua regra: X → Y"
- Atualizar regra existente sem confirmar → se a pessoa categorizou diferente dessa vez, pergunta se é exceção ou nova regra
- Aprender estabelecimento depois de uma única ocorrência sem confirmação → sempre confirma a categoria antes de gravar
- Não confirmar antes de criar → toda mutação tem confirmação em uma linha
- Encher linguiça → resposta é curta. "✓ Lançado. [resumo]" e fim.
- Esquecer de atualizar
Estabelecimentos.md → toda transação com estabelecimento novo gera linha nova
- Passar só
amount_cents numa conta USD → exige original_amount_cents + original_currency: "USD". Ver Passo 4.5.
- Inventar cotação no câmbio → o FIN não usa cotação automática. Se a pessoa só falou uma das duas quantias, pergunta a outra.
- Lançar câmbio como 2 transferências separadas → câmbio é
fin_cambio (atômico, 1 chamada).
- Tentar câmbio com cartão de crédito → só funciona entre 2 contas cash de moedas diferentes.
Tom
PT-BR informal, direto. Sem travessão (—). Resposta curta, ação rápida.