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).
- 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!
- Ghostty, Kitty or another graphic-supporting terminal. Other terminals fall back to coarse unicode blocks.
libheif/heif-convertfor 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 exportHALLWARD_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 = trueReload 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.
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
hallwardYou 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 cwdMark 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-
Install the dependencies (Arch/Omarchy shown; use your distro's equivalents elsewhere):
sudo pacman -S ffmpeg libheif mpv imv
imvis the stills viewer — nsxiv, feh, or swayimg also work. -
Download the latest release:
curl -fLO https://github.com/mauricewipf/hallward/releases/latest/download/hallward-x86_64-unknown-linux-gnu.tar.gz
-
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/
-
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'.
Homebrew (one command):
brew install mauricewipf/hallward/hallwardThis 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/hallwardManual:
-
Install the dependencies:
brew install libheif ffmpeg mpv
-
Download the latest release:
curl -fLO https://github.com/mauricewipf/hallward/releases/latest/download/hallward-aarch64-apple-darwin.tar.gz
-
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/
-
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).
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| 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) |
cargo test
cargo run -- --root medialibrary init
cargo run -- --root medialibrary
