A dark desktop companion for a Rockbox iPod, built with PyQt6.
Plug the iPod in and NokiPod finds it, scans its music, scrobbles what you listened to on the go, fixes your tags, fetches your lyrics and evens out your volume. The window is one screen: Now Playing on the left, and on the right a cascade of tiles that falls away along an arc. The library, your playlists and the play queue are all levels of that same cascade.
This app is designed around music players (not just iPods!) running Rockbox to add a little more convenience and ease-of-use. It is NOT designed for your local music library. That may come later.
v0.1.1 is the upcoming public beta for Linux and Windows. It is prepared as the first release with a Windows installer, but has not been tagged or published yet. The local candidate passed the full Linux and Windows test/UI loops plus a fresh install and a same-version reinstall over deliberately stale payloads under Wine; the exact workflow still needs its first hosted run, and native Windows with a physical iPod remains a smaller evidence set than Linux. Expect rough edges and please report them.
| Tool | What it does |
|---|---|
| Library | Browse the iPod's music (Artists, Albums, Songs) as tiles colored from the real cover art, with arrow keys or the mouse, and play it through your computer. Playing a track queues the rest of the list behind it. |
| Search | Pretty self-explanatory |
| Queue and lyrics | The queue is a level of the cascade: history above, the playing track centred, upcoming below, drag the grip to reorder. The lyrics panel reads a .lrc sidecar or an embedded lyrics tag and follows the timestamps. |
| Scrobbler | Auto-scrobbles new plays from the iPod's .scrobbler.log to Last.fm the moment the device connects, with today and all-time counts and a recent-plays feed. |
| ReplayGain | Runs rsgain over the Music folder on the music player running Rockbox with your chosen target loudness and album or track mode, reporting per-track gain and peak. |
| Playlists | Reads the device's .m3u and .m3u8 playlists, shows them as song tiles you can reorder by dragging, and builds new ones by ticking songs. |
| Tags | A batch tag editor: edit title, artist, album, year and genre across the library, flag what is missing, and embed album art. Fix for Me fills the gaps from MusicBrainz and downloads cover art. |
| Settings | Volume and fades, repeat, auto-queue, resume where you left off, device info and eject, the interface click voice, whether to copy your play history to the iPod (off unless you turn it on), and live sliders over the interface's own colour, tile and motion values. |
The library, with the cascade of tiles on the right:
Artists:
An artist's albums, each tile coloured from its own cover art:
Searching the whole library at once, with songs, albums and artists grouped under labelled dividers:
The queue, with history above the playing track and upcoming below:
Lyrics, following the song as it plays:
The Scrobbler sheet:
The Tags editor, and its bulk grid:
ReplayGain and Settings:
Download NokiPod-Setup-*.exe from the
latest release
(Windows installers ship from v0.1.1 onwards) and run it. NokiPod requires an
x64-compatible Windows 10 version 1809 (build 17763) or later, or Windows 11.
It installs strictly per-user — no administrator prompt — puts NokiPod in the
Start menu, and bundles rsgain, so ReplayGain works out of the box. The
workflow builds that scanner from an exact rsgain source commit and a pinned
vcpkg snapshot using FFmpeg 9.0.1; FFmpeg and the other copyleft libraries are
replaceable DLLs beside rsgain.exe. Their notices, binary hashes, exact
source provenance, rebuild instructions, and source offer are installed in the
rsgain folder. The same folder includes the Windows frozen/runtime CycloneDX
SBOM; a separately named release SBOM inventories the locked Python packages.
The workflow also replaces CPython's superseded OpenSSL 3.0.21 DLLs with a
source-built, hash-pinned OpenSSL 3.0.22 security release and verifies real
certificate-checked HTTPS; Qt uses the native Windows Schannel backend.
The installer/compile targets and reviewed DLL-import allowlist are set for
Windows 10, but the final installer still needs its first smoke run on a native
Windows 10 1809 VM. The installer is not code-signed: SmartScreen will warn on a fresh download, and
"More info → Run anyway" is expected. SECURITY.md describes how
to check the download against SHA256SUMS.txt and the build provenance
attestation first. Provenance and platform code signing provide different
assurances; the installer does not yet have the latter.
Download NokiPod-*-x86_64.AppImage from the latest release, make it executable, and run it:
chmod +x NokiPod-*-x86_64.AppImage
./NokiPod-*-x86_64.AppImageAn AppImage is a single self-contained file. Python and Qt are bundled inside it, nothing is installed, and it runs from wherever you put it.
From a source checkout, the integration helper can add the AppImage to your application menu. It records wherever the AppImage actually lives, so it works no matter where you put it:
packaging/install.sh # or: install.sh /path/to/NokiPod-*.AppImage
packaging/install.sh --uninstall # to remove the entryA tool like Gear Lever can handle AppImage integration for you instead.
NokiPod never checks for or installs an update by itself. Release AppImages
intentionally contain no embedded update URL, and the release publishes no
.zsync sidecar, so the unverified AppImage delta-update path is not supported.
Download each new AppImage or Windows installer from the releases page and
verify it the way SECURITY.md describes before running it.
Neither is needed for scrobbling.
- ReplayGain needs
rsgain. The Windows installer bundles it; on Linux put it on yourPATH:sudo pacman -S rsgainorapt install rsgain. - Fingerprint tag matching (accurate even when the existing tags are
wrong) needs
fpcalcfrom Chromaprint (pacman -S chromaprint,apt install libchromaprint-tools, or on Windows thefpcalc.exefrom acoustid.org/chromaprint) plus a free AcoustID key entered in the app. On Windows, putfpcalc.exebeside the installedNokiPod.exeor somewhere on yourPATH. A copy found only in an unrelated folder NokiPod was launched from is deliberately ignored. Plain text matching works without either extra.
pip install -r requirements.txt # PyQt6 + mutagen
python3 nokipod.py # or ./run.shAutomatically. Every mount point is scored for Rockbox and iPod markers
(.scrobbler.log, .rockbox, iPod_Control, Music), and the best
candidate wins. A folder called Music on its own is never enough, so an
ordinary USB stick is not mistaken for a device.
That means it works on any Rockbox iPod, not just one that has been set up a
particular way: a fresh Rockbox install, an iPod with no music on it yet, one
using the Apple iPod_Control/Music layout, and even a non-iPod Rockbox
player are all recognised. TO BE CLEAR: I HAVE NOT TESTED THIS SOFTWARE ON
ANY iPOD THAT DOESN'T RUN ROCKBOX.
Nothing to configure. Plug it in and the status dot in the top bar turns
green while the library is scanned behind the launch screen. If you mount
your device somewhere unusual, NOKIPOD_FORCE_MOUNT=/path/to/mount overrides
the search.
- Source:
<iPod>/.scrobbler.log, Rockbox's tab-separated play log. - History archive: a cumulative record of every entry ever uploaded, in
the same format, kept in
~/.local/share/nokipod. Created automatically. - Duplicate rule: an entry is a duplicate when its artist, title and timestamp all match something already in the history. The same song heard again at a different time is not a duplicate, so it scrobbles again.
- Tracks rated
S(skipped on the iPod) are never uploaded. - Timestamps: Rockbox logs either UTC (
#TZ/UTC) or the device's local wall-clock time (#TZ/UNKNOWN). Local times are converted using your computer's timezone, DST-aware, per timestamp, with no hardcoded offset. - Uploads go in batches of 50. Each accepted batch is archived immediately, so a failure part way through never re-scrobbles earlier batches. Tracks Last.fm ignores (a timestamp too old, say) are archived too, so they are not retried forever.
- The original
.scrobbler.logis left on the iPod. Duplicate detection makes re-reading it harmless.
Press Lyrics (or L) while a song is playing. NokiPod reads a .lrc
sidecar next to the track, or a lyrics tag inside it, and highlights the live
line as the song plays.
If a song has none, the panel offers to fetch them from
LRCLIB, a free and open lyrics database that needs no
account and no API key. You can do the one song or the whole library, and
Automatically add lyrics to new songs keeps anything you add later topped
up. Lyrics are saved as .lrc files beside the audio, the same format
LRCGET uses, so a library built by
either tool works in both.
Songs LRCLIB has nothing for are remembered so the automatic sweep stops asking. Add for every song deliberately retries them, which is what you want after correcting a track's tags. Matching is by artist, title, album and duration, so tracks with missing tags will not match. Run the Tags editor first.
Fix for Me matches your files against the free MusicBrainz web service, filling missing title, artist, album, year and genre, and embedding cover art from the Cover Art Archive. No account or key is needed.
MusicBrainz genre data is thin outside well-known releases, so when it has no genre for a track NokiPod falls back to Last.fm's crowd tags. That uses only the API key you already entered for scrobbling. With no key it simply skips that step.
In the Tags overview, clicking a count such as Missing genre opens exactly those tracks.
rsgain easy --skip-existing "<iPod>/Music"
rsgain is resolved from your PATH. --skip-existing means re-runs only
touch files that have no ReplayGain tags yet.
You connect with your own free Last.fm API account, and the wizard walks you
through creating one. NokiPod stores the API key, shared secret and the
session key it obtains in config.json inside ~/.local/share/nokipod.
Session keys do not expire. If Last.fm ever invalidates one, NokiPod clears it
and offers the wizard again.
NokiPod has no account of its own, no telemetry and no update check. It talks to four services, each one only when you use the feature that needs it.
| Goes to | What it sends | When |
|---|---|---|
| Last.fm | The artist, title, album, track number, duration and timestamp of each play, signed with your session key. Your username, to read back your public play count and recent plays. An artist and title, to look up crowd tags when MusicBrainz has no genre. | Scrobbling, and the genre fallback in Fix for Me |
| LRCLIB | Artist, title, album and duration, as a search query. No account, no key. | Fetching lyrics |
| MusicBrainz and the Cover Art Archive | Artist, title and album as a search query, then the release it matched, to read genre and download cover art. | Fix for Me |
| AcoustID | The acoustic fingerprint fpcalc computes from the audio, its duration, and your AcoustID key. Not the file, not its name, not its path. |
Fix for Me, and only if you entered an AcoustID key |
Nothing else leaves the machine, and no audio is ever uploaded.
Everything NokiPod remembers is in ~/.local/share/nokipod (or
$XDG_DATA_HOME/nokipod if you have set that). NokiPod asks for 0700 on the
folder and 0600 on these files, so on an ordinary Linux or macOS home
directory no other account on the machine can read them.
Whether that holds depends on the filesystem the folder sits on. FAT, exFAT,
NTFS mounted without permissions, and most network shares have nowhere to
keep a permission bit, so chmod on them reports success and changes nothing.
If your home directory or your $XDG_DATA_HOME is on one of those, your
Last.fm keys and your listening history are readable by anyone with an account
on the machine.
So NokiPod does not trust chmod. Every time it starts it reads the modes
back off the disk, and if the folder or config.json did not end up private
it shows you one notice saying so and naming the path. Once, at startup, not
on every action. It still runs: not being able to protect the file is no
reason to lock you out of your own music player. On Windows the folder is
%APPDATA%\NokiPod and it is your Windows profile, not a mode, that keeps
other accounts out, so there is nothing to check and nothing is shown.
| File | What is in it |
|---|---|
config.json |
Your Last.fm API key, shared secret and session key, your username, your AcoustID key if you entered one, and every setting from the Settings tool |
scrobble-history.log |
Every play ever uploaded. This is the file duplicate detection reads |
app-plays.log |
Plays made through NokiPod itself rather than on the iPod |
scrobble-log-export.log |
The two above merged with the device's log |
playback-archive-<date>.log |
A copy of the device's raw playback.log, taken before NokiPod resets it |
lyrics-misses.json |
Tracks LRCLIB had nothing for, so a sweep stops asking |
scan-cache.json |
The scan cache: the path and tags of each file on the device, so a rescan is quick |
Off by default. Settings has a Copy play history to iPod toggle, and while
it is off nothing about your listening is written to the device. The merged
log is still built in your data folder either way, as
scrobble-log-export.log in the table above.
Turn it on and NokiPod writes that same merged log to
scrobble-log-export.log in the root of the iPod: when the device is plugged
in and its scan finishes, after every batch Last.fm accepts, and when you
press Export & sync now. It is the whole archive rather than the new
plays, so it grows for the life of the install.
Worth knowing what that means before you turn it on. An iPod is FAT formatted, and FAT has no permission bits, so this copy cannot be protected the way the one in your data folder is. It is your full listening history, readable, in the root of a removable drive that plugs into any computer.
Turning the toggle back off stops NokiPod writing the file again, but it does
not remove a copy already sitting on the device. Delete it from the iPod,
the button next to the toggle in Settings, does that, with the iPod plugged
in. The two are independent, so turn the toggle off first: delete it while
copying is still on and the next sync writes it straight back. NokiPod says
so when that is the situation. You can also delete
scrobble-log-export.log from the device's root yourself.
If you have used an earlier build of NokiPod, assume the file is already on your iPod. Every version before this one wrote it on every sync with no setting to stop it.
There is no disconnect button yet. Settings shows Last.fm authorisation · Re-link account, but that only runs the wizard again and overwrites the stored credentials with a new set. To remove them, quit NokiPod first, because a running copy holds the settings in memory and writes them back, then delete the file:
rm ~/.local/share/nokipod/config.jsonThat takes the API key, the shared secret and the session key with it, and NokiPod starts up unlinked and offers the wizard. It clears your other settings too, since they live in the same file.
One caveat if you have upgraded from an older build: some installs carry a
config.json.bak-tz next to it, left by a version that is no longer in the
code, and it holds the same secrets. Check with ls ~/.local/share/nokipod
and delete anything that starts with config.json, or use the command below,
which covers it.
To drop the listening history as well, remove the whole folder:
rm -r ~/.local/share/nokipodDeleting the session key stops NokiPod using it, but does not revoke it at Last.fm's end. Revoke NokiPod there through your Last.fm account's own settings for applications you have granted access to.
python -m unittest discover -s tests # core tests, no GUI needed
QT_QPA_PLATFORM=offscreen python3 nokipod.py --selftest # GUI smoke test
python3 tests/harness_ui.py # behavioural UI harnessReleases are built by GitHub Actions
(.github/workflows/build.yml) from a PyInstaller
one-folder build. Linux assembles an AppDir with appimagetool; Windows wraps
the frozen app and a source-built, pinned rsgain/FFmpeg native payload in an
Inno Setup installer. The Linux job
runs on Ubuntu 24.04 while building inside a digest-pinned Ubuntu 22.04
container for broad glibc compatibility. Pushing a strict v* tag that matches
APP_VERSION in nokipod.py publishes both platform artifacts to a GitHub
release only after their tests and security gates pass.
The release attestation records which workflow and commit produced the
published bytes; it is provenance, not a guarantee of bit-for-bit reproducible
builds. The packaged Python runtime is pinned to 3.13.15, and the rsgain and
vcpkg source archives are pinned by commit and verified by SHA-256. Their
transitive native source recipes carry hashes as well. The exact vcpkg tool
asset is also SHA-256-pinned and Microsoft Authenticode-verified before its
first execution. OpenSSL 3.0.22 is built from its exact source archive with a
checked CPython DLL-name patch; its source, patch, configuration, binary hashes,
and licence are recorded with the native payload. FFmpeg n9.0.1 is also checked
at source level for the four published fixes associated with CVE-2026-8461 and
CVE-2026-30999 rather than treated as safe by version number alone. The hosted Windows
job's maintained windows-2022 runner image (pinned to match Visual Studio
2022) and Ubuntu packages selected from the base image's signed repositories
can still change between otherwise identical workflow runs.
Building the Windows native ReplayGain payload directly requires PowerShell 7
or later (pwsh) and Visual Studio 2022 with the x64 C++ tools:
pwsh -File packaging/build-rsgain-windows.ps1To build one locally:
pip install -r requirements.txt pyinstaller
packaging/build-appimage.sh # -> dist-appimage/NokiPod-<version>-x86_64.AppImageappimagetool is downloaded automatically on first run. Note that a local
build bundles whatever Qt libraries your desktop happens to have, so it can be
considerably larger than the release build. Build on the oldest glibc you need
to support for the widest compatibility.
- Comfortaa, the interface typeface, bundled in assets/fonts so NokiPod looks the same on a machine that does not have it installed. Copyright 2011 The Comfortaa Project Authors, with Reserved Font Name "Comfortaa", licensed under the SIL Open Font License 1.1. The full licence travels with the font in assets/fonts/OFL.txt. Three static weights are bundled (Regular, SemiBold, Bold), the weights the interface actually asks for. If loading them ever fails, NokiPod falls back through Quicksand, Varela Round, Nunito and Rubik, and says so on the console. Settings then shows which face is really in use.
- LRCLIB, the lyrics database behind the Add lyrics buttons. Free and open, no account and no API key.
- rsgain, the ReplayGain
scanner. The Windows payload is built from the commit recorded in
packaging/build-rsgain-windows.ps1, with FFmpeg 9.0.1 and without the nonfree FDK AAC fallback. Native licence texts, source provenance, and the rebuild/source offer travel inside the installer'srsgainfolder. - MusicBrainz and the Cover Art Archive, behind Fix for Me.
- The library, tag reads and writes, and album-art embedding use mutagen. Playback uses Qt Multimedia, and degrades gracefully if no audio backend is present.
- TO BE CLEAR: This software was made almost entirely with Claude Design, Claude Code, and a little bit of ChatGPT Codex. I still use Claude Design for my creative direction, and this project has still taken months to get to a point I'm ready to release it. I hope you'll like it.
NokiPod is free software under the GNU General Public License v3.0 only
(GPL-3.0-only). See LICENSE. You may use, study, share and modify
it. If you distribute a modified version, it has to stay under the GPL too.
Not "or later", which is what this said before. NokiPod links PyQt6, and
PyQt6's GPL option is GPL-3.0-only, so the combined work can only be conveyed
under GPL-3.0 and nobody downstream gets to relicense it under a later GPL.
That applies to the AppImage, which bundles PyQt6, and to a source checkout
the moment you pip install -r requirements.txt. mutagen is
GPL-2.0-or-later, which upgrades into GPL-3.0 without a problem.
The third-party pieces above keep their own licences, including Comfortaa under the SIL Open Font License 1.1.
NokiPod is not affiliated with Apple, Rockbox, Last.fm, MusicBrainz or LRCLIB. "iPod" is a trademark of Apple Inc.











