Skip to content

brettatoms/phig

Repository files navigation

phig

An image management power tool. Scan directories of images, build a metadata database, detect duplicates, recognize faces, and organize files into a clean folder structure.

Features

  • Scan — recursively scan directories, computing SHA256 + perceptual hashes, extracting EXIF data, and storing everything in SQLite
  • Duplicates — find exact copies (same SHA256) and visually similar images (perceptual hash)
  • Copy/Move — copy or move images into a structured layout (e.g., YYYY/MM/) with configurable format strings, conflict resolution, and dry-run mode
  • Search — query the database by filename, date, EXIF data, file size, visual similarity, or face matching
  • Face Recognition — detect faces, compute embeddings, name people, and search by person
  • Purge — remove entries from the database by glob pattern
  • Match/filter — repeatable --match and --filter globs across all commands, matching against full paths, with filter taking precedence

Building

With devenv (development)

Requires Nix with devenv and optionally direnv.

cd phig
direnv allow          # auto-activates the dev environment (one-time)

cmake -B build
cmake --build build

The binary is at ./build/phig. It links against Nix store libraries and is intended for local development use.

With system packages (distribution)

phig builds against stock system libraries — OpenCV (core modules only; no contrib needed), SQLite3, libexif, libcurl, and FFmpeg. Install the dependencies with your package manager:

# Debian / Ubuntu
sudo apt install build-essential cmake pkg-config libopencv-dev libsqlite3-dev \
    libexif-dev libcurl4-openssl-dev libavformat-dev libavcodec-dev \
    libavutil-dev libswscale-dev libgtest-dev

# Fedora
sudo dnf install gcc-c++ cmake make pkgconf-pkg-config opencv-devel sqlite-devel \
    libexif-devel libcurl-devel ffmpeg-free-devel gtest-devel

# Arch Linux
sudo pacman -S base-devel cmake opencv sqlite libexif curl ffmpeg gtest

# macOS (Homebrew)
brew install cmake pkg-config opencv sqlite libexif ffmpeg googletest

Then build and install:

cmake -B build
cmake --build build
sudo cmake --install build                     # installs to /usr/local/bin/phig
# or
cmake --install build --prefix ~/.local        # installs to ~/.local/bin/phig

Notes:

  • OpenCV ≥ 4.5 for core features; face recognition (the YuNet/SFace models) needs ≥ 4.7. Only core modules are used — no opencv_contrib.
  • FFmpeg on Fedora: the official repos ship ffmpeg-free-devel, which is sufficient. The fully-featured ffmpeg-devel lives in the third-party RPM Fusion repo; you only need it if ffmpeg-free-devel is missing a codec you require.
  • Check your build with phig --version.

Configuration

File locations

phig follows the XDG base directory convention on all platforms (honoring XDG_CONFIG_HOME/XDG_DATA_HOME/XDG_CACHE_HOME when set):

What Default location
Database ~/.local/share/phig/phig.db
Face-recognition models ~/.cache/phig/models/
Thumbnails ~/.cache/phig/thumbs/
Config file ~/.config/phig/config.ini

The database is designed to be the single source of truth for your image collection — reusable by other tools, a future API, or a GUI.

Config file

If ~/.config/phig/config.ini exists it is loaded automatically; point at a different file with the global --config <path> flag. Values set defaults; an explicit CLI flag always overrides the config, which overrides the built-in default. Leading ~ in path values is expanded.

[paths]
db = ~/photos/phig.db
models_dir = ~/.cache/phig/models
thumbs_dir = ~/.cache/phig/thumbs

[general]
parallel = 4

[scan]
recursive = true
on_error = warn        # warn | fail
media = all            # image | video | all
thumbs = false
faces = false

[organize]
format = %Y/%m/%original

[duplicates]
type = all             # exact | near | all
threshold = 5          # 0-64

[faces]
threshold = 0.6

Destructive or per-invocation options are deliberately not configurable and must be given on the command line: --force, --dry-run, --on-conflict, --ignore-mount-warning, and the selection/query flags (--match, --filter, etc.). Unknown keys produce a warning; invalid values are a hard error.

phig --help prints an "Active configuration" summary showing the resolved paths and any values your config overrides.

Usage

Scanning

Scan directories to build the image database:

phig scan ~/Photos --recursive
phig scan ~/Photos --recursive --force          # re-hash everything
phig scan ~/Photos --recursive --faces          # also detect faces
phig scan ~/Photos --faces --parallel 2         # control parallelism

Finding Duplicates

phig duplicates                                 # all duplicates
phig duplicates --type exact                    # exact copies only
phig duplicates --type near --threshold 3       # very similar images
phig duplicates --match "*/Photos/*"            # only in Photos directory
phig duplicates --format json --output dupes.json

Searching

# By metadata
phig search --ext jpg
phig search --after 2023-01-01 --before 2024-01-01
phig search --camera "iPhone"
phig search --min-size 5MB
phig search --match "*/Vacation/*"

# Visual similarity (provide a reference image)
phig search --similar reference.jpg
phig search --similar reference.jpg --threshold 3
cat photo.jpg | phig search --similar -         # from stdin

# Count results
phig search --ext jpg --count

# Machine-readable output
phig search --porcelain                         # tab-separated
phig search --print0                            # null-separated (for xargs -0)
phig search --format json
phig search --format csv --output results.csv

# View results in an image viewer
phig search --match "*/Vacation/*" --print0 | xargs -0 eog

Face Recognition

Download face detection models (one-time):

phig models download

Scan with face detection:

phig scan ~/Photos --recursive --faces

Name people and search:

# Name a person using a clear headshot (single face)
phig face name headshot.jpg "Brett"

# Auto-label all matching faces in the database
phig face identify "Brett"

# Search for images of a person
phig search --person "Brett"
phig search --person "Brett" --print0 | xargs -0 eog

# Search by face (provide any photo of the person)
phig search --face photo.jpg
cat photo.jpg | phig search --face -

# List known people
phig face list

# Re-detect faces (e.g., after model update)
phig face rebuild
phig face rebuild --match "*/2024/*"

New scans with --faces automatically label detected faces that match known people.

Organizing Files

Copy or move images into a structured folder layout:

# Preview what would happen
phig cp ~/Photos/Organized --dry-run
phig cp ~/Photos/Organized --format "%Y/%m/%original"
phig cp ~/Photos/Organized --format "%Y/%m/%d/%original"
phig cp ~/Photos/Organized --format "%Y/%m/%camera/%original"

# Move with filters
phig mv ~/Photos/Organized --match "*.jpg" --filter "*_copy*"

# Handle conflicts
phig cp ~/Photos/Organized --on-conflict rename   # auto-rename duplicates
phig cp ~/Photos/Organized --on-conflict overwrite

Format tokens: %Y (year), %m (month), %d (day), %camera (EXIF model), %make (EXIF make), %original (original filename).

Purging Database Entries

phig purge --match "*/old-folder/*" --dry-run   # preview
phig purge --match "*.tmp"                       # remove by pattern
phig purge --match "*/Trash/*"                   # remove by directory

Match and Filter

All commands support --match and --filter for glob-based path filtering:

# Match includes files (repeatable)
phig search --match "*/Vacation/*" --match "*/Beach/*"

# Filter excludes files (repeatable, wins over match)
phig search --match "*.jpg" --filter "*_thumb*"

# Tilde expansion works
phig search --match "~/Photos/*"

# Globs match against the full path
phig duplicates --match "*/2024/*"
phig purge --match "*/old-backup/*"

Running Tests

cmake --build build && ./build/phig-tests

License

MIT

About

An image management power tool for the CLI

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Contributors

Languages