kotsu-cli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. kotsu_cli-0.1.0/.github/workflows/publicar.yml +39 -0
  2. kotsu_cli-0.1.0/.github/workflows/verificar.yml +23 -0
  3. kotsu_cli-0.1.0/.gitignore +33 -0
  4. kotsu_cli-0.1.0/AGENTS.md +91 -0
  5. kotsu_cli-0.1.0/LICENSE +21 -0
  6. kotsu_cli-0.1.0/PKG-INFO +252 -0
  7. kotsu_cli-0.1.0/README.md +228 -0
  8. kotsu_cli-0.1.0/README.pt-BR.md +226 -0
  9. kotsu_cli-0.1.0/docs/imagens/FONTES.md +5 -0
  10. kotsu_cli-0.1.0/docs/imagens/banner.en.svg +49 -0
  11. kotsu_cli-0.1.0/docs/imagens/banner.svg +49 -0
  12. kotsu_cli-0.1.0/docs/imagens/divisor.svg +26 -0
  13. kotsu_cli-0.1.0/docs/imagens/icones/backup.svg +6 -0
  14. kotsu_cli-0.1.0/docs/imagens/icones/dados.svg +6 -0
  15. kotsu_cli-0.1.0/docs/imagens/icones/dev.svg +6 -0
  16. kotsu_cli-0.1.0/docs/imagens/icones/estrutura.svg +6 -0
  17. kotsu_cli-0.1.0/docs/imagens/icones/instalar.svg +6 -0
  18. kotsu_cli-0.1.0/docs/imagens/icones/lancar.svg +6 -0
  19. kotsu_cli-0.1.0/docs/imagens/icones/licenca.svg +6 -0
  20. kotsu_cli-0.1.0/docs/imagens/icones/parcelas.svg +6 -0
  21. kotsu_cli-0.1.0/docs/imagens/icones/privado.svg +6 -0
  22. kotsu_cli-0.1.0/docs/imagens/icones/teclado.svg +6 -0
  23. kotsu_cli-0.1.0/docs/imagens/icones/temas.svg +6 -0
  24. kotsu_cli-0.1.0/docs/imagens/icones/todomes.svg +6 -0
  25. kotsu_cli-0.1.0/docs/imagens/stack/claude.svg +6 -0
  26. kotsu_cli-0.1.0/docs/imagens/stack/githubactions.svg +6 -0
  27. kotsu_cli-0.1.0/docs/imagens/stack/python.svg +6 -0
  28. kotsu_cli-0.1.0/ferramentas/camadas.py +118 -0
  29. kotsu_cli-0.1.0/ferramentas/gerar_vetores.py +595 -0
  30. kotsu_cli-0.1.0/ferramentas/testar_instalacao.py +102 -0
  31. kotsu_cli-0.1.0/ferramentas/verificar.py +51 -0
  32. kotsu_cli-0.1.0/instalar.ps1 +45 -0
  33. kotsu_cli-0.1.0/instalar.sh +39 -0
  34. kotsu_cli-0.1.0/pyproject.toml +52 -0
  35. kotsu_cli-0.1.0/src/money_cli/__init__.py +3 -0
  36. kotsu_cli-0.1.0/src/money_cli/__main__.py +197 -0
  37. kotsu_cli-0.1.0/src/money_cli/armazenamento/__init__.py +4 -0
  38. kotsu_cli-0.1.0/src/money_cli/armazenamento/backup.py +70 -0
  39. kotsu_cli-0.1.0/src/money_cli/armazenamento/banco.py +525 -0
  40. kotsu_cli-0.1.0/src/money_cli/armazenamento/caminhos.py +72 -0
  41. kotsu_cli-0.1.0/src/money_cli/armazenamento/migracoes/0001_inicial.sql +35 -0
  42. kotsu_cli-0.1.0/src/money_cli/armazenamento/migracoes/0002_recorrencia.sql +21 -0
  43. kotsu_cli-0.1.0/src/money_cli/armazenamento/migracoes/0003_mesclagem.sql +54 -0
  44. kotsu_cli-0.1.0/src/money_cli/armazenamento/migracoes/__init__.py +32 -0
  45. kotsu_cli-0.1.0/src/money_cli/armazenamento/preferencias.py +31 -0
  46. kotsu_cli-0.1.0/src/money_cli/armazenamento/trava.py +123 -0
  47. kotsu_cli-0.1.0/src/money_cli/armazenamento/troca.py +285 -0
  48. kotsu_cli-0.1.0/src/money_cli/dominio/__init__.py +5 -0
  49. kotsu_cli-0.1.0/src/money_cli/dominio/dinheiro.py +10 -0
  50. kotsu_cli-0.1.0/src/money_cli/dominio/filtro.py +63 -0
  51. kotsu_cli-0.1.0/src/money_cli/dominio/linha.py +179 -0
  52. kotsu_cli-0.1.0/src/money_cli/dominio/mes.py +57 -0
  53. kotsu_cli-0.1.0/src/money_cli/dominio/mescla.py +440 -0
  54. kotsu_cli-0.1.0/src/money_cli/dominio/parcelas.py +52 -0
  55. kotsu_cli-0.1.0/src/money_cli/dominio/recorrencia.py +20 -0
  56. kotsu_cli-0.1.0/src/money_cli/dominio/tipos.py +95 -0
  57. kotsu_cli-0.1.0/src/money_cli/dominio/totais.py +17 -0
  58. kotsu_cli-0.1.0/src/money_cli/tela/__init__.py +1 -0
  59. kotsu_cli-0.1.0/src/money_cli/tela/app.py +756 -0
  60. kotsu_cli-0.1.0/src/money_cli/tela/cores.py +31 -0
  61. kotsu_cli-0.1.0/src/money_cli/tela/perguntas.py +144 -0
  62. kotsu_cli-0.1.0/src/money_cli/tela/temas.py +74 -0
  63. kotsu_cli-0.1.0/tests/conftest.py +16 -0
  64. kotsu_cli-0.1.0/tests/test_armazenamento.py +151 -0
  65. kotsu_cli-0.1.0/tests/test_backup.py +103 -0
  66. kotsu_cli-0.1.0/tests/test_camadas.py +46 -0
  67. kotsu_cli-0.1.0/tests/test_desempenho_m2.py +77 -0
  68. kotsu_cli-0.1.0/tests/test_dominio.py +81 -0
  69. kotsu_cli-0.1.0/tests/test_lancar.py +92 -0
  70. kotsu_cli-0.1.0/tests/test_linha.py +158 -0
  71. kotsu_cli-0.1.0/tests/test_m2_dominio.py +145 -0
  72. kotsu_cli-0.1.0/tests/test_recorrencia.py +185 -0
  73. kotsu_cli-0.1.0/tests/test_sincronia.py +133 -0
  74. kotsu_cli-0.1.0/tests/test_tela.py +68 -0
  75. kotsu_cli-0.1.0/tests/test_tela_lancar.py +183 -0
  76. kotsu_cli-0.1.0/tests/test_tela_m2.py +238 -0
  77. kotsu_cli-0.1.0/tests/test_temas.py +96 -0
  78. kotsu_cli-0.1.0/tests/test_troca.py +560 -0
  79. kotsu_cli-0.1.0/vetores/carimbo.json +44 -0
  80. kotsu_cli-0.1.0/vetores/datas.json +350 -0
  81. kotsu_cli-0.1.0/vetores/dinheiro.json +54 -0
  82. kotsu_cli-0.1.0/vetores/invalidos.json +674 -0
  83. kotsu_cli-0.1.0/vetores/linha.json +405 -0
  84. kotsu_cli-0.1.0/vetores/mescla.json +1948 -0
