movelooper logo

A modern CLI tool that automatically organizes and moves your files based on configurable categories. No manual sorting, no chaos.

Features

Category-based rules

Define categories with extensions, filters, and destinations in a simple YAML file.

Watch mode

Monitor directories in real-time and move files automatically as they appear.

Undo

Interactive batch picker to select and revert any past operation. Pass a batch ID to skip the picker.

Dry-run everywhere

--dry-run on move and undo, preview before committing.

Conflict strategies

rename, overwrite, skip, or hash_check per category.

Powerful filters

Regex, glob, age, and size filters; not exclusion; composable any/all logic.

Wildcard extension

extensions: [all] matches any file type, combine with organize-by: "{ext}" for a catch-all sorter.

organize-by templates

Build subdirectory structures with tokens: {ext}, {mod-year}, {mod-month}, {size-range}, and more.

Rich rename tokens

Name transforms, system info, timestamps, hashes, and sequences, e.g. {mod-date}_{name-slug}.{ext}.

Action control

move, copy, or symlink per category, to back up or link files without touching the originals.

Detects real file types

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 at destination

Rename files on arrival using the token engine: rename: "{mod-date}_{name}.{ext}".

TUI config editor

movelooper edit opens a two-panel TUI editor with undo, redo, and validation on save.

Template scaffolding

Bootstrap a new config from a built-in template in the TUI editor: movelooper edit -o movelooper.yaml.

Config imports

Split categories across multiple YAML files with import:. Use movelooper edit to open the merged config in the interactive TUI editor.

Self-update

Stay on the latest release with movelooper self-update.

Installation

# 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

Quick start

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

Examples

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

Commands

Command Description
movelooperRun the move operation once across all categories
movelooper watchMonitor source directories and move files in real-time
movelooper undoOpen interactive picker to select and revert a batch
movelooper undo --listList all recorded batches
movelooper undo --dry-runPreview what would be restored
movelooper editOpen the config in an interactive TUI editor
movelooper edit -o movelooper.yamlScaffold a new config from a template in the TUI editor
movelooper validateValidate a config file and report all errors
movelooper configPrint the resolved configuration file path
movelooper show-docsBrowse the field reference in the terminal
movelooper self-updateDownload and install the latest release