leadger 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.
- leadger-0.1.0/.gitignore +19 -0
- leadger-0.1.0/CHANGELOG.md +57 -0
- leadger-0.1.0/LICENSE +21 -0
- leadger-0.1.0/PKG-INFO +215 -0
- leadger-0.1.0/README.md +183 -0
- leadger-0.1.0/frontend/README.md +73 -0
- leadger-0.1.0/pyproject.toml +47 -0
- leadger-0.1.0/src/leadger/__init__.py +1 -0
- leadger-0.1.0/src/leadger/__main__.py +5 -0
- leadger-0.1.0/src/leadger/cli.py +253 -0
- leadger-0.1.0/src/leadger/core/__init__.py +14 -0
- leadger-0.1.0/src/leadger/core/ics.py +82 -0
- leadger-0.1.0/src/leadger/core/ids.py +16 -0
- leadger-0.1.0/src/leadger/core/parse.py +79 -0
- leadger-0.1.0/src/leadger/core/periods.py +32 -0
- leadger-0.1.0/src/leadger/core/recur.py +45 -0
- leadger-0.1.0/src/leadger/core/storage.py +385 -0
- leadger-0.1.0/src/leadger/core/tasks.py +161 -0
- leadger-0.1.0/src/leadger/core/time_utils.py +43 -0
- leadger-0.1.0/src/leadger/core/yaml_io.py +97 -0
- leadger-0.1.0/src/leadger/server.py +221 -0
- leadger-0.1.0/src/leadger/static/assets/index-BFMiMAZM.css +2 -0
- leadger-0.1.0/src/leadger/static/assets/index-PnqahOsL.js +24 -0
- leadger-0.1.0/src/leadger/static/favicon.svg +5 -0
- leadger-0.1.0/src/leadger/static/index.html +14 -0
- leadger-0.1.0/tests/__init__.py +0 -0
- leadger-0.1.0/tests/test_api.py +167 -0
- leadger-0.1.0/tests/test_cli.py +117 -0
- leadger-0.1.0/tests/test_parse.py +77 -0
- leadger-0.1.0/tests/test_recur.py +159 -0
- leadger-0.1.0/tests/test_storage.py +235 -0
- leadger-0.1.0/tests/test_tasks.py +108 -0
- leadger-0.1.0/tests/test_yaml_io.py +99 -0
leadger-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
.venv/
|
|
5
|
+
venv/
|
|
6
|
+
*.egg-info/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
build/
|
|
9
|
+
dist/
|
|
10
|
+
|
|
11
|
+
# Frontend
|
|
12
|
+
frontend/node_modules/
|
|
13
|
+
frontend/dist/
|
|
14
|
+
|
|
15
|
+
# Editors / OS
|
|
16
|
+
.DS_Store
|
|
17
|
+
|
|
18
|
+
# Claude Code local settings
|
|
19
|
+
.claude/settings.local.json
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Formato baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/).
|
|
4
|
+
|
|
5
|
+
## [0.1.0] — 2026-06-11
|
|
6
|
+
|
|
7
|
+
Primeira release.
|
|
8
|
+
|
|
9
|
+
### Adicionado
|
|
10
|
+
|
|
11
|
+
- Tarefas recorrentes: `!todo-dia`, `!rec:dia`, `!rec:seg`…`!rec:dom` na
|
|
12
|
+
captura (web e CLI). Concluir a ocorrência aberta cria a próxima;
|
|
13
|
+
cancelar ou excluir encerra a série. Chave opcional `recur` no YAML;
|
|
14
|
+
editável inline (o token `!rec:` vem pré-preenchido no editor) e via
|
|
15
|
+
`PATCH /api/tasks/{id}`. A meta do dia segue honesta — cada ocorrência
|
|
16
|
+
conta como tarefa normal.
|
|
17
|
+
- Export iCalendar somente leitura: `leadger ics [--out arquivo]` e
|
|
18
|
+
`GET /calendar.ics` no servidor local. Tarefas abertas viram eventos de
|
|
19
|
+
dia inteiro (tags = categorias) e recorrentes ganham `RRULE`.
|
|
20
|
+
- CLI `leadger week`: resumo da semana no terminal — % por dia (seg→dom,
|
|
21
|
+
hoje marcado com `*`), agregado da semana e seções de (não) concluídas.
|
|
22
|
+
- Visão Semana na web: faixa seg→dom com o % batido de cada dia (dia bônus
|
|
23
|
+
= ∞, sem registro = —) e lista separada em "Não concluídas" /
|
|
24
|
+
"Concluídas", agrupadas por data.
|
|
25
|
+
- Alerta de tarefa parada: tarefa aberta há 7+ dias gera um aviso único na
|
|
26
|
+
tela (não repete por tarefa), convidando a concluir, reagendar, pausar
|
|
27
|
+
ou cancelar.
|
|
28
|
+
- Filtro por tag (clique na `#tag`; `Esc` limpa) e ação "Copiar resumo do
|
|
29
|
+
período (Markdown)" na paleta — pronto para colar no standup.
|
|
30
|
+
- Botões de ação visuais por linha (editar, pausar/retomar, cancelar,
|
|
31
|
+
excluir) no hover/seleção, com o atalho de teclado no tooltip; duplo
|
|
32
|
+
clique no título edita.
|
|
33
|
+
- `python -m leadger` como alias do comando `leadger`.
|
|
34
|
+
|
|
35
|
+
- Core de domínio sobre um único `leadger.yaml` (ruamel round-trip: comentários
|
|
36
|
+
e ordem do arquivo sobrevivem): snapshot lazy do dia, rollover automático de
|
|
37
|
+
tarefas não concluídas (com contador de migrações), métrica "% do dia
|
|
38
|
+
entregue" com over-delivery e dia bônus, escrita atômica com `.bak`.
|
|
39
|
+
- REST API FastAPI: `GET /api/state`, `POST /api/tasks` (sintaxe inline
|
|
40
|
+
`#tag` / `!hoje` / `!amanha` / `!sex` / `!2026-07-01`), `PATCH /api/tasks/{id}`,
|
|
41
|
+
`GET /api/history`, `GET /api/insights`.
|
|
42
|
+
- CLI `leadger`: `serve` (porta livre a partir de 4242, abre o navegador),
|
|
43
|
+
`add` com sintaxe inline, `today` com resumo do dia, `--data` para apontar
|
|
44
|
+
outro arquivo.
|
|
45
|
+
- Frontend React embarcado (nenhum Node necessário no uso final): tela Hoje
|
|
46
|
+
(anel de progresso, captura com highlight em tempo real, lista navegável por
|
|
47
|
+
teclado, períodos Dia–Ano, paleta ⌘K, cheatsheet `?`) e tela Histórico
|
|
48
|
+
(linha do % diário 30/90 dias, heatmap anual, distribuição por estado,
|
|
49
|
+
fator de correção pessoal, tarefas mais empurradas).
|
|
50
|
+
- Indicador `↻N` de tarefas empurradas para o dia seguinte (âmbar a partir
|
|
51
|
+
de 3 migrações) e card "Mais empurradas" no Histórico.
|
|
52
|
+
- Exclusão de tarefas (`DELETE /api/tasks/{id}`; na UI: `Del`, × no hover ou
|
|
53
|
+
paleta, com confirmação inline na própria linha).
|
|
54
|
+
- UI em português (padrão) e inglês — botão PT/EN no header, persistido.
|
|
55
|
+
- Animação de boas-vindas na primeira visita (anel âmbar + wordmark), com
|
|
56
|
+
respeito a `prefers-reduced-motion`.
|
|
57
|
+
- Dark mode padrão com toggle para light; acento âmbar `#F5A524`.
|
leadger-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gabriel Henrique
|
|
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.
|
leadger-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: leadger
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Personal productivity — local, calm, yours.
|
|
5
|
+
Author-email: Gabriel Henrique <gabrielhcacontato@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: cli,local-first,productivity,tasks,todo,yaml
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Environment :: Web Environment
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Office/Business :: Scheduling
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: fastapi>=0.111
|
|
22
|
+
Requires-Dist: ruamel-yaml>=0.18
|
|
23
|
+
Requires-Dist: typer>=0.12
|
|
24
|
+
Requires-Dist: tzdata>=2024.1; sys_platform == 'win32'
|
|
25
|
+
Requires-Dist: uvicorn[standard]>=0.29
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
28
|
+
Requires-Dist: httpx>=0.27; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
<div align="center">
|
|
34
|
+
|
|
35
|
+
# Leadger
|
|
36
|
+
|
|
37
|
+
**Personal productivity — local, calm, yours.**
|
|
38
|
+
|
|
39
|
+
[](https://pypi.org/project/leadger/)
|
|
40
|
+
[](https://pypi.org/project/leadger/)
|
|
41
|
+
[](LICENSE)
|
|
42
|
+
|
|
43
|
+
*For the important tasks that don't belong in your work's Jira.*
|
|
44
|
+
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
No cloud. No account. No telemetry. No gamification. Your data lives in a
|
|
50
|
+
single human-readable YAML file you can keep in git.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install leadger
|
|
54
|
+
leadger
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
That starts a local web UI on `localhost` and opens your browser. No Node
|
|
58
|
+
required — the frontend ships embedded in the package.
|
|
59
|
+
|
|
60
|
+
<!-- demo: add docs/presentation.mp4 or a screenshot here -->
|
|
61
|
+
|
|
62
|
+
## Why Leadger?
|
|
63
|
+
|
|
64
|
+
Most task apps fail the same way: red "overdue" badges that breed anxiety,
|
|
65
|
+
metrics you can game by deleting tasks, and feature creep that turns a todo
|
|
66
|
+
list into a project-management chore. Leadger takes the opposite bet —
|
|
67
|
+
**statistical honesty about yourself, calmly delivered**:
|
|
68
|
+
|
|
69
|
+
- **Frozen daily goal.** The first time you open Leadger each day, it
|
|
70
|
+
snapshots your planned tasks: that's your goal. Tasks created during the
|
|
71
|
+
day count as *extras* — they add to your delivery but never inflate the
|
|
72
|
+
goal. Cancelling or deleting a planned task doesn't shrink the goal
|
|
73
|
+
either (anti-gaming, by design).
|
|
74
|
+
- **"% of the day delivered."** The hero metric. It can pass 100%
|
|
75
|
+
(over-delivery gets a second amber lap on the ring). Zero goal with
|
|
76
|
+
deliveries = bonus day (∞).
|
|
77
|
+
- **Honest rollover.** Whatever you don't finish migrates to the next day
|
|
78
|
+
automatically, with a visible `↻N` counter. History surfaces your most
|
|
79
|
+
pushed tasks — procrastination becomes visible, without judgment.
|
|
80
|
+
- **Personal correction factor.** *"You plan 5.8 tasks/day on average and
|
|
81
|
+
deliver 5.2 — your real rate is 90%."* Just statistics over your last 30
|
|
82
|
+
days, so you can plan like the person you actually are.
|
|
83
|
+
- **Week at a glance.** The Week view shows each day's % (Mon→Sun strip),
|
|
84
|
+
the week's aggregate on the ring, and the list split into *not done* /
|
|
85
|
+
*done*.
|
|
86
|
+
- **Stale-task alert.** A task open for 7+ days triggers a one-time,
|
|
87
|
+
dismissable notice: complete, reschedule, pause or cancel — deciding is
|
|
88
|
+
progress too.
|
|
89
|
+
- **Markdown summary.** One palette action copies the period's
|
|
90
|
+
goal/delivered/% plus both task lists — ready to paste into a standup.
|
|
91
|
+
|
|
92
|
+
## Quick capture
|
|
93
|
+
|
|
94
|
+
An always-visible input with live syntax highlighting:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Estudar FAISS #estudo !amanha
|
|
98
|
+
Entregar relatório #trabalho !sex
|
|
99
|
+
Pagar contas !2026-07-01
|
|
100
|
+
Meditar !todo-dia
|
|
101
|
+
Review da semana #trabalho !rec:seg
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
| Token | Meaning |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `#tag` | add a tag (click a tag in the list to filter by it) |
|
|
107
|
+
| `!hoje` / `!amanha` | target today / tomorrow |
|
|
108
|
+
| `!seg`…`!dom` | target the next matching weekday |
|
|
109
|
+
| `!YYYY-MM-DD` | target an exact date |
|
|
110
|
+
| `!todo-dia` | recurring: every day |
|
|
111
|
+
| `!rec:dia` / `!rec:seg`…`!rec:dom` | recurring: daily / weekly on that weekday |
|
|
112
|
+
|
|
113
|
+
> Capture tokens are Portuguese — Leadger is a PT-first product; the UI
|
|
114
|
+
> ships in Portuguese and English (toggle in the header).
|
|
115
|
+
|
|
116
|
+
**Recurring tasks** are materialized one occurrence at a time: completing
|
|
117
|
+
the open occurrence creates the next; cancelling or deleting it ends the
|
|
118
|
+
series. The daily goal stays honest — each occurrence counts as a regular
|
|
119
|
+
task on its day.
|
|
120
|
+
|
|
121
|
+
## Keyboard first (mouse welcome)
|
|
122
|
+
|
|
123
|
+
| Key | Action |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `n` | focus capture |
|
|
126
|
+
| `j` / `k` | navigate the list |
|
|
127
|
+
| `x` / `p` / `c` | complete · pause · cancel |
|
|
128
|
+
| `e` | inline edit (double-click works too) |
|
|
129
|
+
| `1`–`6` | period: Day · Week · Month · Quarter · Half · Year |
|
|
130
|
+
| `⌘K` / `Ctrl+K` | command palette |
|
|
131
|
+
| `g h` / `g t` | History · Today |
|
|
132
|
+
| `?` | cheatsheet |
|
|
133
|
+
|
|
134
|
+
Every keyboard action also has a visual control — hover a task row for
|
|
135
|
+
edit/pause/cancel/delete buttons, each tooltip teaching its shortcut.
|
|
136
|
+
|
|
137
|
+
## CLI
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
leadger # start the server and open the browser
|
|
141
|
+
leadger serve --port 8080 --no-browser
|
|
142
|
+
leadger add "Estudar FAISS #estudo !amanha"
|
|
143
|
+
leadger today # today's summary in the terminal
|
|
144
|
+
leadger week # weekly summary: % per day + (not) done
|
|
145
|
+
leadger ics --out agenda.ics # export open tasks as iCalendar
|
|
146
|
+
leadger --data other.yaml … # use another data file
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Calendar (.ics)
|
|
150
|
+
|
|
151
|
+
See your open tasks in any calendar app, without a cloud:
|
|
152
|
+
`leadger ics --out leadger.ics` writes the file, and with the server
|
|
153
|
+
running, `http://localhost:4242/calendar.ics` serves the same content.
|
|
154
|
+
Recurring tasks become `RRULE`s, so the whole series shows up projected on
|
|
155
|
+
your calendar. The export is read-only — the YAML remains the single
|
|
156
|
+
source of truth.
|
|
157
|
+
|
|
158
|
+
## Your data
|
|
159
|
+
|
|
160
|
+
Everything lives in `~/.leadger/leadger.yaml` — a commented, readable,
|
|
161
|
+
versionable YAML file. Leadger preserves your comments and key order on
|
|
162
|
+
every write (round-trip), writes atomically and keeps a `.bak` of the
|
|
163
|
+
previous version. Edit it in any editor; the app detects the change and
|
|
164
|
+
reloads.
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
167
|
+
tasks:
|
|
168
|
+
- id: t_8f3k2a
|
|
169
|
+
title: Revisar pipeline de segmentação
|
|
170
|
+
status: todo # todo | done | paused | cancelled
|
|
171
|
+
target: 2026-06-09
|
|
172
|
+
tags: [trabalho]
|
|
173
|
+
migrations: 0 # times pushed to the next day
|
|
174
|
+
recur: seg # optional: dia | seg..dom (recurring task)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## What Leadger deliberately doesn't do
|
|
178
|
+
|
|
179
|
+
Sync, cloud, accounts, subtasks, pomodoro, XP, badges, confetti,
|
|
180
|
+
databases. The YAML is the single source of truth.
|
|
181
|
+
|
|
182
|
+
## Development
|
|
183
|
+
|
|
184
|
+
See `CONTEXT.md` for the full contract (schema, business rules, phases).
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
pip install -e ".[dev]"
|
|
188
|
+
pytest
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Frontend (React + Vite + Tailwind)
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
cd frontend
|
|
195
|
+
npm install
|
|
196
|
+
npm run dev # hot reload; proxies /api to the backend on 4242
|
|
197
|
+
npm run build # outputs frontend/dist
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
For development, run the backend with `leadger serve --port 4242
|
|
201
|
+
--no-browser` and Vite with `npm run dev`.
|
|
202
|
+
|
|
203
|
+
### Release
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
make dist # frontend build + embed into src/leadger/static + python -m build
|
|
207
|
+
twine upload dist/*
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Without `make` (PowerShell): `npm run build` in `frontend/`, copy
|
|
211
|
+
`frontend/dist/*` into `src/leadger/static/`, then `python -m build`.
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
[MIT](LICENSE)
|
leadger-0.1.0/README.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Leadger
|
|
4
|
+
|
|
5
|
+
**Personal productivity — local, calm, yours.**
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/leadger/)
|
|
8
|
+
[](https://pypi.org/project/leadger/)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
|
|
11
|
+
*For the important tasks that don't belong in your work's Jira.*
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
No cloud. No account. No telemetry. No gamification. Your data lives in a
|
|
18
|
+
single human-readable YAML file you can keep in git.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install leadger
|
|
22
|
+
leadger
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
That starts a local web UI on `localhost` and opens your browser. No Node
|
|
26
|
+
required — the frontend ships embedded in the package.
|
|
27
|
+
|
|
28
|
+
<!-- demo: add docs/presentation.mp4 or a screenshot here -->
|
|
29
|
+
|
|
30
|
+
## Why Leadger?
|
|
31
|
+
|
|
32
|
+
Most task apps fail the same way: red "overdue" badges that breed anxiety,
|
|
33
|
+
metrics you can game by deleting tasks, and feature creep that turns a todo
|
|
34
|
+
list into a project-management chore. Leadger takes the opposite bet —
|
|
35
|
+
**statistical honesty about yourself, calmly delivered**:
|
|
36
|
+
|
|
37
|
+
- **Frozen daily goal.** The first time you open Leadger each day, it
|
|
38
|
+
snapshots your planned tasks: that's your goal. Tasks created during the
|
|
39
|
+
day count as *extras* — they add to your delivery but never inflate the
|
|
40
|
+
goal. Cancelling or deleting a planned task doesn't shrink the goal
|
|
41
|
+
either (anti-gaming, by design).
|
|
42
|
+
- **"% of the day delivered."** The hero metric. It can pass 100%
|
|
43
|
+
(over-delivery gets a second amber lap on the ring). Zero goal with
|
|
44
|
+
deliveries = bonus day (∞).
|
|
45
|
+
- **Honest rollover.** Whatever you don't finish migrates to the next day
|
|
46
|
+
automatically, with a visible `↻N` counter. History surfaces your most
|
|
47
|
+
pushed tasks — procrastination becomes visible, without judgment.
|
|
48
|
+
- **Personal correction factor.** *"You plan 5.8 tasks/day on average and
|
|
49
|
+
deliver 5.2 — your real rate is 90%."* Just statistics over your last 30
|
|
50
|
+
days, so you can plan like the person you actually are.
|
|
51
|
+
- **Week at a glance.** The Week view shows each day's % (Mon→Sun strip),
|
|
52
|
+
the week's aggregate on the ring, and the list split into *not done* /
|
|
53
|
+
*done*.
|
|
54
|
+
- **Stale-task alert.** A task open for 7+ days triggers a one-time,
|
|
55
|
+
dismissable notice: complete, reschedule, pause or cancel — deciding is
|
|
56
|
+
progress too.
|
|
57
|
+
- **Markdown summary.** One palette action copies the period's
|
|
58
|
+
goal/delivered/% plus both task lists — ready to paste into a standup.
|
|
59
|
+
|
|
60
|
+
## Quick capture
|
|
61
|
+
|
|
62
|
+
An always-visible input with live syntax highlighting:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
Estudar FAISS #estudo !amanha
|
|
66
|
+
Entregar relatório #trabalho !sex
|
|
67
|
+
Pagar contas !2026-07-01
|
|
68
|
+
Meditar !todo-dia
|
|
69
|
+
Review da semana #trabalho !rec:seg
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
| Token | Meaning |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `#tag` | add a tag (click a tag in the list to filter by it) |
|
|
75
|
+
| `!hoje` / `!amanha` | target today / tomorrow |
|
|
76
|
+
| `!seg`…`!dom` | target the next matching weekday |
|
|
77
|
+
| `!YYYY-MM-DD` | target an exact date |
|
|
78
|
+
| `!todo-dia` | recurring: every day |
|
|
79
|
+
| `!rec:dia` / `!rec:seg`…`!rec:dom` | recurring: daily / weekly on that weekday |
|
|
80
|
+
|
|
81
|
+
> Capture tokens are Portuguese — Leadger is a PT-first product; the UI
|
|
82
|
+
> ships in Portuguese and English (toggle in the header).
|
|
83
|
+
|
|
84
|
+
**Recurring tasks** are materialized one occurrence at a time: completing
|
|
85
|
+
the open occurrence creates the next; cancelling or deleting it ends the
|
|
86
|
+
series. The daily goal stays honest — each occurrence counts as a regular
|
|
87
|
+
task on its day.
|
|
88
|
+
|
|
89
|
+
## Keyboard first (mouse welcome)
|
|
90
|
+
|
|
91
|
+
| Key | Action |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `n` | focus capture |
|
|
94
|
+
| `j` / `k` | navigate the list |
|
|
95
|
+
| `x` / `p` / `c` | complete · pause · cancel |
|
|
96
|
+
| `e` | inline edit (double-click works too) |
|
|
97
|
+
| `1`–`6` | period: Day · Week · Month · Quarter · Half · Year |
|
|
98
|
+
| `⌘K` / `Ctrl+K` | command palette |
|
|
99
|
+
| `g h` / `g t` | History · Today |
|
|
100
|
+
| `?` | cheatsheet |
|
|
101
|
+
|
|
102
|
+
Every keyboard action also has a visual control — hover a task row for
|
|
103
|
+
edit/pause/cancel/delete buttons, each tooltip teaching its shortcut.
|
|
104
|
+
|
|
105
|
+
## CLI
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
leadger # start the server and open the browser
|
|
109
|
+
leadger serve --port 8080 --no-browser
|
|
110
|
+
leadger add "Estudar FAISS #estudo !amanha"
|
|
111
|
+
leadger today # today's summary in the terminal
|
|
112
|
+
leadger week # weekly summary: % per day + (not) done
|
|
113
|
+
leadger ics --out agenda.ics # export open tasks as iCalendar
|
|
114
|
+
leadger --data other.yaml … # use another data file
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Calendar (.ics)
|
|
118
|
+
|
|
119
|
+
See your open tasks in any calendar app, without a cloud:
|
|
120
|
+
`leadger ics --out leadger.ics` writes the file, and with the server
|
|
121
|
+
running, `http://localhost:4242/calendar.ics` serves the same content.
|
|
122
|
+
Recurring tasks become `RRULE`s, so the whole series shows up projected on
|
|
123
|
+
your calendar. The export is read-only — the YAML remains the single
|
|
124
|
+
source of truth.
|
|
125
|
+
|
|
126
|
+
## Your data
|
|
127
|
+
|
|
128
|
+
Everything lives in `~/.leadger/leadger.yaml` — a commented, readable,
|
|
129
|
+
versionable YAML file. Leadger preserves your comments and key order on
|
|
130
|
+
every write (round-trip), writes atomically and keeps a `.bak` of the
|
|
131
|
+
previous version. Edit it in any editor; the app detects the change and
|
|
132
|
+
reloads.
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
tasks:
|
|
136
|
+
- id: t_8f3k2a
|
|
137
|
+
title: Revisar pipeline de segmentação
|
|
138
|
+
status: todo # todo | done | paused | cancelled
|
|
139
|
+
target: 2026-06-09
|
|
140
|
+
tags: [trabalho]
|
|
141
|
+
migrations: 0 # times pushed to the next day
|
|
142
|
+
recur: seg # optional: dia | seg..dom (recurring task)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## What Leadger deliberately doesn't do
|
|
146
|
+
|
|
147
|
+
Sync, cloud, accounts, subtasks, pomodoro, XP, badges, confetti,
|
|
148
|
+
databases. The YAML is the single source of truth.
|
|
149
|
+
|
|
150
|
+
## Development
|
|
151
|
+
|
|
152
|
+
See `CONTEXT.md` for the full contract (schema, business rules, phases).
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
pip install -e ".[dev]"
|
|
156
|
+
pytest
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Frontend (React + Vite + Tailwind)
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
cd frontend
|
|
163
|
+
npm install
|
|
164
|
+
npm run dev # hot reload; proxies /api to the backend on 4242
|
|
165
|
+
npm run build # outputs frontend/dist
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
For development, run the backend with `leadger serve --port 4242
|
|
169
|
+
--no-browser` and Vite with `npm run dev`.
|
|
170
|
+
|
|
171
|
+
### Release
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
make dist # frontend build + embed into src/leadger/static + python -m build
|
|
175
|
+
twine upload dist/*
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Without `make` (PowerShell): `npm run build` in `frontend/`, copy
|
|
179
|
+
`frontend/dist/*` into `src/leadger/static/`, then `python -m build`.
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# React + TypeScript + Vite
|
|
2
|
+
|
|
3
|
+
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
4
|
+
|
|
5
|
+
Currently, two official plugins are available:
|
|
6
|
+
|
|
7
|
+
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
|
|
8
|
+
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
|
|
9
|
+
|
|
10
|
+
## React Compiler
|
|
11
|
+
|
|
12
|
+
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
|
|
13
|
+
|
|
14
|
+
## Expanding the ESLint configuration
|
|
15
|
+
|
|
16
|
+
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
export default defineConfig([
|
|
20
|
+
globalIgnores(['dist']),
|
|
21
|
+
{
|
|
22
|
+
files: ['**/*.{ts,tsx}'],
|
|
23
|
+
extends: [
|
|
24
|
+
// Other configs...
|
|
25
|
+
|
|
26
|
+
// Remove tseslint.configs.recommended and replace with this
|
|
27
|
+
tseslint.configs.recommendedTypeChecked,
|
|
28
|
+
// Alternatively, use this for stricter rules
|
|
29
|
+
tseslint.configs.strictTypeChecked,
|
|
30
|
+
// Optionally, add this for stylistic rules
|
|
31
|
+
tseslint.configs.stylisticTypeChecked,
|
|
32
|
+
|
|
33
|
+
// Other configs...
|
|
34
|
+
],
|
|
35
|
+
languageOptions: {
|
|
36
|
+
parserOptions: {
|
|
37
|
+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
38
|
+
tsconfigRootDir: import.meta.dirname,
|
|
39
|
+
},
|
|
40
|
+
// other options...
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
])
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// eslint.config.js
|
|
50
|
+
import reactX from 'eslint-plugin-react-x'
|
|
51
|
+
import reactDom from 'eslint-plugin-react-dom'
|
|
52
|
+
|
|
53
|
+
export default defineConfig([
|
|
54
|
+
globalIgnores(['dist']),
|
|
55
|
+
{
|
|
56
|
+
files: ['**/*.{ts,tsx}'],
|
|
57
|
+
extends: [
|
|
58
|
+
// Other configs...
|
|
59
|
+
// Enable lint rules for React
|
|
60
|
+
reactX.configs['recommended-typescript'],
|
|
61
|
+
// Enable lint rules for React DOM
|
|
62
|
+
reactDom.configs.recommended,
|
|
63
|
+
],
|
|
64
|
+
languageOptions: {
|
|
65
|
+
parserOptions: {
|
|
66
|
+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
67
|
+
tsconfigRootDir: import.meta.dirname,
|
|
68
|
+
},
|
|
69
|
+
// other options...
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
])
|
|
73
|
+
```
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "leadger"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Personal productivity — local, calm, yours."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Gabriel Henrique", email = "gabrielhcacontato@gmail.com" }]
|
|
13
|
+
keywords = ["productivity", "tasks", "todo", "local-first", "yaml", "cli"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Environment :: Web Environment",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Programming Language :: Python :: 3.14",
|
|
25
|
+
"Topic :: Office/Business :: Scheduling",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"fastapi>=0.111",
|
|
29
|
+
"uvicorn[standard]>=0.29",
|
|
30
|
+
"ruamel.yaml>=0.18",
|
|
31
|
+
"typer>=0.12",
|
|
32
|
+
"tzdata>=2024.1; sys_platform == 'win32'",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
dev = ["pytest>=8.0", "httpx>=0.27", "build>=1.2", "twine>=5.0"]
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
leadger = "leadger.cli:app"
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.wheel]
|
|
42
|
+
packages = ["src/leadger"]
|
|
43
|
+
# garante o frontend embarcado mesmo que padroes de ignore mudem
|
|
44
|
+
artifacts = ["src/leadger/static/**"]
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.sdist]
|
|
47
|
+
include = ["src/leadger", "tests", "README.md", "CHANGELOG.md", "LICENSE"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|