Skip to content

Version Packages#45

Merged
jvgomg merged 1 commit intomainfrom
changeset-release/main
Mar 23, 2026
Merged

Version Packages#45
jvgomg merged 1 commit intomainfrom
changeset-release/main

Conversation

@podkit-release-bot
Copy link
Copy Markdown
Contributor

@podkit-release-bot podkit-release-bot bot commented Mar 19, 2026

podkit v0.6.0

The biggest release since video sync landed — new commands, a reworked sync engine, a pile of bug fixes, and quality of life improvements that make podkit feel more solid day-to-day.

If you're upgrading from 0.5.x, everything is backwards-compatible. No config changes needed.

podkit doctor

This release introduces podkit doctor — the start of making podkit useful beyond just syncing content. The idea is simple: podkit already knows your iPod inside and out, so it should be able to diagnose and fix problems too.

The first check tackles something every iPod user has run into at some point: corrupted album artwork. Wrong covers, glitched images, artwork from a completely different album showing up — the iPod's artwork database is fragile and it doesn't take much to break it. podkit doctor detects integrity issues and rebuilds the artwork from your source collection automatically. See the artwork repair guide for the full walkthrough.

The second check finds orphan files — tracks sitting on the iPod that aren't referenced by the database, quietly eating up space. --verbose breaks them down by directory and extension; --format csv exports the full list for inspection.

More checks are coming. The goal is for podkit doctor to be a swiss army knife for iPod maintenance — useful even if you don't use podkit for syncing.

Highlights

podkit device scan — Discover connected iPods without guessing mount paths. Shows volume name, UUID, size, and mount status. Especially useful for finding the volume UUID needed to configure multi-device or Docker setups.

Graceful shutdown — Ctrl+C during sync now finishes the current operation and saves all completed work to the iPod database before exiting (code 130). Previously, Ctrl+C killed the process immediately, potentially leaving orphaned files and unsaved progress. A second Ctrl+C force-quits if you really need out. The database is also saved every 50 tracks during sync, so even a crash or force-quit loses minimal work.

Unified sync pipeline — Music and video sync now run through the same engine (SyncDifferSyncPlannerSyncExecutor). This means video sync gets all the reliability features music had — self-healing upgrades, error categorization with configurable retries, and consistent progress reporting. The ContentTypeHandler pattern makes it straightforward to add new content types down the road.

Under the Hood

  • Dual progress bars — sync output now shows both overall progress and per-file progress simultaneously, so you can see how far along a large sync is at a glance.
  • Album artwork cache cuts redundant artwork extractions by ~10x — one extraction per album instead of per track. The podkit doctor repair routine shares the same cache.
  • Full USB ejectpodkit device eject now fully detaches the USB device, not just unmounts the volume. On macOS, the iPod disappears from Disk Utility; on Linux, the USB device is powered off.
  • Incremental saves during video sync — the database saves every 10 completed video transfers, reducing data loss from interruptions during long video syncs.
  • The daemon forwards SIGINT to the sync child process on SIGTERM, so Docker's 10-second shutdown window is actually used for graceful draining instead of a hard kill.
  • Docker image layers optimized with COPY --chmod=755 instead of separate RUN chmod steps.

Bug Fixes

  • --delete flag was removing tracks of the wrong content type — syncing music could delete videos and vice versa
  • Episode/season number 0 was treated as unset (|| vs ??), causing S01E00 episodes to be deleted and re-added every sync
  • Track removal left audio/video files on disk — track.remove() now deletes the file by default
  • Duplicate source tracks caused an infinite metadata update loop — the diff engine now deduplicates, first match wins
  • Video sync overall progress counter was incrementing on every transcode sub-tick instead of once per video
  • podkit doctor orphan detection now skips macOS ._ resource fork files that were inflating the count
  • Graceful shutdown fixes: video sync interruptions could silently skip the database save; "Force quit" appeared immediately on first Ctrl+C via bun run; Ctrl+C during read-only phases now exits instantly

Full changelog

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

podkit@0.6.0

Minor Changes

  • 4dd7b44 Thanks @jvgomg! - Add podkit device scan command to discover connected iPod devices. Shows each iPod's volume name, UUID, size, and mount status — useful for finding the volume UUID needed to configure multi-device setups, especially in Docker.

  • d19d6e3 Thanks @jvgomg! - Add podkit doctor command for running diagnostic checks on an iPod, and podkit device reset-artwork for wiping artwork and clearing sync tags. podkit doctor runs all checks and reports problems; podkit doctor --repair artwork-integrity -c <collection> repairs by check ID using the source collection. @podkit/core exports resetArtworkDatabase and rebuildArtworkDatabase primitives, and a diagnostic framework in the diagnostics/ module built on a DiagnosticCheck interface (check + repair pattern). Includes a binary ArtworkDB parser and integrity checker.

  • b698a07 Thanks @jvgomg! - Add dual progress bars to sync output showing both overall and per-file progress simultaneously. Video sync now displays total file count alongside per-file transcode percentage and speed, so users can see how far along a large sync is. Music sync uses the same layout for consistency.

  • 2873f14 Thanks @jvgomg! - Add graceful shutdown handling for sync and doctor commands

    Pressing Ctrl+C during podkit sync now triggers a graceful shutdown: the current operation finishes, all completed tracks are saved to the iPod database, and the process exits cleanly with code 130. Previously, Ctrl+C killed the process immediately, potentially leaving orphaned files and unsaved work.

    • Sync: first Ctrl+C drains the current operation and saves; second Ctrl+C force-quits
    • Doctor: repair operations save partial progress on interrupt
    • Incremental saves: the database is now saved every 50 completed tracks during sync, reducing data loss from force-quits or crashes
    • New podkit doctor check: detects orphaned files on the iPod (files not referenced by the database) with optional cleanup via --repair orphan-files
  • 7624265 Thanks @jvgomg! - Unify sync pipeline with ContentTypeHandler pattern

    • Add generic ContentTypeHandler<TSource, TDevice> interface for media-type-specific sync logic
    • Add MusicHandler and VideoHandler implementations
    • Add UnifiedDiffer, UnifiedPlanner, and UnifiedExecutor generic pipeline components
    • Add shared error categorization and retry logic (error-handling.ts)
    • Add handler registry for looking up handlers by type string
    • Video sync now routes through the unified pipeline in the CLI
    • Video executor supports self-healing upgrades (preset-change, metadata-correction)
    • Video executor categorizes errors and supports configurable per-category retries
    • Fix album artwork cache incorrectly sharing artwork between tracks with and without artwork
    • Generic CollectionAdapter<TItem, TFilter> interface replaces separate music/video adapter contracts

Patch Changes

  • 67d1357 Thanks @jvgomg! - Fix --delete flag removing video tracks when syncing music (and vice versa). The delete flag now only considers tracks of the content type being synced.

  • 120a7b1 Thanks @jvgomg! - Improve podkit doctor orphan file reporting. Orphan detection now skips macOS ._ resource fork files that were inflating the count. Add --verbose output showing orphan breakdown by directory, file extension, and the 10 largest files. Add --format csv to export the full orphan file list for inspection.

  • 3f56a1b Thanks @jvgomg! - Fix video sync deleting and re-adding episodes with episode number 0 (e.g., S01E00)

    The || operator treated episode/season number 0 as falsy, converting it to undefined. This broke diff key matching for episode 0, causing every sync to delete and re-add the video. Changed to ?? (nullish coalescing) which only converts null/undefined, preserving 0 as a valid value.

  • 3db2bbb Thanks @jvgomg! - Fix graceful shutdown during sync: Ctrl+C now reliably saves completed work to the iPod database before exiting. Previously, video sync interruptions could silently skip the database save, causing the next sync to redo already-completed work. Also fix "Force quit" appearing immediately on first Ctrl+C when running via bun run. Ctrl+C during read-only phases (scanning, diffing) now exits instantly instead of showing a misleading "finishing current operation" message.

  • 1c98ac2 Thanks @jvgomg! - Fix video sync overall progress counter incrementing on every transcode sub-progress tick instead of once per video

  • 143e314 Thanks @jvgomg! - Fully detach USB device on eject so iPod disappears from Disk Utility (macOS) and system (Linux/Docker)

    Previously, eject only unmounted the volume but left the physical disk device attached. On macOS, the iPod would still appear in Disk Utility after ejecting. On Linux, the USB device could remain visible.

    Now eject resolves the whole-disk identifier and fully detaches the USB device:

    • macOS: diskutil eject targets the whole disk (e.g., disk5) instead of the volume
    • Linux: udisksctl power-off targets the whole disk (e.g., /dev/sda) and is also called after the umount fallback path
  • Updated dependencies [8e11397, 8fdf618, d19d6e3, 3f56a1b, 120a7b1, 143e314, 2873f14, 66560a9, 7624265, 632f360]:

    • @podkit/core@0.6.0

@podkit/core@0.6.0

Minor Changes

  • d19d6e3 Thanks @jvgomg! - Add podkit doctor command for running diagnostic checks on an iPod, and podkit device reset-artwork for wiping artwork and clearing sync tags. podkit doctor runs all checks and reports problems; podkit doctor --repair artwork-integrity -c <collection> repairs by check ID using the source collection. @podkit/core exports resetArtworkDatabase and rebuildArtworkDatabase primitives, and a diagnostic framework in the diagnostics/ module built on a DiagnosticCheck interface (check + repair pattern). Includes a binary ArtworkDB parser and integrity checker.

  • 2873f14 Thanks @jvgomg! - Add graceful shutdown handling for sync and doctor commands

    Pressing Ctrl+C during podkit sync now triggers a graceful shutdown: the current operation finishes, all completed tracks are saved to the iPod database, and the process exits cleanly with code 130. Previously, Ctrl+C killed the process immediately, potentially leaving orphaned files and unsaved work.

    • Sync: first Ctrl+C drains the current operation and saves; second Ctrl+C force-quits
    • Doctor: repair operations save partial progress on interrupt
    • Incremental saves: the database is now saved every 50 completed tracks during sync, reducing data loss from force-quits or crashes
    • New podkit doctor check: detects orphaned files on the iPod (files not referenced by the database) with optional cleanup via --repair orphan-files
  • 66560a9 Thanks @jvgomg! - Unify sync pipeline: CLI presenter pattern, naming symmetry, tests, and cleanup (TASK-186)

    • Add ContentTypePresenter pattern for content-type-agnostic CLI sync orchestration
    • Rename music-specific symbols with Music prefix (computeDiff→computeMusicDiff, DefaultSyncExecutor→MusicExecutor, etc.)
    • Rename generic pipeline from Unified prefix to Sync prefix (UnifiedDiffer→SyncDiffer, UnifiedPlanner→SyncPlanner, UnifiedExecutor→SyncExecutor)
    • Remove unused handler registry (registerHandler, getHandler, getAllHandlers, clearHandlers)
    • Remove dead video pipeline code (PlaceholderVideoSyncExecutor, createVideoExecutor)
    • Fix TranscodeProgress.speed type inconsistency (string→number)
    • Add 'space-constraint' to SyncWarningType union
    • Add completedCount to ExecutorProgress
    • Add 47 new tests for VideoHandler, MusicHandler, and SyncExecutor
    • All old symbol names preserved as backward-compatible aliases
  • 7624265 Thanks @jvgomg! - Unify sync pipeline with ContentTypeHandler pattern

    • Add generic ContentTypeHandler<TSource, TDevice> interface for media-type-specific sync logic
    • Add MusicHandler and VideoHandler implementations
    • Add UnifiedDiffer, UnifiedPlanner, and UnifiedExecutor generic pipeline components
    • Add shared error categorization and retry logic (error-handling.ts)
    • Add handler registry for looking up handlers by type string
    • Video sync now routes through the unified pipeline in the CLI
    • Video executor supports self-healing upgrades (preset-change, metadata-correction)
    • Video executor categorizes errors and supports configurable per-category retries
    • Fix album artwork cache incorrectly sharing artwork between tracks with and without artwork
    • Generic CollectionAdapter<TItem, TFilter> interface replaces separate music/video adapter contracts

Patch Changes

  • 8e11397 Thanks @jvgomg! - Add album-level artwork cache to sync executor, reducing redundant artwork extractions by ~10x (one extraction per album instead of per track). The cache is shared with the doctor repair routine via a new AlbumArtworkCache abstraction.

  • 8fdf618 Thanks @jvgomg! - Fix infinite metadata update loop when source collection contains duplicate tracks

    When a source collection had multiple entries with the same (artist, title, album) but different track numbers, each duplicate would generate a separate metadata-correction operation against the same iPod track. After applying one update, the next sync would see the other duplicate's metadata as a diff — causing an endless update cycle.

    The diff engine now skips duplicate source tracks that match an already-claimed iPod track. The first source entry wins; subsequent duplicates are ignored.

  • 3f56a1b Thanks @jvgomg! - Fix video sync deleting and re-adding episodes with episode number 0 (e.g., S01E00)

    The || operator treated episode/season number 0 as falsy, converting it to undefined. This broke diff key matching for episode 0, causing every sync to delete and re-add the video. Changed to ?? (nullish coalescing) which only converts null/undefined, preserving 0 as a valid value.

  • 120a7b1 Thanks @jvgomg! - Fix track removal leaving orphan files on iPod. When removing tracks during sync (both music and video), the audio/video file was deleted from the iPod database but left on disk, accumulating orphan files over time. track.remove() now deletes the file by default. Pass { keepFile: true } to preserve the file on disk.

  • 143e314 Thanks @jvgomg! - Fully detach USB device on eject so iPod disappears from Disk Utility (macOS) and system (Linux/Docker)

    Previously, eject only unmounted the volume but left the physical disk device attached. On macOS, the iPod would still appear in Disk Utility after ejecting. On Linux, the USB device could remain visible.

    Now eject resolves the whole-disk identifier and fully detaches the USB device:

    • macOS: diskutil eject targets the whole disk (e.g., disk5) instead of the volume
    • Linux: udisksctl power-off targets the whole disk (e.g., /dev/sda) and is also called after the umount fallback path
  • 632f360 Thanks @jvgomg! - Add incremental database saves during video sync, saving every 10 completed transfers by default. Reduces data loss if the process is interrupted during a large video sync.

@podkit/daemon@0.2.2

Patch Changes

@podkit/docker@0.2.3

Patch Changes

@podkit-release-bot podkit-release-bot bot force-pushed the changeset-release/main branch 7 times, most recently from 48f3797 to 9b815ad Compare March 22, 2026 22:31
@podkit-release-bot podkit-release-bot bot force-pushed the changeset-release/main branch from 9b815ad to ad51016 Compare March 23, 2026 00:54
@jvgomg jvgomg merged commit 5188193 into main Mar 23, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant