Quantified Self

Like many worthwhile endeavors, I originally started doing this out of spite: if everyone is surveilling me & profiting from my data, shouldn’t I also get to derive some value from it? Or at the very least: can I get a copy?

In the past I had written some #python scrapers and done basic processing with my limited #programming ability, like calculating stats from my Strava #cycling logs. But now that Claude Code can one-shot this type of task, I got a little more ambitious with this experiment.

I’m also interested in the idea of agent visibility - if I give an agent tools to use this data, what connections can an #LLM find?

Personal Data

The flow of personal data from services, to private git repos, and then ultimately used in downstream tools.

Data Collection

flowchart LR
    subgraph sources["Data Sources"]
        HA["🏠 Home Assistant"]
        G["πŸƒ Garmin"]
        ST["🚴 Strava"]
        SA["😴 Sleep as Android"]
    end

    subgraph repos["Private Repos"]
        R[("JSON Format")]
    end
    
    subgraph downstream["Tools"]
        MCP["πŸ€– Brad MCP"]
        RPT["πŸ“Š Reports"]
        WEB["🌐 brad.quest"]
    end

    subgraph audience["Audience"]
        AG["Agents"]
        ME["Me"]
        PL["Public"]
    end

    HA & G & ST & SA --> R
    R --> MCP & WEB & RPT
    MCP --> AG & ME
    WEB --> PL
    RPT --> ME

For each data source, I run a Python script using Forgejo Actions on a regular schedule. If new data is found, it’s committed back into the repo and the script calculates out additional metrics & enrichment.

Data Sources

SourceTypeMCP Domain
Last.fmCloudmusic
WithingsCloudweight
Sleep as AndroidCalendarsleep
StravaCloudfitness
SteamCloudgaming
RetroAchievementsCloudgaming
LetterboxdCloudfilms
BoardGameGeekCloudboardgames
Home AssistantSelf-hostedhome
NutritionAgentnutrition
iNaturalistCloudnature

Repo Structure

Each source has its own private repo. All repos follow the same general structure β€” a data/ folder with daily JSON files and an index.json for quick lookups. Using music scrobbles from LastFM as an example:

scrobbles/
└── data/
    β”œβ”€β”€ index.json            # aggregate stats + list of all daily file dates
    β”œβ”€β”€ summary.json          # archive completeness, last fetch timestamp
    β”œβ”€β”€ fetch_state.json      # incremental sync progress
    β”œβ”€β”€ library_artists.json  # all artists with total play counts
    β”œβ”€β”€ loved_tracks.json
    β”œβ”€β”€ top/
    β”‚   β”œβ”€β”€ artists/
    β”‚   β”‚   β”œβ”€β”€ 7day.json
    β”‚   β”‚   β”œβ”€β”€ 1month.json
    β”‚   β”‚   └── overall.json
    β”‚   β”œβ”€β”€ albums/
    β”‚   └── tracks/
    β”œβ”€β”€ charts/               # weekly charts (historical backfill)
    β”‚   β”œβ”€β”€ artists/
    β”‚   β”‚   β”œβ”€β”€ 2005-W08.json
    β”‚   β”‚   └── 2026-W05.json
    β”‚   β”œβ”€β”€ albums/
    β”‚   └── tracks/
    └── scrobbles/            # one file per day with listening activity
        β”œβ”€β”€ 2005-05-24.json
        β”œβ”€β”€ 2005-05-25.json
        └── 2026-02-04.json

JSON Format

Data is aggregated into a consistent JSON format. For example, daily files are named YYYY-MM-DD.json. A scrobble entry looks like:

{
  "date": "2026-02-04",
  "scrobble_count": 42,
  "scrobbles": [
    {
      "timestamp": 1770175192,
      "datetime": "2026-02-04T03:19:52+00:00",
      "track": "The Paradox",
      "artist": "At the Gates",
      "album": "The Nightmare of Being",
      "image": "https://lastfm.freetls.fastly.net/...",
      "mbid": "6671f0ea-dd8b-407e-a5aa-9de39edcf68a",
      "loved": false
    }
  ]
}

Personal Tools

Downstream of that data collection, I’ve started building personal tooling that incorporates it.

Bands in Town

We are lucky in the #bayarea to have the long-running JRL List, which conveniently publishes it’s DIY show listings in plaintext.

I have a script that simply scrapes the list and fuzzy matches against artists from my listening history to create a web view and a calendar feed.

Daily Email

A very obvious thing to do. I get a basic morning summary of health, sleep, and top media for the week alongside my upcoming calendar & tasks. This is just a script that runs as an action.

MCP

See Brad MCP

brad.quest

This site's pages for Listening, Map, and Now pages are all derived from my personal data.