@@ -0,0 +1,39 @@
1
+ name: publicar
2
+
3
+ # Publica no PyPI quando uma tag v* (ex.: v0.1.0) é enviada. Usa Trusted Publishing: sem token.
4
+ on:
5
+ push:
6
+ tags: ["v*"]
7
+
8
+ jobs:
9
+ construir:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.12"
16
+ - name: Confere a versão da tag
17
+ run: |
18
+ v=$(python -c "import tomllib;print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
19
+ test "v$v" = "$GITHUB_REF_NAME" || { echo "tag $GITHUB_REF_NAME != versão $v"; exit 1; }
20
+ - run: pip install -e ".[dev]" build
21
+ - run: python ferramentas/verificar.py
22
+ - run: python -m build
23
+ - uses: actions/upload-artifact@v4
24
+ with:
25
+ name: dist
26
+ path: dist/
27
+
28
+ publicar:
29
+ needs: construir
30
+ runs-on: ubuntu-latest
31
+ environment: pypi
32
+ permissions:
33
+ id-token: write
34
+ steps:
35
+ - uses: actions/download-artifact@v4
36
+ with:
37
+ name: dist
38
+ path: dist/
39
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,23 @@
1
+ name: verificar
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ verificar:
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ os: [windows-latest, ubuntu-latest]
13
+ python: ["3.11", "3.13"]
14
+ runs-on: ${{ matrix.os }}
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ matrix.python }}
20
+ - run: python -m pip install -e ".[dev]"
21
+ - run: python ferramentas/verificar.py
22
+ - run: python -m pip install pipx
23
+ - run: python ferramentas/testar_instalacao.py
@@ -0,0 +1,33 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ build/
6
+ dist/
7
+ .venv/
8
+ venv/
9
+
10
+ # Ferramentas
11
+ .pytest_cache/
12
+ .ruff_cache/
13
+ .coverage
14
+ htmlcov/
15
+
16
+ # Dados pessoais: nunca versionar bancos, backups ou exports
17
+ *.sqlite
18
+ *.sqlite3
19
+ *.sqlite-*
20
+ *.sqlite3-*
21
+ *.db
22
+ *.db-journal
23
+ *.db-wal
24
+ *.db-shm
25
+ backups/
26
+ *.csv
27
+ .env
28
+
29
+ # Editores e sistema
30
+ .vscode/
31
+ .idea/
32
+ .DS_Store
33
+ Thumbs.db
@@ -0,0 +1,91 @@
1
+ # AGENTS.md
2
+
3
+ Guia para quem mexe neste repositório, pessoa ou agente. Leia antes de mudar código.
4
+
5
+ ## O que é
6
+
7
+ Kotsu (pacote `kotsu-cli`): app de terminal (Python + Textual) para receitas, despesas, categorias,
8
+ contas e parcelas do mês. Alvo principal: Windows Terminal,
9
+ funcionando igual no Linux.
10
+
11
+ ## Comandos
12
+
13
+ ```bash
14
+ pip install -e ".[dev]"
15
+ money --dados ./tmp # abre o app com uma pasta de teste
16
+ python ferramentas/verificar.py --rapido # antes de cada commit
17
+ python ferramentas/verificar.py # antes de cada PR (igual à CI)
18
+ python ferramentas/camadas.py # só a regra de camadas
19
+ python ferramentas/testar_instalacao.py # pipx instalado; usa rede só na instalação
20
+ python ferramentas/gerar_vetores.py # regrava vetores/*.json (casos do Android)
21
+ ```
22
+
23
+ ## Camadas (o teste falha se forem violadas)
24
+
25
+ | Pasta | Pode importar | Não pode |
26
+ |---|---|---|
27
+ | `src/money_cli/dominio/` | só biblioteca padrão sem I/O | `armazenamento`, `tela`, `sqlite3`, `os`, `pathlib`, `io`, Textual, Rich |
28
+ | `src/money_cli/armazenamento/` | `dominio` | `tela`, Textual, Rich |
29
+ | `src/money_cli/tela/` | `dominio`, `armazenamento` | `sqlite3` direto |
30
+
31
+ `src/money_cli/__main__.py` é o ponto de montagem e pode ver tudo.
32
+ Regra financeira (totais, parcelas, parser da linha rápida) mora em `dominio/`; a tela só mostra.
33
+
34
+ ## Regras de dados
35
+
36
+ - Dinheiro é `int` em centavos, sempre positivo; o sinal vem do `tipo` (receita/despesa).
37
+ Nunca `float`.
38
+ - Todo lançamento tem conta (D21): o domínio e o banco recusam lançamento sem conta.
39
+ Categoria é opcional.
40
+ - Datas são civis (`datetime.date`), sem fuso, gravadas como `AAAA-MM-DD`.
41
+ - Totais (receitas, despesas, saldo) nunca são gravados: o SQL calcula por mês.
42
+ - Consultas por mês usam faixa `data >= início AND data < fim` para usar o índice.
43
+ Listas são paginadas (`limite`, `desde`).
44
+ - Na tela, valor negativo aparece só em vermelho, sem sinal (`dominio.dinheiro.formatar`).
45
+
46
+ ## Banco e migrações
47
+
48
+ - Toda escrita passa por `Banco.transacao()`: grava tudo ou nada. Parcelas de uma compra
49
+ entram numa transação só.
50
+ - Mudou o esquema? Crie `src/money_cli/armazenamento/migracoes/NNNN_nome.sql` com o próximo
51
+ número. Nunca edite uma migração já publicada. Antes de migrar um banco existente, o app
52
+ copia o arquivo para `money.antes-vN.sqlite`.
53
+ - Teste toda migração nova com um banco na versão anterior.
54
+ - Recorrência (D36): categoria `recorrente` + tabela `recorrencia` (modelo da série e
55
+ `gerada_ate`). `Banco.estender_recorrencias(mes)` gera os meses que faltam e só avança, por
56
+ isso mês excluído não volta. A tela chama isso ao desenhar, limitada a hoje + 24 meses.
57
+ - Backup é só manual (D35): a tecla `b` copia o banco para `backups/` com data e hora no
58
+ nome, sem sobrescrever, e mantém só as 5 mais recentes (poda depois de publicar). O app não faz backup sozinho. Teste relógio e
59
+ falhas com dados temporários. Memória (`Banco.em_memoria()`) não cria backup.
60
+
61
+ ## Troca entre aparelhos (D39)
62
+
63
+ - Cada aparelho tem o próprio banco; os dados se juntam por arquivo de troca
64
+ (`--exportar`, `--importar`, `--conferir`). A regra de mesclagem é pura e mora em
65
+ `dominio/mescla.py`; ler, gravar e aplicar ficam em `armazenamento/troca.py`.
66
+ - Toda escrita em `conta`, `categoria`, `lancamento` e no modelo de `recorrencia` carimba
67
+ `alterado_em` com `Banco.carimbar(c)` (um carimbo por transação). Editar um lançamento
68
+ zera `gerado`. Excluir lançamento grava a lápide antes do `DELETE`. Esqueceu o carimbo?
69
+ A alteração perde para o outro aparelho na mesclagem.
70
+ - Avançar `gerada_ate` não carimba: o mês gerado usa o `uid` fixo (`uid_do_mes`) e o
71
+ carimbo do modelo da série.
72
+ - Campo novo em tabela sincronizada entra em: migração, `troca.ler_estado`, `troca._aplicar`,
73
+ `mescla.validar`, a forma canônica (muda o código de conferência) e `FORMATO` se o arquivo
74
+ antigo deixar de servir.
75
+ - `vetores/*.json` são os casos compartilhados com o app Android. Mudou regra do domínio
76
+ (linha rápida, datas, dinheiro, carimbo, mesclagem)? Acrescente o caso em
77
+ `ferramentas/gerar_vetores.py`, rode-o e confira o diff do JSON. O teste falha se os
78
+ arquivos estiverem desatualizados.
79
+
80
+ ## Como trabalhar
81
+
82
+ - Nomes de código, mensagens e documentos em português.
83
+ - Decisão de produto nova ou alterada: descreva no PR e atualize o README no mesmo PR.
84
+ - Nada entra na `main` sem revisão. Trabalhe em branch e abra PR.
85
+ - Testes não usam rede nem a pasta de dados real (use `Banco.em_memoria()` ou `tmp_path`).
86
+ - README e este arquivo são atualizados no mesmo PR que muda o que eles descrevem.
87
+ - Paleta fixa em `tela/cores.py`; mude pouco e de propósito.
88
+ - Nunca versione bancos, backups ou exports (o `.gitignore` bloqueia SQLite e `*.csv`).
89
+ - Testes de instalação reais via pipx rodam fora do checkout na CI Windows/Linux;
90
+ dependem de rede só para instalar. Testes unitários continuam sem rede.
91
+ - Commits com o e-mail noreply do GitHub.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sera-DAI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,252 @@
1
+ Metadata-Version: 2.5
2
+ Name: kotsu-cli
3
+ Version: 0.1.0
4
+ Summary: Cozy personal finance in your terminal: income, expenses and installments of the month on one screen.
5
+ Project-URL: Homepage, https://github.com/Sera-DAI/kotsu
6
+ Project-URL: Issues, https://github.com/Sera-DAI/kotsu/issues
7
+ Project-URL: Português, https://github.com/Sera-DAI/kotsu/blob/main/README.pt-BR.md
8
+ Author: Sera-DAI
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: budget,finance,terminal,textual,tui
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: End Users/Desktop
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Office/Business :: Financial
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: textual<9,>=8.0
19
+ Provides-Extra: dev
20
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
21
+ Requires-Dist: pytest>=8; extra == 'dev'
22
+ Requires-Dist: ruff>=0.6; extra == 'dev'
23
+ Description-Content-Type: text/markdown
24
+
25
+ <p align="center">
26
+ <img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/banner.en.svg" alt="Kotsu: cozy personal finance in your terminal" width="100%">
27
+ </p>
28
+
29
+ <p align="center"><b>English</b> · <a href="https://github.com/Sera-DAI/kotsu/blob/main/README.pt-BR.md">Português (Brasil)</a></p>
30
+
31
+ <p align="center">
32
+ <img src="https://img.shields.io/badge/python-3.11%2B-ff7fb8?style=flat-square&labelColor=1d1424&logo=python&logoColor=ffe9f4" alt="Python 3.11+">
33
+ <img src="https://img.shields.io/badge/terminal-Windows%20%C2%B7%20Linux-ff7fb8?style=flat-square&labelColor=1d1424&logo=windowsterminal&logoColor=ffe9f4" alt="Windows Terminal and Linux">
34
+ <img src="https://img.shields.io/badge/data-only%20on%20your%20computer-ffa28c?style=flat-square&labelColor=1d1424&logo=sqlite&logoColor=ffe9f4" alt="Local data">
35
+ <img src="https://img.shields.io/badge/license-MIT-ffa28c?style=flat-square&labelColor=1d1424" alt="MIT license">
36
+ </p>
37
+
38
+ <p align="center">
39
+ <img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/stack/python.svg" width="44" alt="Python" title="Python">
40
+ <img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/stack/githubactions.svg" width="44" alt="GitHub Actions" title="GitHub Actions">
41
+ <img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/stack/claude.svg" width="44" alt="Claude" title="Claude">
42
+ </p>
43
+
44
+ <p align="center"><sub>Built with Python, Textual, SQLite and Claude</sub></p>
45
+
46
+ <p align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/divisor.svg" width="420" alt=""></p>
47
+
48
+ # Kotsu
49
+
50
+ **Kotsu** (コツコツ, *kotsukotsu*) is a Japanese word for "little by little, steadily". It is a terminal app for everyday money: income, expenses and the month's installments on a single screen, in a pink and salmon **Cotton Candy** look. No giant spreadsheet, no dashboard full of charts. You jot an entry on one line, see the whole month and get on with your day.
51
+
52
+ It runs on Windows Terminal and Linux, works offline and keeps everything in a SQLite file on your computer. No account, no cloud, no telemetry, no ads.
53
+
54
+ > The app interface is in Brazilian Portuguese for now (labels such as *receitas* = income, *despesas* = expenses, *saldo* = balance). The commands and keys below work the same in any language.
55
+
56
+ ## Contents
57
+
58
+ - [I. What it does](#i-what-it-does)
59
+ - [II. Install](#ii-install)
60
+ - [III. Use](#iii-use)
61
+ - [IV. Your data and backups](#iv-your-data-and-backups)
62
+ - [V. Under the hood](#v-under-the-hood)
63
+ - [VI. Development](#vi-development)
64
+ - [VII. License](#vii-license)
65
+
66
+ ## I. What it does
67
+
68
+ <table>
69
+ <tr>
70
+ <td width="72" align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/lancar.svg" width="44" alt=""></td>
71
+ <td><b>Quick line</b><br><code>89,90 mercado #alimentação @nubank</code> and Enter. No forms: the amount comes first, then account, category and date in any order.</td>
72
+ </tr>
73
+ <tr>
74
+ <td align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/parcelas.svg" width="44" alt=""></td>
75
+ <td><b>One screen</b><br>Income, expenses and balance for the month, one line per account (each with its own color) and the list of entries. The ← / → arrows switch months.</td>
76
+ </tr>
77
+ <tr>
78
+ <td align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/todomes.svg" width="44" alt=""></td>
79
+ <td><b>Installments and "every month"</b><br><code>120 geladeira @nubank 10x</code> becomes 10 installments, one per month. Categories marked "every month" (rent, internet, salary) show up on their own, with a <code>↻</code>.</td>
80
+ </tr>
81
+ <tr>
82
+ <td align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/temas.svg" width="44" alt=""></td>
83
+ <td><b>Two Cotton Candy themes</b><br>Night (default) and light, with hearts, a little face and "zzz… zerada" when an account is empty. The <code>t</code> key switches and your choice is saved.</td>
84
+ </tr>
85
+ <tr>
86
+ <td align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/teclado.svg" width="44" alt=""></td>
87
+ <td><b>Keyboard first</b><br>Everything has a key, and the footer reminds you which. Filter by <code>@account</code> or <code>#category</code> with <code>/</code>.</td>
88
+ </tr>
89
+ <tr>
90
+ <td align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/privado.svg" width="44" alt=""></td>
91
+ <td><b>Truly private</b><br>Your data stays on your computer. Kotsu never sends anything over the network.</td>
92
+ </tr>
93
+ </table>
94
+
95
+ ## II. Install
96
+
97
+ <table>
98
+ <tr>
99
+ <td width="72" align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/instalar.svg" width="44" alt=""></td>
100
+ <td>Requires Python 3.11 or newer and <a href="https://pipx.pypa.io/">pipx</a>. The package is not on PyPI yet: install straight from GitHub.</td>
101
+ </tr>
102
+ </table>
103
+
104
+ Windows Terminal (PowerShell), in one line:
105
+
106
+ ```powershell
107
+ irm https://raw.githubusercontent.com/Sera-DAI/kotsu/main/instalar.ps1 | iex
108
+ ```
109
+
110
+ Linux/macOS (needs pipx; the script tells you if it is missing):
111
+
112
+ ```bash
113
+ curl -fsSL https://raw.githubusercontent.com/Sera-DAI/kotsu/main/instalar.sh | bash
114
+ ```
115
+
116
+ Or step by step, without a script:
117
+
118
+ Windows Terminal (PowerShell):
119
+
120
+ ```powershell
121
+ py -m pip install --user pipx
122
+ py -m pipx ensurepath
123
+ py -m pipx install kotsu-cli
124
+ ```
125
+
126
+ Linux (Debian/Ubuntu):
127
+
128
+ ```bash
129
+ sudo apt install pipx
130
+ pipx ensurepath
131
+ pipx install kotsu-cli
132
+ ```
133
+
134
+ Reopen the terminal and run `kotsu`. To update: `pipx upgrade kotsu-cli` (or run the installer again). To remove: `pipx uninstall kotsu-cli` (your data stays in the data folder).
135
+
136
+ ## III. Use
137
+
138
+ ```text
139
+ ☁ Algodão-Doce ☁ novembro de 2026
140
+
141
+ ♡ receitas 3.500,00 ✧ despesas 432,90 ☆ saldo 3.067,10 (◕‿◕)♡
142
+
143
+ ♡ itaú ♥♥♥♥♥♥♥♥♥♥♥♥♥♥· -210,50 +3.500,00
144
+ ♡ nubank ♥♥♥♥♥♥♥♥♥♥♥♥♥♥ -222,40
145
+
146
+ Data Descrição Categoria Conta Valor
147
+ 08/11 padaria alimentação nubank 12,50
148
+ 07/11 mercado alimentação nubank 89,90
149
+ ```
150
+
151
+ | Key | Action |
152
+ |---|---|
153
+ | `l` | opens the quick line (Enter saves, Esc closes) |
154
+ | ← / → | previous / next month |
155
+ | `/` | filters by `@account`, `#category`, both, or just a name (empty Enter or Esc clears) |
156
+ | `e` | edits the selected entry in the quick line, date included |
157
+ | `c` | copies the selected entry into the quick line, dated today |
158
+ | `d` | deletes the selected entry (an installment asks "only this one or all?") |
159
+ | `r` | renames the selected entry |
160
+ | `m` | turns "every month" on/off for the selected entry's category |
161
+ | `b` | manual database backup (a new copy in `backups/`) |
162
+ | `t` | switches the theme (Cotton Candy night or light) |
163
+ | `v` | shows the check code (same on another device = same data) |
164
+ | `q` | quits |
165
+
166
+ The line starts with the amount; the rest comes in any order:
167
+
168
+ ```text
169
+ 89,90 mercado #alimentação @nubank expense (no sign)
170
+ +3500 salário @itaú income
171
+ 120 geladeira #casa @nubank 10x 10 installments of 120.00, one per month
172
+ 45 farmácia ontem date: ontem (yesterday), 15/10 or 15/10/2025 (default: today)
173
+ ```
174
+
175
+ Every entry needs an `@account`; without one the line is not saved. An account or category that does not exist yet asks whether to create it. Editing or renaming an installment asks "only this one or all?". Amounts use a decimal comma and dates are day/month, as in Brazil.
176
+
177
+ ### ↻ Categories that repeat every month
178
+
179
+ When you create a category, Kotsu asks whether it repeats every month (or press `m` on an existing one). Every new entry in it reappears each month with the same amount, account and day (day 31 becomes the last day of the month), with no end, until you stop it. Months appear as you navigate with ← / →, up to 24 months ahead of today. Deleting, editing or renaming one asks "only this month or the following ones?".
180
+
181
+ ## IV. Your data and backups
182
+
183
+ <table>
184
+ <tr>
185
+ <td width="72" align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/backup.svg" width="44" alt=""></td>
186
+ <td>
187
+ <ul>
188
+ <li><b>Where it lives:</b> <code>%APPDATA%\money-cli</code> on Windows and <code>~/.local/share/money-cli</code> on Linux (or the folder in the <code>MONEY_CLI_DADOS</code> variable). <code>kotsu --dados FOLDER</code> opens another folder.</li>
189
+ <li><b>Manual backup:</b> the <code>b</code> key creates <code>backups/money.YYYY-MM-DD-HHMMSS.sqlite</code> and keeps the 5 most recent copies. Kotsu never backs up on its own.</li>
190
+ <li><b>Using two computers (Google Drive):</b> on both, run <code>kotsu --pasta-dados "G:\My Drive\Kotsu"</code> (any existing data on the computer is copied there; if both already have data, choose which one wins). Keep the folder "Available offline". Use one computer at a time: Kotsu warns if it is open on the other one and refuses to open if Drive created conflicting copies (<code>--forcar</code> skips the warning). Backups from the <code>b</code> key stay in the local folder, outside Drive. <code>kotsu --pasta-dados-padrao</code> undoes it.</li>
191
+ <li><b>Merging with another device:</b> <code>kotsu --exportar data.json</code> writes everything to a file; on the other device, <code>kotsu --importar data.json</code> merges it with what is there (the most recent change to each entry wins, and deleted entries stay deleted). Do it both ways and check: <code>kotsu --conferir</code> shows a short code that is the same on both when the data is the same; <code>kotsu --conferir data.json</code> lists the differences. Before importing, Kotsu saves <code>backups/money.antes-da-troca.sqlite</code>.</li>
192
+ <li><b>No password or encryption:</b> protect your computer and the folder as you would any personal file.</li>
193
+ <li><b>Restore:</b> close the app, move the current <code>money.sqlite</code> elsewhere, copy the chosen backup to <code>money.sqlite</code>, open the app and check the totals.</li>
194
+ </ul>
195
+ </td>
196
+ </tr>
197
+ </table>
198
+
199
+ ## V. Under the hood
200
+
201
+ <table>
202
+ <tr>
203
+ <td width="72" align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/estrutura.svg" width="44" alt=""></td>
204
+ <td>Three layers, and a test fails if one of them imports what it must not. Financial rules (totals, installments, the quick-line parser) live in the domain; the screen only displays.</td>
205
+ </tr>
206
+ </table>
207
+
208
+ ```mermaid
209
+ %%{init: {"theme": "base", "themeVariables": {"primaryColor": "#41274f", "primaryTextColor": "#ffe9f4", "primaryBorderColor": "#ff7fb8", "lineColor": "#ffa28c", "secondaryColor": "#291b33", "tertiaryColor": "#1d1424", "fontFamily": "Segoe UI, sans-serif"}}}%%
210
+ flowchart LR
211
+ T["tela/<br>Textual: display only"] --> A["armazenamento/<br>SQLite, migrations, backup"]
212
+ T --> D["dominio/<br>money in cents,<br>installments, quick line"]
213
+ A --> D
214
+ A --> F[("money.sqlite<br>on your computer")]
215
+ ```
216
+
217
+ - Money is an integer number of cents, never a `float`; the sign comes from the type (income or expense).
218
+ - Every write is a transaction: all or nothing. Changed the schema? A numbered migration, with a copy of the database made first.
219
+ - Totals are never stored: SQL computes them per month.
220
+
221
+ Full contributor rules (in Portuguese): [AGENTS.md](AGENTS.md).
222
+
223
+ ## VI. Development
224
+
225
+ <table>
226
+ <tr>
227
+ <td width="72" align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/dev.svg" width="44" alt=""></td>
228
+ <td>Requires Python 3.11+. The tests never touch the network.</td>
229
+ </tr>
230
+ </table>
231
+
232
+ ```bash
233
+ git clone https://github.com/Sera-DAI/kotsu.git
234
+ cd kotsu
235
+ python -m venv .venv
236
+ # Windows: .venv\Scripts\activate Linux: source .venv/bin/activate
237
+ pip install -e ".[dev]"
238
+ kotsu --dados ./tmp # uses a test folder
239
+ python ferramentas/verificar.py --rapido # lint + fast tests
240
+ python ferramentas/verificar.py # everything, same as CI
241
+ ```
242
+
243
+ ## VII. License
244
+
245
+ <table>
246
+ <tr>
247
+ <td width="72" align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/icones/licenca.svg" width="44" alt=""></td>
248
+ <td><a href="https://github.com/Sera-DAI/kotsu/blob/main/LICENSE">MIT</a>. Made with care, little by little.</td>
249
+ </tr>
250
+ </table>
251
+
252
+ <p align="center"><img src="https://raw.githubusercontent.com/Sera-DAI/kotsu/main/docs/imagens/divisor.svg" width="420" alt=""></p>