Skip to content

Repository files navigation

Hallward

Terminal photo library: miller-style folders, a thumbnail grid for albums, an external image viewer, and Ask AI over marked stills. Photos stay ordinary files on disk. Hallward only adds a .album/ directory (SQLite catalog + JPEG thumbs).

Hallward TUI screenshot

Features

  • Browse photos and videos from the Terminal
  • Point Hallward on a remote or mounted file system and it works as well
  • Ask AI questions about photos: "Which car is this?"
  • Edit a marked photo with a prompt: "Remove the persons in the background."
  • View photos and videos in external viewer
  • First-class Omarchy support
  • More is coming. Stay tuned!

Prerequisites

  • Ghostty, Kitty or another graphic-supporting terminal. Other terminals fall back to coarse unicode blocks.
  • libheif / heif-convert for HEIC thumbnails (Arch: pacman -S libheif)
  • ffmpeg (ships ffprobe) for video thumbnails and Live Photo detection — not a player
  • A video player: mpv
  • An OpenRouter API key for Ask AI and image editing — set once with hallward credentials set, or export HALLWARD_OPENROUTER_API_KEY

macOS: still images open in built-in Preview (no extra install). Quit Preview (Cmd-Q) to return to Hallward, same as mpv. Video playback requires mpv (brew install mpv). FFmpeg’s ffplay is a terminal player: it tears down the TUI, dumps decoder logs to the shell, and is not an acceptable viewer. If the status pane says video: ffplay or video: no player, install mpv and restart Hallward until it shows video: mpv.

Linux / Omarchy: an image viewer: imv (preferred), or nsxiv, feh, swayimg. mpv is preferred for video; ffplay is a last-resort fallback only.

The status pane shows thumbs: kitty when the terminal is drawing real image pixels, and thumbs: halfblocks when it fell back to coarse unicode blocks (looks pixelated). Multiplexers must pass Kitty graphics through to the host terminal:

tmux (3.3+), in ~/.tmux.conf:

set -g allow-passthrough on

Then tmux source-file ~/.tmux.conf (or restart tmux). Hallward already wraps Kitty sequences in tmux’s DCS envelope when it detects tmux; without allow-passthrough, tmux strips them.

herdr, in ~/.config/herdr/config.toml:

[experimental]
kitty_graphics = true

Reload config (prefix+shift+r), detach, and reattach. For herdr --remote, set this on both the local client and the remote server, then restart the remote (herdr server stop and start again). herdr does not use tmux passthrough; this flag is the equivalent.

Use

Point Hallward at a folder of albums (collections are folders that only contain other folders):

~/Pictures/Library/
  .album/               # generated on init (catalog + thumbs)
  2025/                 # collection
    Rome/               # album (images and/or standalone videos)
  Samples/              # album

First run in that folder:

cd ~/Pictures/Library
hallward

You will be asked to initialize. That creates .album/ and builds thumbs (HEIC decode can take a minute).

hallward init          # create .album/ and index
hallward index         # refresh after adding/removing files
hallward               # open the TUI
hallward --root PATH   # library is PATH instead of cwd

Ask AI

Mark with Space key one or more images and the search bar becomes Ask AI.

Type a question and press Enter: "Which car is this?" OpenRouter answers in the pane (google/gemini-3.5-flash-lite).

If the prompt is an edit instruction such as "Remove the persons in the background.", Hallward classifies it with OpenRouter, then edits with google/gemini-3.1-flash-lite-image. Ask AI and image edit share one credential: run hallward credentials set (stdin, echo off) or set HALLWARD_OPENROUTER_API_KEY. Hallward stores the key in ~/.config/hallward/credentials (mode 0600, directory 0700). The edited photo is saved as a new sibling file (photo-edited.png, then photo-edited-2.png, …). The original is never overwritten. Editing needs exactly one marked still. Esc cancels an in-flight request.

hallward credentials set              # paste key at prompt (not echoed)
hallward credentials set --from-env   # copy HALLWARD_OPENROUTER_API_KEY into the file
hallward credentials clear            # remove the credentials file

Ask AI

Install

