Mullion FileMan: A Dual-Pane File Manager and a Set of Folder Tools

Mullion FileMan is a C++17 dual-pane terminal file manager. It has twenty folder_* CLI tools that compare and sync folders, and an MCP server for AI agents.

On this page

Every so often I end up with two copies of the same photo library on two drives, and no idea whether they still match. File Explorer can’t tell me which files differ, and I’m not deleting either copy until I know.

Mullion FileMan is what I built to answer that question, and it grew from there. It is a C++17 project with two parts:

  • About twenty standalone folder_* command line tools that do the actual work.
  • A two-pane file manager that runs in the terminal, in the style of Norton Commander, built on top of those tools.

There is also an MCP server, so an AI agent can use the same tools. This post covers how to build the project, the tools I reach for most, the two-pane UI and the MCP server.

Build the project

There is no installer. The build puts the binaries in the project root, and you run them from there. To build the CLI tools on Windows, use this command:

.\build.ps1

On macOS or Linux, use this command:

./build.sh

Both scripts find your compiler automatically. To run the unit tests during the build, add -Test (or --test on Unix). All you need is a C++17 compiler with a working std::filesystem. The CLI tools have no external dependencies.

The terminal UI (TUI) needs FTXUI, which CMake downloads for you. So build the TUI with CMake on every platform:

cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

On Windows, a batch script builds the TUI and puts the CLI tools with it:

.\build-mullion-fileman.bat

Compare two folders

folder_parity was the first tool I wrote, and it is still the one I use most. It walks two folders and lists the files that differ:

folder_parity ./backup ./live -o report.csv

Each row in the CSV is one file that differs, labeled MISSING_IN_1, MISSING_IN_2 or DIFFERENT, with its sizes and modification dates. Files that match are left out. The CSV is saved in a way that lets Excel show accented and non-English filenames correctly.

By default, the tool compares files by size. That is fast, but it misses a change that leaves the size the same. To be certain, add --hash, and the tool reads every file in full and compares the contents:

folder_parity "J:\Photos" "I:\Photos" --hash --jobs -1 --ignore-system -o report.csv
  • --jobs -1 uses all CPU cores.
  • --ignore-system ignores .DS_Store, Thumbs.db and similar files. Without this flag, these files fill the report.

How long hashing a photo library takes depends mostly on the disk. On an SSD, using all cores makes a big difference.

Once you have read the report, the same tool can bring the two folders in line:

folder_parity ./backup ./live --sync --sync-to 1        # one-way mirror
folder_parity ./a ./b --sync --prefer newer             # two-way, newest wins

--prefer accepts 1, 2, newer or larger. It decides which file wins when both sides have the same file with different contents. The exit codes are script-friendly:

  • 0: the trees are the same.
  • 2: the tool found differences.
  • 1: an error occurred.

Sort files into a tree

folder_sort is my other regular. It takes one big messy folder and files everything into subfolders. By default it only shows a preview. Nothing changes until you add --apply:

folder_sort ~/Downloads ~/Sorted --by type          # preview
folder_sort ~/Downloads ~/Sorted --by type --apply  # do it

--by selects one of five built-in layouts:

Layout Result
date {year}/{month}/{name}
month {year}-{month}/{name}
type {category}/{name} — images, video, audio, documents, archives, code, other
ext {ext}/{name}
letter {firstletter}/{name}

If none of these layouts fit, write your own path with --template. The template accepts these fields: {name}, {stem}, {ext}, {category}, {firstletter}, {year}, {month}, {day}, {date:FMT}, {size}, and {idx} / {idx:W} for numbers with leading zeros:

folder_sort ./inbox ./archive --template "{year}/{category}/{stem}{ext}" --move --apply

By default, the tool copies the files. To move them instead, add --move. If two files have the same name, the tool adds a " (2)" suffix. To skip these files, add --skip. Each run writes a CSV index (sort-index.csv, or the name you give with -o) that records where every file went. If you run --move with the wrong template, that index is how you put everything back.

NOTE: folder_sort only looks at what the filesystem knows: modification time, extension and size. --by date uses the modification date, not the date the photo was taken, and these two dates can be years apart. For photos, use folder_photos. It reads the capture date that the camera stored in the file (the EXIF data).

The other tools

All the tools follow the same rules:

  • They create subfolders as needed.
  • They use multiple CPU cores when that helps.
  • Anything that could lose data shows a preview first and does nothing until you add --apply.
  • Each tool is a single executable with no shared libraries, so you can copy one file to another machine and run it.

Files and folders

Tool Function
folder_parity Compare two trees, show the differences and sync them (optional)
folder_clean Remove unwanted OS files (.DS_Store, Thumbs.db and similar files)
folder_copy / folder_move / folder_delete Recursive file operations with many threads
folder_find Find files by name, content, size or age
folder_view Show a file as text or hex

Organization

Tool Function
folder_sort Move files from a flat folder into a tree from a template
folder_rename Rename many files: literal, regex, case, prefix/suffix, {n:03} numbers
folder_attr Timestamps, Windows attributes, POSIX chmod/owner/group

Maintenance

Tool Function
folder_dupes Find duplicate files by size, then by hash; show the space that you can recover
folder_du Disk usage with bars, from largest to smallest
folder_checksum Write a checksum manifest, and examine it later with --verify
folder_shred Write over files before they are deleted (--passes N)
folder_scan Find exposed secrets: AWS keys, private keys, JWTs and tokens

Media

Tool Function
folder_photos Sort images by EXIF capture date into a tree from a template
folder_convert Convert many files with ffmpeg; the extension sets the codec
folder_archive Create, extract or list tar archives
folder_watch Monitor a directory and run a command when matching files change

System

Tool Function
folder_sysmon CPU, memory and GPU usage; --watch, --json, --stream
folder_proc List, filter and stop processes, and change their priority
bookmark_sync Sync bookmarks in two directions between Chrome, Firefox and Safari

Some of the tools chain together. folder_watch accepts a --command, where {} stands for the file that changed. That lets you watch a folder and pass each new file to another tool:

folder_watch ./inbox --pattern "*.png" --command "folder_convert {} --to jpg --apply"

folder_scan also works well as a pre-commit hook. It reports each match as file:line and hides the secret itself.

The dual-pane UI

mullion-fileman is the interactive UI. Give it the two directories to open:

mullion-fileman ./backup ./live

The dual-pane UI. The menu bar is at the top and the F-key row is at the bottom.

If you have used Norton Commander or Midnight Commander, you already know how this works. There are two panes side by side:

  • Push Tab to go to the other pane.
  • Push Enter to open a directory.
  • Push Backspace to go to the parent directory.
  • You can also use the Vim keys j and k.

Each pane shows the name, date and size of each item. A status line shows the path, the number of items and the current sort.

The most important functions are:

  • Tagging. Space tags the current row. + and - tag rows by glob. * inverts the selection. Tagged rows become yellow and show an asterisk. Copy, move and delete apply to all tagged rows.
  • Quick filter. / filters the pane while you type. Esc removes the filter. Enter keeps the filtered view.
  • F-keys. F3 shows a file as text or hex. F5 is copy, F6 is move, F7 is mkdir and F8 is delete. F8 first shows a dry run and asks for confirmation before it removes files.
  • Other keys. t opens the tree view. s opens the sort menu. x opens the Tools menu for bulk operations. : runs a shell command in the directory of the active pane.

You can also use the menu bar and the mouse. Double-click a folder to open it. Right-click to open a context menu. m opens a system monitor that shows the CPU, memory and GPU usage.

The TUI has two optional functions:

  • A local AI agent (a) that examines folders. It can only read files.
  • Voice input (V) to speak to the agent.

To include them, use -DBUILD_MULLION_FILEMAN_AI=ON during the build. To run the agent on the GPU, also use -DMULLION_FILEMAN_AI_CUDA=ON. Both are off by default, which keeps the normal build small.

Use the tools from an AI agent

The project also has an MCP server, which is how AI agents such as Claude plug in outside tools. It is a small Python wrapper that calls the same folder_* programs, so the C++ code stays free of dependencies:

cd mcp
pip install -r requirements.txt
python server.py

The server gives eight tools: compare, sync, find, view, clean, copy, move and delete. It finds the executables through $FOLDER_TOOLS_DIR. If this variable is not set, it uses the repository root. For Claude Desktop, add an entry to claude_desktop_config.json:

{
  "mcpServers": {
    "folder-tools": {
      "command": "python",
      "args": ["path/to/server.py"],
      "env": { "FOLDER_TOOLS_DIR": "path/to/repo" }
    }
  }
}

Now you can ask the agent in plain words to compare J:\Photos and I:\Photos by hash, or to find *.log files larger than 1 MB in D:\logs. It gets the same preview-first defaults as the command line.

Warning

WARNING: folder_parity --sync does not delete files. It only adds files and writes over files. A sync cannot remove a file that you forgot about. But “sync” is not the same as “mirror”: files that are only on the destination stay there. Read the CSV report before you sync important data.

Mullion FileMan runs on Windows, macOS and Linux. Issues and PRs are welcome.

Two related posts: Redthread is another MCP tool of mine, for agent memory. And if the photo library is what brought you here, Sabattier edits the photos once they are sorted.

Written by Sina Fathi-Kazerooni

I write about reinforcement learning, transformers, multi-agent systems, and the tools I build along the way.