Metadata-Version: 2.3
Name: grafit
Version: 1.18.0
Summary: Garmin FIT file loader for SQLite + Grafana
Requires-Dist: python-fitparse>=2.1.6
Requires-Dist: pytest>=7.0 ; extra == 'dev'
Requires-Dist: black>=23.0 ; extra == 'dev'
Requires-Dist: ruff>=0.1.0 ; extra == 'dev'
Requires-Python: >=3.11
Project-URL: Homepage, https://github.com/nbr23/grafit
Project-URL: Repository, https://github.com/nbr23/grafit
Project-URL: Issues, https://github.com/nbr23/grafit/issues
Provides-Extra: dev
Description-Content-Type: text/markdown

# GraFIT

Loads Garmin FIT files into a SQLite database and visualizes them in Grafana.

GraFIT parses `.fit` files (activities, sleep, GPS, etc.) using [python-fitparse](https://github.com/nbr23/python-fitparse), writes them to SQLite using a schema generated from the FIT profile, and ships with Grafana provisioning (datasource + dashboards) so you can browse the data immediately.

## Install

```
uv tool install grafit
```

Or run without installing:

```
uvx grafit <command> [options]
```

Requires Python 3.11+.

## Usage

```
uv run grafit <command> [options]
```

### Commands

- `init <db_path>` — create and initialize the SQLite database.
- `import <path> <db_path>` — import a FIT file or directory of FIT files into the database.
  - `--force` reimport files already present in the database.
  - `--no-recursive` do not recurse into subdirectories.
  - `--fetch-weather` look up historical hourly weather (temperature, apparent temperature, humidity) for each session's start coordinates and date from the [Open-Meteo](https://open-meteo.com) archive. Failures are logged and skipped — the FIT import itself never fails because of weather.
- `backfill-weather <db_path>` — fetch weather for sessions already imported without `--fetch-weather`. Safe to re-run: only sessions missing weather are queried; rate-limited or failed sessions are picked up on the next run.
  - `--force` re-fetch weather even for sessions that already have it.
- `stats <db_path>` — show row counts per table.
- `purge <db_path> --file-hash <sha256>` — remove all rows imported from a given file.
- `generate-schema <output>` — write the full DDL SQL to a file.
- `install-provisioning <dest>` — copy the bundled Grafana provisioning (datasource + dashboards) to a directory.
  - `--force` overwrite the destination if it exists.

Global flag: `-v` / `--verbose` for debug logging.

## Grafana

A `docker-compose.yml` is provided to run Grafana with the SQLite datasource plugin against `./fit_data.db` and the bundled dashboards mounted from `./grafana-provisioning`.

> **Note:** the bundled compose file enables anonymous admin access and disables the login form. It is intended for local use only — do not expose it to a network.

Drop your FIT files into `./GARMIN` and bring it up:

```
docker compose up
```

A `grafit-init` container installs the bundled provisioning, runs `grafit init`, and runs `grafit import ./GARMIN` against shared volumes; Grafana waits for it to finish before starting. Re-running `docker compose up` reuses the database — already-imported files are skipped by hash.

Grafana is then available at http://localhost:3000.
