Custom Script Documentation
March 8, 2026 · View on GitHub
Tidarr supports two custom shell scripts that allow you to perform custom operations during the post-processing pipeline:
custom-script.sh- Runs before files are moved to the librarycustom-post-script.sh- Runs after files are moved to the library
Pipeline Order
Download → Beets → ReplayGain → Permissions → custom-script.sh → Move to Library → custom-post-script.sh → Plex/Jellyfin/Navidrome Scan → Notifications
Pre-Move Script: custom-script.sh
How it works:
- Create a shell script named
custom-script.shin your config folder (the mountedshared/volume) - The script will be automatically detected and executed during post-processing
- The script runs before files are moved to the library
Execution context:
- OS Environment: Alpine Linux 3.21
- Shell:
/bin/sh(Alpine's default shell - BusyBox ash) - Available tools: bash, ffmpeg, curl, wget, python3, beets, and standard Alpine utilities
- Working directory: The script runs in the
/shared/.processing/{item_id}directory where files are temporarily stored
Available environment variables:
PROCESSING_PATH # Path to the .processing directory where files are located
ITEM_TYPE # Type of content: album, track, video, playlist, mix, artist, etc.
ITEM_URL # Tidal URL of the item being processed
ITEM_NAME # Human-readable name of the item (e.g. playlist/mix title)
Example script:
#!/bin/sh
# custom-script.sh - Example pre-move processing script
echo "Processing ${ITEM_TYPE} from ${ITEM_URL}"
echo "Files located in: ${PROCESSING_PATH}"
# Example 1: Convert FLAC to MP3 for mobile sync
find . -name "*.flac" -type f | while read file; do
echo "Converting: $file"
ffmpeg -i "$file" -codec:a libmp3lame -qscale:a 2 "${file%.flac}.mp3"
done
# Example 2: Custom tagging or metadata modifications
# Your custom processing logic here...
echo "Custom processing complete!"
Use cases:
- Convert FLAC to additional formats (MP3, AAC, etc.)
- Apply custom tagging or metadata modifications
- Generate thumbnails or additional artwork
- Modify files before they reach the library
File location: /your/docker/path/to/tidarr/config/custom-script.sh
Post-Move Script: custom-post-script.sh
How it works:
- Create a shell script named
custom-post-script.shin your config folder (the mountedshared/volume) - The script will be automatically detected and executed after files are moved to the library
- The script runs before library scans (Plex/Jellyfin/Navidrome) and notifications
Execution context:
- OS Environment: Alpine Linux 3.21
- Shell:
/bin/sh(Alpine's default shell - BusyBox ash) - Available tools: bash, ffmpeg, curl, wget, python3, beets, and standard Alpine utilities
- Working directory: The script runs in the library directory (e.g.,
/music)
Available environment variables:
DESTINATION_PATH # The library path where files were moved (e.g., /music)
FOLDERS_MOVED # Comma-separated list of folders that were moved (relative to DESTINATION_PATH)
ITEM_TYPE # Type of content: album, track, video, playlist, mix, artist, etc.
ITEM_URL # Tidal URL of the item being processed
ITEM_NAME # Human-readable name of the item (e.g. playlist/mix title)
Example script:
#!/bin/sh
# custom-post-script.sh - Example post-move processing script
echo "Item moved to: ${DESTINATION_PATH}"
echo "Folders: ${FOLDERS_MOVED}"
echo "Type: ${ITEM_TYPE}"
# Example 1: Move playlists to a separate directory
if [ "$ITEM_TYPE" = "playlist" ] || [ "$ITEM_TYPE" = "mix" ]; then
echo "Moving playlist files to /playlists..."
mv "${DESTINATION_PATH}/playlists/"* /playlists/ 2>/dev/null || true
fi
# Example 2: Send custom notification with final path
curl -X POST "https://your-webhook.com/notify" \
-H "Content-Type: application/json" \
-d "{\"type\": \"$ITEM_TYPE\", \"path\": \"$DESTINATION_PATH\", \"folders\": \"$FOLDERS_MOVED\"}"
# Example 3: Sync to external storage
# rsync -av "${DESTINATION_PATH}/" /mnt/backup/music/
echo "Post-processing complete!"
Use cases:
- Move specific content types to different directories (playlists, mixes, etc.)
- Sync files to external storage or backup locations
- Send notifications with final file paths
- Trigger external automation systems
- Update external databases or catalogs
File location: /your/docker/path/to/tidarr/config/custom-post-script.sh
Important Notes
- Both scripts are optional - Tidarr works normally without them
- Scripts are made executable automatically (chmod +x is applied)
- Script errors won't stop the download pipeline - processing continues regardless
- All stdout/stderr output is logged and visible in the download terminal dialog
- Scripts run sequentially, not in parallel
Docker Volume Example
To use the playlist separation feature mentioned above, you need to mount an additional volume:
services:
tidarr:
volumes:
- /path/to/config:/shared
- /path/to/music:/music
- /path/to/playlists:/playlists # Additional volume for playlists
Then in your custom-post-script.sh:
#!/bin/sh
if [ "$ITEM_TYPE" = "playlist" ] || [ "$ITEM_TYPE" = "mix" ]; then
mv "${DESTINATION_PATH}/playlists/"* /playlists/ 2>/dev/null || true
fi