Linux (x86_64, glibc)

  1. Install the dependencies (Arch/Omarchy shown; use your distro's equivalents elsewhere):

    sudo pacman -S ffmpeg libheif mpv imv

    imv is the stills viewer — nsxiv, feh, or swayimg also work.

  2. Download the latest release:

    curl -fLO https://github.com/mauricewipf/hallward/releases/latest/download/hallward-x86_64-unknown-linux-gnu.tar.gz
  3. Extract and move onto your PATH:

    tar -xzf hallward-x86_64-unknown-linux-gnu.tar.gz
    chmod +x hallward
    mkdir -p ~/.local/bin && mv hallward ~/.local/bin/
  4. Run it in a Kitty-graphics-capable terminal (Kitty, Ghostty, WezTerm) for sharp thumbnails:

    hallward --root /path/to/your/photos

Other tarballs and checksums: Releases. With the GitHub CLI: gh release download --repo mauricewipf/hallward --pattern '*linux-gnu.tar.gz'.

macOS (Apple Silicon)

Homebrew (one command):

brew install mauricewipf/hallward/hallward

This installs hallward plus libheif, ffmpeg, and mpv. Homebrew auto-taps on first install; you may need to trust the formula once:

brew trust --formula mauricewipf/hallward/hallward

Manual:

  1. Install the dependencies:

    brew install libheif ffmpeg mpv
  2. Download the latest release:

    curl -fLO https://github.com/mauricewipf/hallward/releases/latest/download/hallward-aarch64-apple-darwin.tar.gz
  3. Extract and move onto your PATH:

    tar -xzf hallward-aarch64-apple-darwin.tar.gz
    chmod +x hallward
    mkdir -p ~/.local/bin && mv hallward ~/.local/bin/
  4. First launch: the binary is unsigned, so if Gatekeeper blocks it, allow it in System Settings → Privacy & Security. Stills open in Preview (Cmd-Q to return); video playback uses mpv. Sharp thumbnails need Ghostty or Kitty (brew install --cask ghostty).

Tap: mauricewipf/homebrew-hallward. Do not use ffplay as a viewer (see Prerequisites).

From source

Needs Rust:

git clone https://github.com/mauricewipf/hallward.git
cd hallward
cargo install --path .

Or without installing:

cargo build --release
# binary: target/release/hallward

Keyboard

Key Action
arrows Miller columns; in an album grid, move the selection frame
Right on a collection Open its subfolders
Right on an album Focus the thumbnail grid
Left from the left edge of the grid Back to the album column
Shift+Tab Jump to the search field from Library, Folders, or Gallery (Ask AI when stills are marked). Type there to filter collection and album names (not filenames)
letters / digits With stills marked, typing goes to Ask AI (q does not quit while stills are marked; Ctrl-C still quits)
Tab Jump to the filtered tree, or to Ask AI when it is active
Space Toggle a mark on the focused thumbnail
Esc Clear marks; if none are marked, clear copy/cut; if none of those, clear search and show the full tree. In Ask AI, clear the prompt and answer, leave the field, and keep marks
Enter Open marked photos in the external viewer (album order, focused file first if marked). If nothing is marked, open a same-type playlist of the album starting at the focused photo: images in Preview on macOS (Cmd-Q to return) or imv / nsxiv / feh / swayimg on Linux; videos in mpv. In Ask AI, send the prompt
click Click a marked thumbnail to unmark it; click an unmarked thumbnail or empty grid padding to clear marks
double-click Open marked photos (or the album playlist if none are marked)
r Re-scan files and refresh thumbnails (when search / Ask AI is closed)
d Delete the focused photo/video, or all marked items, after a y/n confirm. In Library / Folders with nothing marked, delete the focused folder and everything in it. Also removes a Live Photo motion .MOV beside a still. Then reindexes. In Search / Ask AI, d types as usual
c Copy the focused photo/video, or all marked items. In Library / Folders with nothing marked, copy the focused folder. Press c again on a copied item to un-copy it. Newly marked items are added to an existing copy/cut set (c on a cut set switches it to copy). Copied thumbnails get a double border; copied folders are cyan. p pastes. In Search / Ask AI, c types as usual
x Cut the focused photo/video, or all marked items. In Library / Folders with nothing marked, cut the focused folder. Press x again on a cut item to un-cut it. Newly marked items are added to an existing copy/cut set (x on a copy set switches it to cut). Cut thumbnails get a dashed border; cut folders are cyan. p moves them. In Search / Ask AI, x types as usual
p Paste copied or cut files into the current album, or folders into the same place a would create a new album (library root, or inside the open collection). Newly marked items are added to the clipboard first. Same names become photo-2.jpg / Rome-2, …. Live Photo motion files stay paired. Copy can paste again; cut clears after a move. In Search / Ask AI, p types as usual
q Quit (when search / Ask AI is closed)

Dev (this repo)

cargo test
cargo run -- --root medialibrary init
cargo run -- --root medialibrary

About

Photo library TUI. Manage your photo library from the terminal!

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages