A modern CLI tool that automatically organizes and moves your files based on configurable categories. No manual sorting, no chaos.
Define categories with extensions, filters, and destinations in a simple YAML file.
Monitor directories in real-time and move files automatically as they appear.
Interactive batch picker to select and revert any past operation. Pass a batch ID to skip the picker.
--dry-run on move and undo, preview before committing.
rename, overwrite, skip, or hash_check per category.
Regex, glob, age, and size filters; not exclusion; composable any/all logic.
extensions: [all] matches any file type, combine with organize-by: "{ext}" for a catch-all sorter.
Build subdirectory structures with tokens: {ext}, {mod-year}, {mod-month}, {size-range}, and more.
Name transforms, system info, timestamps, hashes, and sequences, e.g. {mod-date}_{name-slug}.{ext}.
move, copy, or symlink per category, to back up or link files without touching the originals.
Match and organize by content (magic bytes), not just the extension: a .jpg that is really a PNG is sorted correctly with filter.mime and {mime-type}.
Rename files on arrival using the token engine: rename: "{mod-date}_{name}.{ext}".
movelooper edit opens a two-panel TUI editor with undo, redo, and validation on save.
Bootstrap a new config from a built-in template in the TUI editor: movelooper edit -o movelooper.yaml.
Split categories across multiple YAML files with import:. Use movelooper edit to open the merged config in the interactive TUI editor.
Stay on the latest release with movelooper self-update.
# 1. Download the binary for your platform from the releases page # https://github.com/lucasassuncao/movelooper/releases # 2. Extract and add to your PATH, then create a config: movelooper edit -o movelooper.yaml
git clone https://github.com/lucasassuncao/movelooper.git cd movelooper go build -o movelooper . ./movelooper edit -o movelooper.yaml
Scaffold a config from a template in the TUI editor, then run.
movelooper edit -o movelooper.yaml # create a config from a template in the TUI movelooper --dry-run # preview what would be moved movelooper # move files movelooper watch # real-time monitoring
configuration: logging: output: both level: info watch: delay: 5m categories: - name: "images" source: path: "C:\\Users\\you\\Downloads" extensions: [jpg, jpeg, png, gif, webp] filter: not: - match: glob: "screenshot_*" age: min: 10m destination: path: "C:\\Users\\you\\Images" conflict-strategy: rename organize-by: "{ext}"
configuration: logging: output: both level: info categories: - name: "photos-backup" source: path: "C:\\Users\\you\\Downloads" extensions: [jpg, jpeg, raw] destination: path: "C:\\Users\\you\\Backup\\photos" action: copy # keep original in Downloads rename: "{mod-date}_{name}.{ext}" # photo.jpg → 2025-04-16_photo.jpg conflict-strategy: skip
configuration: logging: output: both level: info categories: - name: "everything-else" source: path: "C:\\Users\\you\\Downloads" extensions: [all] # matches any file type destination: path: "C:\\Users\\you\\Sorted" conflict-strategy: hash_check organize-by: "{ext}"
movelooper.yaml (main file)
configuration: logging: output: console level: info import: - categories/media.yaml - categories/documents.yaml - categories/wallhaven.yaml
categories/wallhaven.yaml (imported file)
categories: - name: "wallhaven" source: path: "C:\\Users\\you\\Downloads" extensions: [jpg, png] filter: match: regex: "^wallhaven" destination: path: "C:\\Users\\you\\Walls\\Wallhaven" conflict-strategy: hash_check
| Command | Description |
|---|---|
movelooper | Run the move operation once across all categories |
movelooper watch | Monitor source directories and move files in real-time |
movelooper undo | Open interactive picker to select and revert a batch |
movelooper undo --list | List all recorded batches |
movelooper undo --dry-run | Preview what would be restored |
movelooper edit | Open the config in an interactive TUI editor |
movelooper edit -o movelooper.yaml | Scaffold a new config from a template in the TUI editor |
movelooper validate | Validate a config file and report all errors |
movelooper config | Print the resolved configuration file path |
movelooper show-docs | Browse the field reference in the terminal |
movelooper self-update | Download and install the latest release |