A self-hosted web application to organize your media library by identifying files using TVDB or TMDB and moving them with proper naming conventions
Features • Screenshots • Installation • Configuration • Development
- File Browser - Browse your downloads folder with parsed information (title, year, season, episode)
- TVDB & TMDB Integration - Search and identify movies/TV shows using TVDB or TMDB APIs
- Auto-Match - Automatically matches files to search results based on filename similarity
- Batch Processing - Identify and move multiple files at once
- Multiple TV Series - Handle episodes from different series in a single workflow
- Smart Renaming - Automatically renames files following media server conventions (Plex/Jellyfin/Emby compatible)
- Plex Integration - Trigger Plex library refresh directly from the app after moving files
- Configurable Paths - Set custom download and media library paths
For instant file moves (no copy+delete), mount downloads and media under the same parent directory:
docker run -d \
--name unmove \
-p 3000:3000 \
-e PUID=99 \
-e PGID=100 \
-v /mnt/user:/data \
-v /path/to/config:/config \
-e DOWNLOAD_PATH=/data/downloads \
-e MEDIA_PATH=/data/media \
yusseiin/unmove:latestWhy? When downloads and media are on the same Docker volume, moving files is instant (just a rename). With separate volumes, Docker must copy the file then delete it.
version: "3.8"
services:
unmove:
image: yusseiin/unmove:latest
container_name: unmove
ports:
- "3000:3000"
environment:
- PUID=99
- PGID=100
- DOWNLOAD_PATH=/data/downloads
- MEDIA_PATH=/data/media
# Optional: Plex integration
- PLEX_URL=http://192.168.1.100:32400
- PLEX_TOKEN=your-plex-token
volumes:
- /mnt/user:/data # Single mount for instant moves
- /path/to/config:/config
restart: unless-stoppedIf you prefer separate volume mounts (moves will copy+delete instead of instant):
docker run -d \
--name unmove \
-p 3000:3000 \
-e PUID=99 \
-e PGID=100 \
-v /path/to/downloads:/downloads \
-v /path/to/media:/media \
-v /path/to/config:/config \
-e DOWNLOAD_PATH=/downloads \
-e MEDIA_PATH=/media \
yusseiin/unmove:latestAvailable in Community Applications. Search for "unmove" or install manually using the Docker Hub image yusseiin/unmove:latest.
For instant moves on Unraid, use the recommended configuration that mounts /mnt/user as a single volume.
⚠️ Important Note about Instant Moves on UnraidEven with a single Docker volume mount, instant moves will only work if both the downloads and media folders are on the same physical disk. Unraid's
/mnt/useris a virtual filesystem (shfs/fuse) that spans multiple disks. If your downloads are ondisk1and media is ondisk2, the system must copy+delete the file regardless of the Docker configuration.To ensure instant moves:
- Configure both shares (downloads and media) to use the same disk in Unraid's share settings, OR
- Mount a specific disk directly:
-v /mnt/disk1:/datainstead of/mnt/user:/dataIf your files are on different physical disks, the application will automatically fall back to copy+delete (which is slower but works correctly).
| Variable | Default | Description |
|---|---|---|
PUID |
99 | User ID for file permissions |
PGID |
100 | Group ID for file permissions |
DOWNLOAD_PATH |
/data/downloads |
Path to downloads inside container |
MEDIA_PATH |
/data/media |
Path to media library inside container |
PLEX_URL |
- | Plex server URL (e.g., http://192.168.1.100:32400) |
PLEX_TOKEN |
- | Plex authentication token (how to get it) |
Recommended (Instant Moves):
| Container Path | Description |
|---|---|
/data |
Parent directory containing both downloads and media (enables instant moves) |
/config |
Configuration storage |
With DOWNLOAD_PATH=/data/downloads and MEDIA_PATH=/data/media
Legacy (Separate Volumes):
| Container Path | Description |
|---|---|
/downloads |
Your downloads folder (source) |
/media |
Your media library (destination) |
/config |
Configuration storage |
With DOWNLOAD_PATH=/downloads and MEDIA_PATH=/media
You can use either TVDB, TMDB, or both as metadata providers. Configure your preferred provider in the application settings.
- Create a free account at thetvdb.com
- Go to API Information and generate an API key
- Set the
TVDB_API_KEYenvironment variable
- Create a free account at themoviedb.org
- Go to API Settings and request an API key
- Set the
TMDB_API_KEYenvironment variable
UnMove can trigger Plex library refreshes after moving files, so Plex immediately picks up your newly organized media.
- Get your Plex authentication token (instructions)
- Set the environment variables:
PLEX_URL: Your Plex server URL (e.g.,http://192.168.1.100:32400)PLEX_TOKEN: Your Plex authentication token
Once configured, click the Plex icon in the top navigation bar to:
- View all your Plex library sections
- Refresh individual libraries or all libraries at once
Settings are accessible via the gear icon in the top-right corner of the interface and are stored in /config/unmove-config.json.
| Setting | Default | Description |
|---|---|---|
| Language | en |
Interface language and folder naming. Options: en (English), it (Italian). Affects season folder names (e.g., "Season 01" vs "Stagione 01") |
| Series Metadata Provider | tvdb |
Metadata provider for TV series. Options: tvdb (TVDB), tmdb (TMDB). Can be switched per-search in the identify dialogs |
| Movies Metadata Provider | tmdb |
Metadata provider for movies. Options: tvdb (TVDB), tmdb (TMDB). Can be switched per-search in the identify dialogs |
| Series Base Folders | [] |
List of base folders for TV series. Each folder has a name and preserveQualityInfo setting to keep quality/encoding info in filenames |
| Movies Base Folders | [] |
List of base folders for movies. Each folder has a name and preserveQualityInfo setting to keep quality/encoding info in filenames |
| Movie Folder Structure | name |
How movie files are organized. Options: name (Movie Name (Year)/Movie.mkv), year (Year/Movie.mkv), or none (Movie.mkv directly in base folder) |
{
"language": "en",
"seriesMetadataProvider": "tvdb",
"moviesMetadataProvider": "tmdb",
"seriesBaseFolders": [
{ "name": "TV Series", "preserveQualityInfo": true },
{ "name": "Anime", "preserveQualityInfo": false }
],
"moviesBaseFolders": [
{ "name": "Movies", "preserveQualityInfo": false },
{ "name": "4K Movies", "preserveQualityInfo": true }
],
"movieFolderStructure": "name"
}TV Series with preserveQualityInfo: true on the folder:
/media/TV Series/Breaking Bad (2008)/Season 01/Breaking Bad - S01E01 - Pilot [1080p.x264].mkv
TV Series with preserveQualityInfo: false on the folder:
/media/Anime/Naruto (2002)/Season 01/Naruto - S01E01 - Enter Naruto Uzumaki.mkv
Movies with preserveQualityInfo: true and movieFolderStructure: "name":
/media/4K Movies/Avatar - The Way of Water (2022)/Avatar - The Way of Water (2022) [2160p.x265].mkv
Movies with preserveQualityInfo: false and movieFolderStructure: "year":
/media/Movies/2022/Avatar - The Way of Water (2022).mkv
Movies with movieFolderStructure: "none" (no subfolder):
/media/Movies/Avatar - The Way of Water (2022).mkv
- Open the web interface at
http://your-server:3000 - Click the gear icon and select your preference
- Browse your downloads folder
- Select files to identify
- Use "Identify" for single files or "Batch Identify" for multiple files
- Review the matches and move files to your media library
- Node.js 22+
- pnpm
# Clone the repository
git clone https://github.com/yusseiin/unmove.git
cd unmove
# Install dependencies
pnpm install
# Set environment variables
cp .env.example .env.local
# Edit .env.local with your paths
# Run development server
pnpm devOpen http://localhost:3000 to view the app.
# Build for production
pnpm build
# Start production server
pnpm startdocker build --build-arg NEXT_PUBLIC_VERSION=0.0.1 -t unmove .- Next.js 16 - React framework
- React 19 - UI library
- Tailwind CSS - Styling
- shadcn/ui - UI components
- TVDB API - Media database
- TMDB API - Media database
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions


