Skip to content

Agent SOP: Batch Import

Process newly acquired music (downloaded albums, loose tracks, zips) into an organized structure ready for Rekordbox import.

Goal: After this SOP, any processed track can be imported into Rekordbox with Artist, Title, Album, Year, Track Number, and Label displaying correctly. Genre is handled separately via the genre classification SOP.

Paste into your agent to start:

Process the new music in [/path/to/folder] for Rekordbox import.

Constraints

  • Tags are source of truth. Write tags before renaming — filenames are derived from tags.
  • Never set genre. Leave genre tags empty; handled via genre classification SOP.
  • Stop on ambiguity. Never guess artist names, album years, or label names — ask the user.
  • Process album by album. Complete one fully before starting the next.
  • WAV dual-tag rule. WAV files need both ID3v2 and RIFF INFO in sync. write_file_tags handles this automatically.
  • Verify before moving. Confirm tags and filenames before moving to final location.

Prerequisites

Tool Purpose
reklawdbox MCP Tag reading/writing, Discogs/Beatport lookups, cover art embedding

lookup_discogs, lookup_beatport, lookup_bandcamp, lookup_musicbrainz, read_file_tags, write_file_tags, embed_cover_art, and extract_cover_art are MCP tool calls.


Phase 1: Assessment

Step 1: Discover library structure

Before importing, understand how the destination library is organized. Use read_library to find the content root, then scan 2 levels deep:

Terminal window
find "/path/to/content-root" -maxdepth 2 -type d | head -80

Identify:

  • Album directory — which top-level directory contains Artist/Album (Year)/ subdirectories?
  • Loose track directory — which top-level directory contains batch folders with flat audio files?

Present your findings to the user and confirm before proceeding:

Your library structure appears to be:
- Albums: {albums-dir}/{Artist}/{Album (Year)}/
- Loose tracks: {loose-dir}/{batch-name}/
Is this correct? What should this batch's loose tracks folder be named?

Use the confirmed paths for all move operations in Phase 2 Step 9 and Phase 3 Step 4. If the library is empty or the structure is unclear, ask the user to define their preferred convention.

Step 2: List the batch directory

Terminal window
ls -la "/path/to/batch/"

Categorize: directories (albums/EPs), audio files at root (loose tracks), zip files (need extraction).

Step 3: Handle zip files

Extract all root-level zips. Already-extracted zips (matching directory exists with files) are archived without re-extraction. Failed extractions go to _failed_zips/.

Terminal window
cd "/path/to/batch"
mkdir -p "_processed_zips" "_failed_zips"
find . -maxdepth 1 -type f -name "*.zip" -print0 | while IFS= read -r -d '' zip; do
zip="${zip#./}"
dir="${zip%.zip}"
if [ -d "$dir" ] && find "$dir" -type f -print -quit | grep -q .; then
mv "$zip" "_processed_zips/$zip"
echo "Archived already-extracted: $zip"
continue
fi
tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/batch-import-unzip.XXXXXX")"
if unzip -o "$zip" -d "$tmp_dir"; then
mkdir -p "$dir"
find "$tmp_dir" -mindepth 1 -maxdepth 1 -exec mv -n {} "$dir"/ \;
if find "$dir" -type f -print -quit | grep -q .; then
mv "$zip" "_processed_zips/$zip"
echo "Extracted: $zip"
else
mv "$zip" "_failed_zips/$zip"
echo "No files extracted: $zip"
fi
else
mv "$zip" "_failed_zips/$zip"
echo "Extraction failed: $zip"
fi
rm -rf "$tmp_dir"
done

Step 4: Report to user

Summarize what was found: album directories, loose tracks, zip results.


Phase 2: Process Albums

For each album subdirectory, follow these steps in order.

Step 1: Survey current state

Terminal window
ls -la "/path/to/batch/Album Directory/"

Read tags for all files:

read_file_tags(directory="/path/to/batch/Album Directory/")

Note: current filename pattern, which tags are present, whether cover art exists.

Step 2: Parse directory name

Common incoming patterns:

  • Artist Name - Album Name
  • Artist Name - Album Name (Year)
  • Artist Name - Album Name [FLAC 24-96]

Extract: artist, album name, year (if present).

Step 3: Determine album type

  • Same artist on all tracks → Single Artist
  • Different artists per track → VA Compilation
  • “Various Artists” in dir name → VA Compilation

For VA: label name is required. Check Publisher tag, directory name, or look up.

Step 4: Look up metadata

lookup_discogs(artist="Artist Name", title="First Track Title", album="Album Name")

If no Discogs result, try Beatport:

lookup_beatport(artist="Artist Name", title="First Track Title")

If still missing data (common with self-released and digital-only music), try Bandcamp:

lookup_bandcamp(artist="Artist Name", title="First Track Title")

If you have already found the Bandcamp release page, prefer passing it directly:

lookup_bandcamp(artist="Artist Name", title="First Track Title", url="https://artist.bandcamp.com/album/release-slug")

Bandcamp is the authoritative source for Bandcamp-sourced downloads and is often the only source for self-released music. Direct Bandcamp URLs bypass fragile global search and refresh the cache for the artist/title pair. Use the album page where the release year is listed; the tool selects the matching track from the page metadata.

If still missing year or label, try MusicBrainz as a final fallback:

lookup_musicbrainz(artist="Artist Name", title="First Track Title")

Use results for: release year, label name, artist/album spelling verification.

Lookup miss vs tool failure. The fallback chain above only applies when an earlier tool returns no match. If lookup_discogs instead returns an Auth URL (auth pending or expired session), that is not a miss — it is a one-click remediation. Open the URL for the user (open '<auth-url>' on macOS), wait for them to authorize on Discogs, then call lookup_discogs again; the new session is picked up automatically. For commercial releases, do not substitute Bandcamp/MusicBrainz for an auth click — Discogs is materially more authoritative for label and catalog data. (Bandcamp is the right choice when Discogs genuinely has no result, e.g. self-released and digital-only music.)

Stop and ask on: multiple matches with different years, no results and year/label unknown, ambiguous artist.

Never use lookup results for genre.

Step 5: Write tags

Use write_file_tags for all tag writes. It handles WAV dual-tagging automatically.

Album-wide + per-track tags:

write_file_tags(writes=[
{path: "/path/to/album/01 original.flac", tags: {
artist: "Track Artist", title: "Track Title", track: "1",
album: "Album Name", year: "YEAR", publisher: "Label Name",
album_artist: "Artist Name"
}},
...
])

Per-track tags — parse from filenames. Common incoming patterns:

Pattern Parse as
Artist - Album - NN Title.wav Track N: Artist - Title
NN Artist - Title.wav Track N: Artist - Title
NN Title.wav Track N: [AlbumArtist] - Title
NN. Title.wav Track N: [AlbumArtist] - Title

Step 6: Verify tags

read_file_tags(directory="/path/to/album/")

Confirm every file has: Artist, Title, Track, Album, Year.

Step 7: Rename files from tags

Construct target filenames from tags: NN Artist - Title.ext

Use mv -n (no-clobber) for each file. Validate the target filename is non-empty before renaming.

Terminal window
mv -n "/path/to/album/old filename.flac" "/path/to/album/01 Artist Name - Track Title.flac"

If rename produces unexpected results, stop and check tags — rename depends entirely on tag correctness.

Step 8: Embed cover art

Check for existing cover art in the directory:

Terminal window
find "/path/to/album/" -maxdepth 1 -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) -print

Single obvious cover (cover.jpg, front.jpg, folder.jpg):

embed_cover_art(image_path="/path/to/album/cover.jpg", targets=["/path/to/album/01 Artist - Track.flac", ...])

Multiple images: Ask user which is the cover.

No images: Source a cover. Always embed when a cover can be obtained.

  1. Try lookup_bandcamp(artist="...", title="...", url="https://artist.bandcamp.com/album/...") when a Bandcamp page is known, otherwise use lookup_bandcamp(artist="...", title="...").
    • If the result includes a cover_image URL, use it.
    • Otherwise, if the result includes a bandcamp_url, fetch that page and extract the og:image URL (this is the full-size artwork).
  2. If no Bandcamp result, try lookup_discogs(...).
    • If the result includes a cover_image, use it.
    • Otherwise, if the result includes a release url, fetch that page and extract the primary release image.
  3. Download and embed:
Terminal window
curl -sL -o "/path/to/album/cover.jpg" "COVER_URL"
embed_cover_art(image_path="/path/to/album/cover.jpg", targets=["/path/to/album/01 Artist - Track.flac", ...])

Only fall back to “note for user to source manually” when neither Bandcamp nor Discogs returns any URL at all.

Step 9: Create target directory and move files

Use the album directory convention established in Phase 1 Step 1. Determine clean directory name (strip tech specs, add year, clean special chars).

Terminal window
# Single Artist — use the confirmed album directory
target_dir="/path/to/albums-dir/Artist Name/Album Name (Year)"
# Or VA, use this target instead
# target_dir="/path/to/albums-dir/Various Artists/Label Name/Album Name (Year)"
mkdir -p "$target_dir"
# Move audio + cover art
find "/path/to/batch/Old Dir" -maxdepth 1 -type f \
\( -iname "*.flac" -o -iname "*.wav" -o -iname "*.mp3" \
-o -iname "*.m4a" -o -iname "*.aac" -o -iname "*.aiff" \) \
-exec mv -n {} "$target_dir/" \;
find "/path/to/batch/Old Dir" -maxdepth 1 -type f -iname "cover.*" \
-exec mv -n {} "$target_dir/" \;
# Remove old empty directory
rmdir "/path/to/batch/Old Dir"

Step 10: Verify final state

Keep using the target_dir selected in Step 9. The shell expands that variable:

Terminal window
ls -la "$target_dir/"

For the MCP call, substitute that same selected directory’s literal path; MCP arguments do not expand shell variables:

read_file_tags(directory="/path/to/the-selected-target-directory/")

Confirm: files in correct location, NN Artist - Title.ext format, all tags present, VA has label subdirectory, cover art embedded.


Phase 3: Process Loose Tracks

For audio files at the root of the batch directory.

Step 1: Clean filenames

Strip store-generated (Original), (Original Mix), and (Original Version) suffixes. Keep other parenthetical info ((Remix), (Edit), (Original Club Mix), etc.):

Terminal window
cd "/path/to/batch"
find . -maxdepth 1 -type f \( -name "* (Original Mix).*" -o -name "* (Original Version).*" -o -name "* (Original).*" \) -print0 | while IFS= read -r -d '' f; do
new_name="$(echo "$f" | sed -E 's/ \(Original( (Mix|Version))?\)//')"
mv -n "$f" "$new_name"
done

Expected format: Artist Name - Track Title.ext. If unparseable, ask user.

Step 2: Read/write tags

For each loose track, read existing tags:

read_file_tags(paths=["/path/to/batch/Artist - Title.wav"])

If tags are missing, look up with lookup_discogs(...) / lookup_beatport(...) / lookup_bandcamp(...) / lookup_musicbrainz(...). Bandcamp is often the only source for self-released and digital-only music.

Write tags (include album — almost always available from the source release):

write_file_tags(writes=[{
path: "/path/to/batch/Artist - Title.wav",
tags: {artist: "Artist Name", title: "Track Title", album: "Release Name", publisher: "Label Name", year: "YEAR"}
}])

Step 3: Embed cover art

Always embed cover art when a cover can be obtained — regardless of format. The WAV caveat is about Rekordbox ingestion, not about whether to embed: tags are still useful for other apps, format conversions, and future tooling.

Check for cover_Artist Name - Track Title.jpg files. If found, embed and skip to the WAV note below:

embed_cover_art(image_path="/path/to/cover.jpg", targets=["/path/to/track.flac"])

If no local cover file exists, source one:

  1. Try lookup_bandcamp(artist="...", title="...", url="https://artist.bandcamp.com/album/...") when a Bandcamp page is known, otherwise use lookup_bandcamp(artist="...", title="...").
    • If the result includes a cover_image URL, use it.
    • Otherwise, if the result includes a bandcamp_url, fetch that page and extract the og:image URL (this is the full-size artwork).
  2. If no Bandcamp result, try lookup_discogs(...).
    • If the result includes a cover_image, use it.
    • Otherwise, if the result includes a release url, fetch that page and extract the primary release image.
  3. Download and embed:
Terminal window
curl -sL -o "/path/to/cover_Artist - Title.jpg" "COVER_URL"
embed_cover_art(image_path="/path/to/cover_Artist - Title.jpg", targets=["/path/to/Artist - Title.wav"])

WAV files: Keep the cover image file alongside the audio — Rekordbox cannot read cover art from WAV tags, so the user needs the image colocated for manual import into Rekordbox. The embedded tag is still written. For other formats (FLAC, MP3, AIFF), clean up the downloaded image after embedding.

Only fall back to “note for user to source manually” when neither Bandcamp nor Discogs returns any URL at all.

Step 4: Move loose tracks

Use the loose track destination established in Phase 1 Step 1.

Terminal window
mkdir -p "/path/to/loose-dir/batch-name"
mv -n "/path/to/batch/Artist - Title.wav" "/path/to/loose-dir/batch-name/"

Phase 4: Multi-Disc Albums

If an album has disc subdirectories (CD1/, CD2/, Disc 1/, etc.):

  • Track numbers restart at 01 per disc
  • Cover art at album root (not in disc folders)
  • Set Disc Number tag on each track via write_file_tags
  • Album-wide tags (album, year, publisher) go on all tracks across all discs

Phase 5: Final Verification

Summarize: albums processed (single artist vs VA), loose tracks processed, any unresolved items, WAV tracks whose covers need manual import into Rekordbox (tag is embedded; colocated image file required for Rekordbox), and next steps (import, collection audit SOP, genre classification SOP).


Decision Reference

Proceed automatically when

  • Artist clearly identified in tags, filename, or directory name
  • Year present in tags, directory name, or single clear Discogs match
  • Label present in tags or Discogs (for VA)
  • Single artist with consistent tags across album

Stop and ask when

  • Multiple matches with different years
  • No results and year/label unknown
  • VA album but label unknown
  • Ambiguous: collaboration vs VA vs single artist
  • Multiple images — which is album cover?
  • Conflicting metadata between tags and filenames
  • Unparseable filenames

Common Incoming Filename Patterns

Album tracks

Pattern Parse as
Artist - Album - NN Title.wav Track N: Artist - Title
Artist - Album - NN. Title.wav Track N: Artist - Title
NN Artist - Title.wav Track N: Artist - Title
NN. Artist - Title.wav Track N: Artist - Title
NN Title.wav Track N: [AlbumArtist] - Title
NN. Title.wav Track N: [AlbumArtist] - Title
Artist - Album - NN AX. Title.wav Track N: Artist - Title (vinyl)

Loose tracks

Pattern Status
Artist - Title.wav Correct
Artist - Title (Remix Info).wav Correct
Artist, Artist B - Title.wav Correct
Artist - Title (Original Mix).wav Remove (Original) / (Original Mix) / (Original Version) suffix
Title.wav Missing artist — ask user