Skip to main content

Personal productivity — local, calm, yours.

Project description


Leadger icon

Leadger

Personal productivity — local, calm, yours.

PyPI Python License: MIT Code style: black

For the important tasks that don't belong in your work's Jira.

Install · Features · Screenshots · Architecture · Development



🚀 Install

pip install leadger
leadger

That's it. A local web UI opens on localhost:4242.
No Node.js, no database, no cloud — the frontend ships pre-built inside the package.

Your data lives in a single human-readable YAML file at ~/.leadger/leadger.yaml
that you can version-control with git, edit in any text editor, and own forever.


✦ Features

🎯 Frozen Daily Goal

The first time you open Leadger each day, it snapshots your planned tasks — that's your goal. Tasks created later are extras. Cancelling or deleting planned tasks doesn't shrink the goal (anti-gaming, by design).

📊 % of the Day Delivered

The hero metric. Over 100%? You get a second amber lap on the ring. Zero goal with deliveries = bonus day (∞).

↻ Honest Rollover

Unfinished tasks migrate to the next day with a visible ↻N counter. History reveals your most-pushed tasks — procrastination becomes visible, without judgment.

🔮 Personal Correction Factor

"You plan 5.8/day, deliver 5.2 — your real rate is 90%."

Statistics over your last 30 days, so you can plan like the person you actually are.

🔄 Recurring Tasks

!daily (every day), !rec:mon (every Monday) — tokens work in English and Portuguese. Each occurrence counts as a regular task — the daily goal stays honest.

📅 Calendar Export (.ics)

leadger ics --out agenda.ics — see your tasks in any calendar app. Recurring tasks become RRULEs. Read-only; the YAML is always the source of truth.


📸 Screenshots

Today — Hero Ring + Task List

Today screen — progress ring, capture input and task list

History — Analytics Dashboard

History screen — line chart, heatmap, distribution and correction factor

Command Palette (⌘K)

Command palette with fuzzy search and keyboard shortcuts

⌨️ Quick Capture

An always-visible input with live syntax highlighting. Type, press Enter, done.

Study FAISS #learning !tomorrow
Entregar relatório #trabalho !sex
Pay the bills !2026-07-01
Meditate !daily
Weekly review #work !rec:mon

Capture Tokens Reference

English Portuguese Meaning Example
#tag #tag Adds a tag #work, #study
!today !hoje Target today (default) Fix bug !today
!tomorrow !amanha Target tomorrow Review PR !tomorrow
!mon!sun !seg!dom Target the next matching weekday Weekly sync !mon
!YYYY-MM-DD !YYYY-MM-DD Target exact date Launch !2026-07-01
!daily / !every-day !todo-dia Recurring daily Meditate !daily
!rec:day !rec:dia Recurring daily Standup !rec:day
!rec:mon!rec:sun !rec:seg!rec:dom Recurring weekly Review !rec:mon

Note: every token works in both English and Portuguese — mix them freely.
The UI also ships in both languages (toggle in the header).


🎹 Keyboard Shortcuts

Leadger is keyboard-first — every action also has a mouse/touch control.

Navigation
n Focus capture input
j / k Move down / up
16 Switch period
g h Go to History
g t Go to Today
Actions
x Complete / reopen task
p Pause / resume task
c Cancel task
e Edit inline
Del Delete (with confirmation)
⌘K / Ctrl+K Command palette
? Cheatsheet

🏗 Architecture

graph TB
    subgraph User["👤 User"]
        Browser["Browser<br><small>localhost:4242</small>"]
        Terminal["Terminal"]
    end

    subgraph Frontend["Frontend — React + Vite + Tailwind"]
        SPA["SPA<br><small>Today · History</small>"]
        Capture["Capture Parser<br><small>parse.ts</small>"]
        Components["Components<br><small>Ring · Heatmap · Palette</small>"]
    end

    subgraph Backend["Backend — Python + FastAPI"]
        API["REST API<br><small>/api/state · /api/tasks · /api/history</small>"]
        CLI["CLI — Typer<br><small>serve · add · today · week · ics</small>"]
        Core["Core Domain"]
    end

    subgraph Core_Detail["Core Modules"]
        Storage["storage.py<br><small>Snapshot · Rollover · Metrics</small>"]
        Tasks["tasks.py<br><small>State transitions</small>"]
        Parse["parse.py<br><small>Inline syntax</small>"]
        Recur["recur.py<br><small>Recurring tasks</small>"]
        YAML["yaml_io.py<br><small>ruamel round-trip</small>"]
    end

    subgraph Data["💾 Data Layer"]
        File["~/.leadger/leadger.yaml<br><small>Single file · Git-friendly</small>"]
        Backup["leadger.yaml.bak<br><small>Auto backup</small>"]
    end

    Browser --> SPA
    SPA --> API
    Terminal --> CLI
    CLI --> Core
    API --> Core
    Core --> Core_Detail
    Storage --> YAML
    YAML --> File
    YAML --> Backup
    SPA --> Capture
    SPA --> Components

    style Frontend fill:#1a1a2e,stroke:#F5A524,color:#e6e6e6
    style Backend fill:#1a1a2e,stroke:#3776AB,color:#e6e6e6
    style Core_Detail fill:#16161a,stroke:#26262c,color:#e6e6e6
    style Data fill:#16161a,stroke:#26262c,color:#e6e6e6
    style User fill:#0e0e11,stroke:#26262c,color:#e6e6e6

Project Structure

leadger/
├── pyproject.toml                 # Build config (hatchling)
├── Makefile                       # CI/Linux: test, build, dist
├── src/leadger/
│   ├── __init__.py
│   ├── __main__.py                # python -m leadger
│   ├── cli.py                     # Typer: serve | add | today | week | ics
│   ├── server.py                  # FastAPI + SPAStaticFiles
│   ├── core/
│   │   ├── storage.py             # Snapshot, rollover, metrics, CRUD
│   │   ├── tasks.py               # State machine (todo ⇄ paused → done/cancelled)
│   │   ├── parse.py               # Inline capture parser (#tag !today !amanha)
│   │   ├── recur.py               # Recurring task logic
│   │   ├── yaml_io.py             # Atomic read/write with ruamel.yaml
│   │   ├── periods.py             # Date range calculations
│   │   ├── time_utils.py          # Timezone helpers
│   │   ├── ids.py                 # Task ID generation (t_XXXXXX)
│   │   └── ics.py                 # iCalendar export
│   └── static/                    # Pre-built frontend (embedded in wheel)
├── frontend/                      # React + Vite + Tailwind source
│   ├── src/
│   │   ├── App.tsx                # Router (pushState: / and /history)
│   │   ├── api.ts                 # API client
│   │   ├── screens/
│   │   │   ├── Today.tsx          # Hero ring + capture + task list
│   │   │   └── History.tsx        # Charts + heatmap + insights
│   │   ├── components/            # ProgressRing, Capture, TaskRow, etc.
│   │   └── lib/                   # i18n, date utils, inline parser
│   └── public/favicon.svg
└── tests/                         # pytest: API, storage, parser, CLI, etc.

🔌 REST API

Method Endpoint Description
GET /api/state?period=day|week|month|quarter|semester|year Tasks + today's metrics
POST /api/tasks Create task (inline syntax parsed)
PATCH /api/tasks/{id} Update title, target, tags, status, recur
DELETE /api/tasks/{id} Delete permanently (204)
GET /api/history?from=&to= Daily series: date, goal, done, pct
GET /api/insights Correction factor (last 30 days)
GET /calendar.ics iCalendar export

💻 CLI

leadger                              # start server + open browser
leadger serve --port 8080 --no-browser
leadger add "Estudar FAISS #estudo !amanha"
leadger today                        # today's summary in the terminal
leadger week                         # weekly summary: % per day + tasks
leadger ics --out agenda.ics         # export as iCalendar
leadger --data ~/other.yaml         # use another data file

