BeatTrack.win-arm64
0.4.7
dotnet add package BeatTrack.win-arm64 --version 0.4.7
NuGet\Install-Package BeatTrack.win-arm64 -Version 0.4.7
<PackageReference Include="BeatTrack.win-arm64" Version="0.4.7" />
<PackageVersion Include="BeatTrack.win-arm64" Version="0.4.7" />
<PackageReference Include="BeatTrack.win-arm64" />
paket add BeatTrack.win-arm64 --version 0.4.7
#r "nuget: BeatTrack.win-arm64, 0.4.7"
#:package BeatTrack.win-arm64@0.4.7
#addin nuget:?package=BeatTrack.win-arm64&version=0.4.7
#tool nuget:?package=BeatTrack.win-arm64&version=0.4.7
beat-track
Cross-source music listening analysis. Merges data from Last.fm, YouTube, and Discogs into a unified profile, then runs queries to surface insights — what's new, what's surging, what you're missing, and what you should revisit.
Built with .NET 11, AOT-compatible, zero external runtime dependencies.
Install
No .NET required — downloads a self-contained native binary.
Via dotnet-install
If you have dotnet-install:
dotnet install --package beat-track
Direct download
Linux / macOS:
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/richlander/beat-track/main/install.sh | sh
Windows:
irm https://raw.githubusercontent.com/richlander/beat-track/main/install.ps1 | iex
From source
./install-source.sh
Builds from the local source tree via dotnet-install (requires the .NET SDK).
Agent integration
beat-track includes a built-in skill definition for AI agents:
beat-track skill
This prints the full agent skill with workflows for establishing the environment, acquiring data, running reports, and managing user preferences. Agents should run this first to understand available commands and data flow.
Quick start
# Set up your Last.fm API key (get one at https://www.last.fm/api/accounts)
mkdir -p ~/.config/beat-track
echo "lastfm_api_key=YOUR_KEY" >> ~/.config/beat-track/config
echo "lastfm_user=YOUR_USERNAME" >> ~/.config/beat-track/config
# Download your full listening history
beat-track history
# Explore
beat-track stats
beat-track top-artists --window 30d
beat-track live -n 10
Building from source
git clone https://github.com/richlander/beat-track.git
cd beat-track
dotnet build
dotnet run --project src/BeatTrack.App -- status
Using without data
You can explore the tool's queries and code without any data. The scrobble-only queries (stats, streaks, top-artists, artist-velocity) need a single CSV file. The full cross-source analysis needs at least two sources to be interesting.
If you don't have a Last.fm account, you can create one and start scrobbling today — the tool works with any amount of data. Even a week of scrobbles is enough for top-artists and stats.
Data sources
Each source is optional. Start with one and add more over time.
Last.fm scrobble history (recommended starting point)
Export your full scrobble history from lastfmstats.com:
- Go to
lastfmstats.com/user/YOUR_USERNAME - Wait for it to load all scrobbles
- Click CSV (top right)
- Place the file at
~/.local/share/beat-track/lastfmstats/lastfmstats-YOUR_USERNAME.csv
The CSV is semicolon-delimited: Artist;Album;AlbumId;Track;Date (epoch milliseconds).
Last.fm API snapshot (adds top artist MBIDs)
For richer metadata (MusicBrainz IDs, top artists by time period, loved tracks):
- Get a Last.fm API key
- Add it to your config file:
mkdir -p ~/.config/beat-track
echo "lastfm_api_key=YOUR_KEY" >> ~/.config/beat-track/config
echo "lastfm_user=YOUR_USERNAME" >> ~/.config/beat-track/config
- Run the snapshot tool:
beat-track snapshot
The API key is read from ~/.config/beat-track/config, LASTFM_API_KEY env var, or stdin (in that order).
The snapshot JSON is written to stdout or to a path via BEAT_TRACK_OUTPUT_PATH. Place it at ~/.local/share/beat-track/YOUR_USERNAME-snapshot.json.
Live scrobble feed
# Show last 10 scrobbles (API key from config file)
beat-track live -n 10
# Follow mode — polls every 15s, ctrl-c to stop
beat-track live -f
# Show last 5, then follow
beat-track live -f -n 5
Discogs collection (adds physical media)
- Go to your Discogs collection page
- Click Export → CSV
- Place the file at
~/.local/share/beat-track/collection-csv/YOUR_USERNAME-collection-*.csv
YouTube watch history (adds video listening)
- Go to takeout.google.com
- Select only YouTube and YouTube Music
- Download and extract
- Place at
~/.local/share/beat-track/takeout/extracted/Takeout/
BeatTrack classifies YouTube watch history to identify music content using known artist matching, VEVO/Topic channel detection, music platform recognition (KEXP, Sub Pop, 3voor12, Cercle, etc.), and title pattern analysis.
Queries
Scrobble-only queries (fast, no API calls)
# General listening statistics — Eddington number, span, one-hit-wonders
beat-track stats
# Top artists with time windows (7d, 30d, 90d, 365d, all)
beat-track top-artists --window 7d
beat-track top-artists --window 365d --limit 30
# Listening streaks — overall and per-artist
beat-track streaks
beat-track streaks --artist "Massive Attack"
# Cumulative play count curves over time
beat-track artist-velocity --top 10 --bucket yearly
beat-track artist-velocity --artists "Radiohead,Björk,Caribou" --bucket monthly
# New discoveries — artists you started listening to within a time window
beat-track new-discoveries --window 7d
beat-track new-discoveries --window 30d
# Artist depth — catalog explorers vs one-hit wonders
beat-track artist-depth --mode deep # who you explore deeply
beat-track artist-depth --mode shallow # one-hit wonders
beat-track artist-depth --mode all --window 365d --min 10
Cross-source analysis (loads all data sources)
Run without a command for the full analysis:
beat-track
This produces:
- Unified profile — merged artist/release data across all sources
- Cross-source breakdown — which artists appear in 1, 2, or all 3 sources
- MBID resolution — maps artist names to MusicBrainz IDs (cached at
~/.cache/beat-track/mbid-cache.md) - Gap analysis — artists similar to your favorites that you've never listened to
- Slice comparison — Last.fm vs YouTube artist overlap with time windows
- New interests — artists appearing for the first time in the last 60 days
- Surging — artists with disproportionately high recent play rates
- Re-engagement — dormant favorites similar to what you're currently into
- Strange absences — artists surrounded by your favorites but completely absent from your data
Known misses
Track artists you've tried but don't connect with. These are automatically excluded from gap analysis, strange absences, re-engagement, and dormant favorites recommendations.
# Add an artist (with optional reason)
beat-track miss add "Johnny Marr" --reason "tried multiple times, doesn't grab me"
# List all known misses
beat-track miss
# Remove (give them another chance)
beat-track miss remove "Johnny Marr"
Known misses are stored at ~/.local/share/beat-track/known-misses.md.
User-defined favorites and similarities
You can declare your own favorite artists and similarity relationships. These supplement service-derived data and are especially useful if you don't have a long listening history.
Favorites (~/.local/share/beat-track/my-favorites.md) — used as seed artists for MBID resolution and gap analysis:
| artist | notes |
| --- | --- |
| Slowdive | |
| Boards of Canada | especially older albums |
Similarity graph (~/.local/share/beat-track/my-similar-artists.md) — merged into the ListenBrainz similarity data, bidirectional:
| artist | similar_to |
| --- | --- |
| Slowdive | My Bloody Valentine |
| Slowdive | Ride |
| Boards of Canada | Aphex Twin |
Combining queries for playlists
Run multiple queries to build a listening plan:
top-artists --window 7dto see current rotationstreaksto find artists you've been on a run with- Full analysis for re-engagement suggestions and strange absences
- Use the output to build a playlist mixing current favorites with recommended revisits and discoveries
Data directory layout
BeatTrack follows the XDG Base Directory Specification. Data and cache are stored separately so you can safely clear the cache without losing user data.
~/.config/beat-track/ # User configuration ($XDG_CONFIG_HOME/beat-track)
└── config # Key=value settings (API keys, username)
~/.local/share/beat-track/ # Persistent user data ($XDG_DATA_HOME/beat-track)
├── lastfmstats/
│ └── lastfmstats-*.csv # Scrobble history export
├── collection-csv/
│ └── *-collection-*.csv # Discogs CSV export
├── takeout/
│ └── extracted/Takeout/... # YouTube Takeout
├── *-snapshot.json # Last.fm API snapshot
├── known-misses.md # Artists excluded from recommendations
├── my-favorites.md # User-declared favorite artists (seed for analysis)
└── my-similar-artists.md # User-defined artist similarity graph
~/.cache/beat-track/ # Regenerable cache ($XDG_CACHE_HOME/beat-track)
├── mbid-cache.md # Artist → MusicBrainz ID mappings
└── similar-artists/ # ListenBrainz similarity data
└── {mbid}.md
Legacy ~/.beattrack/ paths are still checked as a fallback.
Updating data
Re-export your data sources and replace the files. Caches persist across runs — delete ~/.cache/beat-track/ to force a full refresh.
# Re-download scrobble history from lastfmstats.com, then:
beat-track stats
# Re-run full analysis with fresh data
beat-track
Cache format
Caches are stored as markdown pipe tables — human-readable, GitHub-renderable, hand-editable:
| canonical_name | mbid | matched_name | source |
| --- | --- | --- | --- |
| radiohead | a74b1b7f-... | Radiohead | lastfm |
| belle and sebastian | 59ea0a7b-... | Belle and Sebastian | lastfm |
Architecture
BeatTrack.Core # Models, parsers, analysis, queries (zero dependencies)
BeatTrack.LastFm # Last.fm API client
BeatTrack.YouTube # YouTube Takeout parser + music classifier
BeatTrack.Discogs # Discogs CSV parser
BeatTrack.App # Main CLI — unified analysis + queries
BeatTrack.LastFm.App # Last.fm CLI — snapshots + live scrobble feed
Adding queries
Query logic lives in BeatTrack.Core/Queries/ as static classes:
- Create
src/BeatTrack.Core/Queries/YourQuery.cs - Implement
public static int Run(IReadOnlyList<LastFmScrobble> scrobbles, string[] args) - Add routing in the command dispatch block at the top of
src/BeatTrack.App/Program.cs
Key types to build on:
| Type | Purpose |
|---|---|
LastFmScrobble |
Single scrobble: ArtistName, Album, Track, TimestampMs |
BeatTrackSlice |
Weighted artist bag for any filtered view of the data |
BeatTrackSliceComparer |
Three-way comparison: shared, only-A, only-B |
ArtistNameMatcher |
Fuzzy name resolution (spaceless, ASCII-fold, Levenshtein) |
MbidCache |
Persistent artist → MusicBrainz ID mappings |
MarkdownTableStore |
Read/write markdown tables for caches |
BeatTrackAnalysis.CanonicalizeArtistName |
Universal join key across sources |
Building new tools on the core
Reference BeatTrack.Core from a new project:
<ProjectReference Include="../BeatTrack.Core/BeatTrack.Core.csproj" />
Load scrobble data with LastFmStatsCsvReader.ParseCsv(reader) and build analysis on top.
Development
Targets .NET 11 preview. Build defaults:
TreatWarningsAsErrors=trueIsAotCompatible=trueSystem.Text.Jsonsource generation (no reflection)- JSON uses
snake_case_lowernaming policy - Repo naming follows
kebab-case-lower
dotnet test
dotnet run --project src/BeatTrack.App -- stats
License
MIT
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.