Mirobody
인간 건강의 표준 레지스트리, 약 2천 개 임상·생활 지표를 하나의 언어로 정리
로컬에서 관리되는 피트니스 데이터, 시계·밴드·10년 기록·대시보드·AI 코치, 모두 직접 보관, 독일 오픈소스
Local-first fitness data: watch, band, ten years of history, dashboard, AI coach — all in your own home. Open source, built in Germany.
건강Python · ShellGitHub @one7two99온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
Reclaim your wearable data: pulls Garmin (USB) and Gadgetbridge (ADB) files into a local SQLite, no vendor cloud, no subscription. CLI + terminal UI, exports for chat assistants, and a training coach that runs on the LLM you choose: Ollama on premise, Claude API or OpenRouter.
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Project page: https://one7two99.github.io/wristpull/
tests on Linux, macOS and Windows (hardware-free; see docs/platforms.md)
Collects health and training data from wearables without any vendor cloud, stores the raw files immutably, normalises everything into a local SQLite database and prepares it for analysis with Claude (or a local LLM, dashboards, ...).
| Device | Path into wristpull | Status |
|---|---|---|
| Garmin fenix 6X Pro | USB (MTP), FIT files under GARMIN/ | wave 1, done |
| Garmin fenix 6X Pro | Bluetooth via Gadgetbridge, FIT files pulled with ADB | wave 3, done |
| Amazfit Helio Strap | Gadgetbridge (Zepp OS), SQLite export pulled with ADB | wave 3, done |
The code repository never contains health data. Everything lands in ~/Health/wristpull/
(configurable), the .gitignore additionally blocks *.fit, *.sqlite, *.gpx and data folders.
The primary way is the Docker stack on Linux: one image runs the web dashboard and every command,
including the watch over USB, the phone over ADB and the strap over Bluetooth, so the host needs
neither Python nor uv. On a fresh machine contrib/bin/wristpull-setup walks through the whole
setup and asks only for what is missing (or restores a backup); docs/setup.md is
the same checklist by hand, the details are under "Running everything in Docker".
git clone https://github.com/one7two99/wristpull.git ~/dev/wristpull && cd ~/dev/wristpull
contrib/bin/wristpull-setup # Docker, .env, image, dashboard, keys, udev rule, AppArmor profile
contrib/bin/wristpull status # every command through the container
The native installation (Python 3.14 and uv) runs the same package with the same commands. It is the way for development, and for macOS and Windows, where Docker cannot reach the devices. docs/platforms.md says which way fits which machine (Linux, macOS, Windows, Android, iPhone), what each path imports and what it needs.
cd ~/dev/wristpull
uv sync --extra tui --extra coach --extra web --extra ble # terminal UI, Claude backend, web dashboard, strap over Bluetooth
uv run wristpull config --init # writes ~/.config/wristpull/config.toml
uv run wristpull status
With the Docker stack every command runs as docker compose run --rm cli wristpull ... from the
checkout, or shorter through the wrapper contrib/bin/wristpull ...; in a native installation it
is uv run wristpull ... (or once uv tool install --editable ., then wristpull ...). The
examples below use the short form.
| Command | Purpose |
|---|---|
import garmin | copy and parse new FIT files from the USB-connected watch |
pull phone | trigger a Gadgetbridge export, pull database and FIT files over ADB, import them |
pull strap | read the Helio Strap directly over Bluetooth (no phone, no Gadgetbridge) and import it |
strap scan|pair|info | find the band, store its auth key, show where every fetch kind left off |
import gadgetbridge | import an already copied Gadgetbridge export |
import garmin-export | import the Garmin Connect account export (your whole history as FIT files) |
status | what is stored, which device is connected |
inspect FILE | message types and fields of a FIT file |
config | show or create the configuration file |
export, report | Markdown + CSV for Claude, weekly/monthly reports |
coach | training coach: daily check, weekly review, questions, ratings via an LLM |
workout | structured workouts as Markdown, pushed to the watch as FIT files |
reparse | re-parse archived raw files after a parser change |
backup create|show|restore | the whole state (data, config, .env) as one tar.gz, and back onto a new machine |
tui | the terminal UI over all of the above |
serve | the web dashboard for phone and browser (also as a Docker container) |
| Option | Effect |
|---|---|
--config PATH | use this config file instead of ~/.config/wristpull/config.toml |
-q, --quiet | print only the final summary line (no per-file output) |
--version | print the version and exit |
-h, --help | help for the program or any subcommand, e.g. wristpull import garmin --help |
Exit codes: 0 success, 1 no device found (watch or phone), 2 finished with file errors or
invalid arguments.
wristpull import garminReads the watch over USB with the MTP tools, copies every FIT file that is not yet in the archive
and parses it into the database. Already archived files (same SHA-256) are skipped, so the command
can run as often as you like; files the archive already knows by name and size are not even
downloaded. After a successful import daily_summary is rebuilt.
| Option | Effect |
|---|---|
--path PATH | import this GARMIN folder (or a directory containing one) instead of the watch: a copy made with a file manager, or a mass-storage mount |
--dry-run | list the files that would be imported, copy and parse nothing |
wristpull import garmin # the watch on the cable
wristpull import garmin --dry-run # what is new?
wristpull import garmin --path ~/backup/fenix # any directory tree with a GARMIN folder or FIT files
wristpull -q import garmin # summary line only, e.g. for the udev-started import
Output per file: + Monitor/MAVG1415.FIT: heart_rate=672, stress=96, ..., then a summary
<root>: 37 FIT files, 37 new, 0 already archived, 0 errors and the inserted row counts.
Files that cannot be decoded are still archived and marked parse_status = 'error' in raw_files.
여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