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.
- kotsu_cli-0.1.0/.github/workflows/publicar.yml +39 -0
- kotsu_cli-0.1.0/.github/workflows/verificar.yml +23 -0
- kotsu_cli-0.1.0/.gitignore +33 -0
- kotsu_cli-0.1.0/AGENTS.md +91 -0
- kotsu_cli-0.1.0/LICENSE +21 -0
- kotsu_cli-0.1.0/PKG-INFO +252 -0
- kotsu_cli-0.1.0/README.md +228 -0
- kotsu_cli-0.1.0/README.pt-BR.md +226 -0
- kotsu_cli-0.1.0/docs/imagens/FONTES.md +5 -0
- kotsu_cli-0.1.0/docs/imagens/banner.en.svg +49 -0
- kotsu_cli-0.1.0/docs/imagens/banner.svg +49 -0
- kotsu_cli-0.1.0/docs/imagens/divisor.svg +26 -0
- kotsu_cli-0.1.0/docs/imagens/icones/backup.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/dados.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/dev.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/estrutura.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/instalar.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/lancar.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/licenca.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/parcelas.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/privado.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/teclado.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/temas.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/icones/todomes.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/stack/claude.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/stack/githubactions.svg +6 -0
- kotsu_cli-0.1.0/docs/imagens/stack/python.svg +6 -0
- kotsu_cli-0.1.0/ferramentas/camadas.py +118 -0
- kotsu_cli-0.1.0/ferramentas/gerar_vetores.py +595 -0
- kotsu_cli-0.1.0/ferramentas/testar_instalacao.py +102 -0
- kotsu_cli-0.1.0/ferramentas/verificar.py +51 -0
- kotsu_cli-0.1.0/instalar.ps1 +45 -0
- kotsu_cli-0.1.0/instalar.sh +39 -0
- kotsu_cli-0.1.0/pyproject.toml +52 -0
- kotsu_cli-0.1.0/src/money_cli/__init__.py +3 -0
- kotsu_cli-0.1.0/src/money_cli/__main__.py +197 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/__init__.py +4 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/backup.py +70 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/banco.py +525 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/caminhos.py +72 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/migracoes/0001_inicial.sql +35 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/migracoes/0002_recorrencia.sql +21 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/migracoes/0003_mesclagem.sql +54 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/migracoes/__init__.py +32 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/preferencias.py +31 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/trava.py +123 -0
- kotsu_cli-0.1.0/src/money_cli/armazenamento/troca.py +285 -0
- kotsu_cli-0.1.0/src/money_cli/dominio/__init__.py +5 -0
- kotsu_cli-0.1.0/src/money_cli/dominio/dinheiro.py +10 -0
- kotsu_cli-0.1.0/src/money_cli/dominio/filtro.py +63 -0
- kotsu_cli-0.1.0/src/money_cli/dominio/linha.py +179 -0
- kotsu_cli-0.1.0/src/money_cli/dominio/mes.py +57 -0
- kotsu_cli-0.1.0/src/money_cli/dominio/mescla.py +440 -0
- kotsu_cli-0.1.0/src/money_cli/dominio/parcelas.py +52 -0
- kotsu_cli-0.1.0/src/money_cli/dominio/recorrencia.py +20 -0
- kotsu_cli-0.1.0/src/money_cli/dominio/tipos.py +95 -0
- kotsu_cli-0.1.0/src/money_cli/dominio/totais.py +17 -0
- kotsu_cli-0.1.0/src/money_cli/tela/__init__.py +1 -0
- kotsu_cli-0.1.0/src/money_cli/tela/app.py +756 -0
- kotsu_cli-0.1.0/src/money_cli/tela/cores.py +31 -0
- kotsu_cli-0.1.0/src/money_cli/tela/perguntas.py +144 -0
- kotsu_cli-0.1.0/src/money_cli/tela/temas.py +74 -0
- kotsu_cli-0.1.0/tests/conftest.py +16 -0
- kotsu_cli-0.1.0/tests/test_armazenamento.py +151 -0
- kotsu_cli-0.1.0/tests/test_backup.py +103 -0
- kotsu_cli-0.1.0/tests/test_camadas.py +46 -0
- kotsu_cli-0.1.0/tests/test_desempenho_m2.py +77 -0
- kotsu_cli-0.1.0/tests/test_dominio.py +81 -0
- kotsu_cli-0.1.0/tests/test_lancar.py +92 -0
- kotsu_cli-0.1.0/tests/test_linha.py +158 -0
- kotsu_cli-0.1.0/tests/test_m2_dominio.py +145 -0
- kotsu_cli-0.1.0/tests/test_recorrencia.py +185 -0
- kotsu_cli-0.1.0/tests/test_sincronia.py +133 -0
- kotsu_cli-0.1.0/tests/test_tela.py +68 -0
- kotsu_cli-0.1.0/tests/test_tela_lancar.py +183 -0
- kotsu_cli-0.1.0/tests/test_tela_m2.py +238 -0
- kotsu_cli-0.1.0/tests/test_temas.py +96 -0
- kotsu_cli-0.1.0/tests/test_troca.py +560 -0
- kotsu_cli-0.1.0/vetores/carimbo.json +44 -0
- kotsu_cli-0.1.0/vetores/datas.json +350 -0
- kotsu_cli-0.1.0/vetores/dinheiro.json +54 -0
- kotsu_cli-0.1.0/vetores/invalidos.json +674 -0
- kotsu_cli-0.1.0/vetores/linha.json +405 -0
- 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.
|
kotsu_cli-0.1.0/LICENSE
ADDED
|
@@ -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.
|
kotsu_cli-0.1.0/PKG-INFO
ADDED
|
@@ -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>
|