dan felser @felsr
Dan Felser Berlin · Laufen & Rad @felsr

Hi, ich bin Dan.
Kaffee, Carbon und Claude.

Folge 1 von 100 ist raus

Bleib dabei, dann verpasst du die anderen 99 nicht.

Auf Instagram folgen

@felsr

Prompt-Bibliothek

Zu jeder Folge sport KI gibts den Prompt zum Mitnehmen.

Sport KI 01 Neu

Garmin-Prompt

Workouts, Schlaf, HRV, Ruhepuls, Body Battery, Training Readiness — in einem Ordner, den deine KI liest. Plus Dashboard. Kostet nix, läuft lokal, liest nur.

1 Claude Code laden, gibt's als App  2 Prompt reinhauen  3 machen, was er sagt. Am Laptop — am Handy geht's nicht.

Ich möchte meine Garmin-Uhr anbinden, damit du meine Trainings- und Erholungsdaten
lesen kannst, und ich fange bei null an. Ich will nichts herunterladen, keine Ordner
anlegen und keinen Code selbst schreiben. Das machst alles du. Führe mich Schritt für
Schritt in verständlichem Deutsch durch das Setup und halte an, wenn du etwas von mir
brauchst.

Das Ziel: meine eigenen Garmin-Daten — meine Workouts plus meine Erholungswerte
(Schlaf, HRV, Ruhepuls, Body Battery, Stress, Schritte und Training Readiness) — in
einen Ordner auf meinem Rechner holen, den du jedes Mal lesen kannst, wenn ich dich
frage. Dazu ein Dashboard als einzelne HTML-Datei, die ich im Browser öffne. Alles
nur lesend: Du schreibst nie etwas in mein Garmin-Konto zurück, und meine Daten
bleiben lokal auf meinem Rechner.

Hier ist alles, was du tun sollst, von vorne bis hinten. Mach es komplett selbst:

1. Lege einen neuen Ordner dafür an (nenn ihn "garmin-ai") und arbeite darin. Ich
   soll ihn nicht selbst erstellen müssen.

2. Prüfe zuerst, ob Python 3.11 oder neuer installiert ist, und hilf mir bei der
   Installation, falls nicht. Lege dann im Projektordner eine virtuelle Umgebung an
   (.venv) und installiere alles nur dort hinein — nicht ins System-Python. Schreib
   auch die requirements.txt.

3. Schreibe das Sync-Script für mich. Nutze dafür die Open-Source-Bibliothek
   python-garminconnect von cyberjunky
   (https://github.com/cyberjunky/python-garminconnect). Das Script soll meine
   Aktivitäten und meine Tageswerte (Schlaf, HRV, Ruhepuls, Body Battery, Stress,
   Schritte, Training Readiness) holen und als sauberen Ordner "garmin/" ablegen:
   verständliche Markdown-Notizen plus eine data.json. Eine Notiz pro Tag, eine
   Notiz pro Workout. Jeder einzelne Abruf soll einzeln abgesichert sein, damit ein
   fehlender Wert nie den ganzen Lauf abbricht — fehlende Werte werden als "keine
   Daten" behandelt, nicht als Null.

4. Erledige den einmaligen Garmin-Login. Halte an dieser Stelle an und sag mir, dass
   ich das selbst in einem echten Terminalfenster ausführen muss. Mein Passwort soll
   niemals durch unseren Chat laufen und niemals in deinem Kontext landen. Das
   Script fragt E-Mail und dann das Passwort in einer verdeckten Eingabe ab
   (getpass), fängt einen eventuellen 2FA-Code ab und speichert danach nur ein
   Login-Token, das etwa ein Jahr hält. Das Script soll sich weigern zu starten,
   wenn kein echtes Terminal vorhanden ist, in dem die Eingabe verdeckt werden kann.
   Passwort und Token dürfen nie ausgegeben, geloggt oder in Umgebungsvariablen
   abgelegt werden; der Token-Ordner bekommt private Zugriffsrechte (700 für den
   Ordner, 600 für die Dateien).

5. Teste es, indem du meine letzten 3 Tage ohne Schreiben abrufst und mir das
   Ergebnis zeigst, damit ich sehe, dass es funktioniert. Danach schreib die Dateien
   einmal echt raus und zeig mir die Ordnerstruktur.

6. Wenn das läuft, hol einmalig die letzten 60 Tage Historie, damit es überhaupt
   etwas zu vergleichen gibt. Lass das im Hintergrund laufen, es sind viele Abrufe.
   Sag mir danach, wie viele Tage tatsächlich Werte enthalten.

7. Baue mir daraus ein Dashboard. Es soll eine einzige, in sich geschlossene
   HTML-Datei sein: die Daten direkt eingebettet, keine externen Schriften, Skripte
   oder Bilder, keine Internetverbindung nötig. Ich will sie per Doppelklick öffnen
   können. Trenn das sauber: eine Template-Datei für das Aussehen und ein kleines
   Build-Script, das die Daten hineinschreibt — damit das Dashboard bei jedem Sync
   neu gebaut werden kann, ohne dass jemand HTML anfasst.

   Inhalt des Dashboards:
   - Ganz oben groß die Training Readiness des letzten Tages mit Wert, Skala und
     einer Einordnung gegenüber meinem Durchschnitt im Zeitraum.
   - Eine Randspalte mit den aktuellen Werten: Schlaf, HRV, Ruhepuls, Body Battery,
     Distanz der letzten 7 Tage.
   - Vier Kacheln (HRV, Ruhepuls, Schlaf, Stress) mit jeweils aktuellem Wert,
     Sparkline und Veränderung gegenüber der Vorperiode. Hervorheben nur, wenn die
     Abweichung mehr als eine halbe bis dreiviertel Standardabweichung beträgt —
     nicht bei jedem Zufallsrauschen.
   - HRV als großes Diagramm mit Baseline-Band (Mittelwert ± eine
     Standardabweichung), damit Ausreißer sofort auffallen.
   - Ruhepuls als Linie, Schlaf als Säulen mit einer 7-Stunden-Markierung, Body
     Battery als Tagesspanne von tief nach hoch, Wochenkilometer als Säulen pro
     Kalenderwoche.
   - Ein Logbuch der letzten Einheiten mit Datum, Name, Distanz, Zeit, Pace in
     min/km (nicht km/h), Durchschnittspuls und aerobem Trainingseffekt.
   - Eine ausklappbare Rohdaten-Tabelle mit allen Werten des Zeitraums.
   - Eine Umschaltleiste für 14 / 30 / 60 Tage, die alle Diagramme gleichzeitig
     umstellt. Kurze, verständliche Erklärungstexte an jedem Diagramm — ich will
     wissen, was der Wert bedeutet, nicht nur wie er aussieht.

   Designvorgaben — bitte genau so:
   - Minimalistisches Bauhaus, dunkler Hintergrund. Schwarz (#08080A), Off-White
     (#F5F5F5) für Text, dazu abgestufte Grautöne für Sekundärtext und Linien.
   - Helvetica durchgehend: "Helvetica Neue", Helvetica, Arial, sans-serif. Zahlen
     fett und eng getrackt. Überschriften und Labels konsequent kleingeschrieben
     (das ist ein bewusstes Bauhaus-Zitat), Fließtext normal geschrieben.
   - Vier Bauhaus-Primärfarben, jede steht für ein Bedeutungsfeld und nie für einen
     Rang: Blau #3D7BFF für HRV und Trainingsumfang, Rot #F0402F für Puls, Gelb
     #FFC400 für Schlaf, Grün #00C46A für Energie, Stress und Body Battery. Eine
     Metrik behält ihre Farbe auch beim Umschalten des Zeitraums — es darf sich
     nichts umfärben.
   - Weiß ist durchgehend die Hervorhebung: kurze Nächte, schwache Body-Battery-Tage,
     die noch laufende Woche. Weiß markiert außerdem den letzten Datenpunkt.
   - Keine Rundungen, nirgends. Harte Rechtecke, quadratische Marker statt Punkte,
     sichtbares Raster aus dünnen Linien zwischen allen Modulen. Kein Filmkorn, keine
     Vignette, keine dekorativen Effekte — Bauhaus ist Funktion, nicht Atmosphäre.
   - Ein kleines farbiges Quadrat als Marke vor jeder Überschrift und jedem
     Kachel-Label, in der Farbe der jeweiligen Metrik.
   - Zurückhaltende Bewegung: Linien zeichnen sich einmal ein, Säulen wachsen einmal
     auf. Bei prefers-reduced-motion steht alles still.
   - Responsiv bis 375 px Breite, ohne horizontales Scrollen der Seite.

   Diagramm-Handwerk, bitte einhalten:
   - Dünne Marks, hauchdünne durchgezogene Gitterlinien (nie gestrichelt),
     zurückhaltende Achsen, großzügiger Weißraum.
   - Nie zwei Y-Achsen in einem Diagramm.
   - Keine Zahl an jedem Datenpunkt: beschrifte nur den letzten Wert direkt, alles
     andere tragen Achse, Tooltip und Rohdaten-Tabelle.
   - Fehlende Tage sind eine Lücke in der Linie, keine interpolierte Verbindung und
     keine Null.
   - Jedes Diagramm bekommt einen Hover-Layer mit Fadenkreuz und Tooltip; die
     Tooltips dürfen aber nie der einzige Weg zu einem Wert sein — deshalb die
     Rohdaten-Tabelle.
   - Prüfe die Farbkontraste rechnerisch, nicht nach Gefühl: alles, was Text ist,
     mindestens 4,5:1 gegen den Hintergrund; alles, was nur Grafik ist, mindestens
     3:1. Prüfe zusätzlich, ob die Farben bei Farbfehlsichtigkeit unterscheidbar
     bleiben, und sag mir ehrlich, wenn ein Kompromiss nötig war.

8. Wenn das Dashboard steht, frag mich, ob der Sync jeden Morgen automatisch laufen
   soll, und richte das dann ein — inklusive Dashboard-Neubau, damit es nie veraltet.
   Frag mich auch nach der Uhrzeit.

9. Zum Schluss: Öffne das Dashboard selbst im Browser, mach einen Screenshot, prüfe
   die Konsole auf Fehler und teste die Umschaltleiste, den Tooltip und die
   Rohdaten-Tabelle wirklich durch. Zeig mir das Ergebnis, statt mich zu bitten, es
   selbst zu kontrollieren. Wenn etwas verrutscht ist, repariere es und schau erneut
   nach.

Wichtige Fallstricke, die du bitte von vornherein beachtest — sie haben in genau
diesem Setup schon Probleme gemacht:

- Installiere alles in eine virtuelle Umgebung im Projektordner. Neuere Systeme
  verweigern Installationen ins System-Python.
- Die Bibliothek hat ihre API geändert: Ab Version 0.3 heißt der Token-Client
  api.client (nicht mehr api.garth), und login(tokenstore) speichert das Token
  bereits selbst, wenn man einen Pfad übergibt. Ein 2FA-Code wird am saubersten über
  einen prompt_mfa-Callback abgefragt. Prüf die tatsächlich installierte Version,
  bevor du den Login-Code schreibst, statt dich auf ältere Beispiele im Netz zu
  verlassen.
- Das Dashboard muss die Daten eingebettet enthalten. Eine lokal geöffnete
  HTML-Datei darf aus Sicherheitsgründen keine JSON-Datei nachladen — das scheitert
  still.
- Wenn du SVG-Linien animierst: miss die Pfadlänge mit getTotalLength, statt sie zu
  schätzen. Eine geschätzte Länge lässt bei langen Linien Teile dauerhaft unsichtbar
  verschwinden, und das sieht aus wie fehlende Daten.
- Auf macOS: Nimm einen LaunchAgent statt cron — er holt einen Lauf nach, wenn der
  Rechner zur geplanten Zeit geschlafen hat. Lass den LaunchAgent aber niemals ein
  Shell-Script starten, das im Dokumente-Ordner liegt: Der Systemschutz verweigert
  dann den Zugriff ("Operation not permitted"). Ruf stattdessen direkt das
  Python-Programm der virtuellen Umgebung auf und bau den Dashboard-Neubau als
  Option in dieses eine Script ein. Teste den eingerichteten Job einmal scharf,
  indem du ihn manuell auslöst und den Exit-Code sowie die erzeugten Dateien prüfst.
  Auf Windows nimm die Aufgabenplanung, auf Linux cron oder einen systemd-Timer.
- Leg eine .gitignore an, die Token, Gesundheitsdaten, Logs und die virtuelle
  Umgebung ausschließt, falls ich den Ordner je versioniere.

Geh Schritt für Schritt vor. Kipp nicht alles auf einmal aus und lass mich keine
Dateien, Ordner oder Code anfassen. Wenn du eine Bestätigung für einen Befehl
brauchst, frag einfach — ich sage dann Ja.

Meine letzten Reels

Gerade läuft sport KI — Folge 1 von 100. Jede davon ein Ding, das ich wirklich für mein Training gebaut oder gebraucht hab.

Auf Instagram

sommer sachen machen average swiss summer Murmeli Aura claude babysitten surfs up in portugal business in the streets of copenhagen new pb north to south and no plans running 80:01 — chasing sub 80 is just perfect irony

Meine Stats

50,8 km
Längster Lauf
an einem Tag
301 km
Längste Radfahrt
an einem Tag
17:45
5 km
Bestzeit
37:38
10 km
Bestzeit
1:20:01
Halbmarathon
Bestzeit
Folg mir auf Strava Jeder Lauf, jede Ausfahrt — ungefiltert