📄 Your Data

Everything lives in ~/.leadger/leadger.yaml. Leadger preserves your comments and key order (round-trip via ruamel.yaml), writes atomically, and keeps a .bak of the previous version. Edit in any editor — the app detects changes and reloads.

version: 1
config:
  day_start: "05:00"            # when the "day" rolls over
  timezone: America/Sao_Paulo

tasks:
  - id: t_8f3k2a
    title: Revisar pipeline de segmentação
    status: todo                # todo | done | paused | cancelled
    target: 2026-06-09
    tags: [trabalho]
    migrations: 0               # times pushed to the next day
    recur: seg                  # optional: dia | seg..dom

🚫 What Leadger Deliberately Doesn't Do

Sync · Cloud · Accounts · Subtasks · Pomodoro · XP · Badges · Confetti · Databases

The YAML is the single source of truth.


🎨 Design System

Token Dark (default) Light
Accent #F5A524 (amber) #C47D00
Background #0E0E11 #FAFAFA
Panel #16161A #FFFFFF
Text #E6E6E6 #1B1B1F
Muted #8B8B94 #71717A
Border #26262C #E4E4E7
  • Typography: Inter + tabular numerals
  • Animations: 150–200ms ease-out micro-transitions
  • i18n: Portuguese (default) and English — toggle in the header

🛠 Development

Prerequisites

  • Python ≥ 3.11
  • Node.js ≥ 18 (frontend development only)

Setup

git clone https://github.com/GabrielHenriqueCA/leadger.git
cd leadger
pip install -e ".[dev]"
pytest                              # run all backend tests

Frontend

cd frontend
npm install
npm run dev                         # hot reload on :5173, proxies /api → :4242

Run the backend alongside:

leadger serve --port 4242 --no-browser

Build & Release

# Linux / macOS / Git Bash
make dist                           # frontend build → embed → python -m build
twine upload dist/*

PowerShell (Windows):

cd frontend; npm run build; cd ..
Copy-Item -Recurse frontend/dist/* src/leadger/static/ -Force
python -m build
python -m twine upload dist/*

Tech Stack

Layer Technology
Backend Python 3.11+ · FastAPI · Uvicorn
Data ruamel.yaml (round-trip) — single YAML file
CLI Typer
Frontend React 19 · Vite 8 · Tailwind CSS 4 · TypeScript 6
Build Hatchling — frontend embedded in the wheel
Tests pytest (API, storage, parser, CLI, recurrence)

📜 License

MIT — Made with ☕ by Gabriel Henrique

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

leadger-0.1.1.tar.gz (109.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

leadger-0.1.1-py3-none-any.whl (105.8 kB view details)

Uploaded Python 3

File details

Details for the file leadger-0.1.1.tar.gz.

File metadata

  • Download URL: leadger-0.1.1.tar.gz
  • Upload date:
  • Size: 109.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for leadger-0.1.1.tar.gz
Algorithm Hash digest
SHA256 3fb86b03eb198af70479ad6c912cdad13d107535ae22cf1cedfa53e8b53b51be
MD5 934dc547a4a3c5e51457145ac61ef0d8
BLAKE2b-256 a74765710717d58fbda33d9c5442de64b97ec256beb8a21909811cdbfc43ba4a

See more details on using hashes here.

Provenance

The following attestation bundles were made for leadger-0.1.1.tar.gz:

Publisher: release.yml on GabrielHenriqueCA/leadger

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file leadger-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: leadger-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 105.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for leadger-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1bbf3584aee16da9464a655d7df254596adf9011ca8443d884dd17051f6e7a94
MD5 3a2521a9275c5ca1fc2957dc0bb2b865
BLAKE2b-256 cd33fe4f87e6874db66869519c9f459f3281be132d0eb8517fd4f4ec9b4f1a8b

See more details on using hashes here.

Provenance

The following attestation bundles were made for leadger-0.1.1-py3-none-any.whl:

Publisher: release.yml on GabrielHenriqueCA/leadger

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page