Imagee: my own image viewer and optimiser for the Mac

A native image viewer with presets built in. It replaced Preview for images and ImageOptim: it opens a photo up to 4x faster than Preview and shrinks 100 images in 1 s instead of 98 s.

The Imagee app icon: a stack of fanned white photo prints with a red edelweiss on a burgundy gradient square, with the name Imagee under it

Imagee is the app that opens every image on my Mac. It replaces Preview for images and ImageOptim, plus the Python scripts I used to resize images for slides and for the web. I double-click a screenshot, it's on screen. I press 2, it's a WebP at 1,600 px. I press U, it's on ImageKit and the URL is on my clipboard.

I built it with Claude Code: version 1.0 shipped on 27th October 2026, version 1.1 with the folder grid on 28th October. The app is 2.3 MB. The name was first used for my 2022 image scripts, see Imagee.

Why I replaced Preview and ImageOptim

Before the build, the agent counted how I really use images:

What Before Imagee
Viewing Preview, about 10 images a day. 222 opened in 30 days, 83% of them screenshots
Image sizes Median 1,380 px wide, median 204 KB
Optimising ImageOptim: 8 launches in 4 years
Resizing 7 Python scripts, run from Launchee and Filee, 1 hard-coded script per job
Uploads to ImageKit 411 in 30 days, almost all from the publish script of this site
Agents 916 images over 2 MB in 90 days in my Kaltura workspace, from decks and exports

3 conclusions came out of it:

  • Viewing is the daily job, optimising is the monthly one. So the viewer has to be as fast as Preview, and every image job has to sit 1 key away from the image on screen.
  • ImageOptim wasn't the job, my scripts were. Each script became a preset in 1 file.
  • Agents are the biggest user. Claude makes 100s of large images a month. The CLI with JSON is the main door, the window comes second.

Preview also can't open an SVG on macOS 26.5, and ImageOptim can't write WebP.

What Imagee does

The viewer

  • Every format macOS reads: JPEG, PNG, HEIC, WebP, AVIF, GIF, TIFF, BMP, camera RAW and SVG.
  • ← → step through the folder, with the next image ready in about 1 ms.
  • Hold space and drag to pan, with the hand cursor, like Preview.
  • C crops, ⌥⌘S adjusts the size in pixels, percent or cm, ⌘L and ⌘R rotate.
  • Nothing touches the file until ⌘S. The original goes to the Trash, so ⌘Z after a save, or imagee restore, brings it back.
  • ⌘⌫ moves the image to the Trash and shows the next one. ⌘Z puts it back.
  • When a script rewrites the file, the viewer reloads it in about 110 ms. That matters when Claude edits a render while I watch.
  • ⌘K lists every command with its key.

The folder grid

Version 1.1 opens a folder as a grid of thumbnails. ⌘↑ or ⎋ in the viewer goes back to the grid, ↩ opens the selected image. A disk cache keeps a 512 px thumbnail per image, about 20 KB each, so the second visit is instant. / filters, and presets, upload, copy and Trash work on the selection.

The Imagee folder grid in light mode: a red sub folder cell first, then rows of identical synthetic test images with coloured circles, and a status bar reading 401 images, 1 folder, 51.1 MB

The screenshot comes from QA, on generated test images. Imagee's QA never reads my real files.

Presets on the number keys

The presets live in ~/.imagee/presets.jsonc. Imagee reloads the file when it changes.

Key Preset What it does
1 shrink Same size and format, smaller file, replaces
2 web WebP, max 1,600 px wide, quality 80
3 hd Fit 1920 x 1080
4 notes Max 1,600 px wide, replaces
5 email JPEG, fit 1200 x 1200
6 thumb WebP 400 x 300, cropped on the subject (Vision)
7 slide Width in cm at 96 dpi
8 full-slide 1920 x 1080 at 144 dpi, PNG if transparent
9 phone JPEG (HEIC too), fit 1600 x 2133

Every preset strips EXIF, GPS, XMP and IPTC, keeps the colour profile and never upscales. full-slide used to be 960 x 540 in my old script, which looked soft on my 4K displays and in Teams.

  • ⌥⌘O opens the original and the output side by side at 100%. The new file size shows within about 120 ms of a quality change.
  • ⌘B opens a batch window: I drop files or folders and pick a preset. It's ImageOptim's drop-to-shrink, on all cores.
  • Finder Quick Actions: Shrink, Web and Upload with Imagee.
  • U uploads to ImageKit and copies the transform URL, sized for the job.

Imagee vs Preview and ImageOptim

Imagee Preview ImageOptim
My own app, 2.3 MB, MIT licence Built into macOS Free and open source
Opens every image type, SVG included No SVG on macOS 26.5 Not a viewer
Presets on keys 1 to 9 Adjust Size, 1 image at a time 1 setting for every file
WebP, AVIF, HEIC, JPEG, PNG out Exports, no WebP Keeps the format, no WebP
Writes beside or replaces, original to Trash Saves over the file Replaces in place
ImageKit upload with a sized URL No No
CLI with JSON for agents No Command line, no JSON

I lost nothing I used. Preview's markup tools and its PDF side were never part of the job: PDFs go to PDFee: my own PDF app for macOS since 24th October 2026.

Speed

The agent measured all 3 apps on 28th October 2026, on my Mac Studio, with the same files. The open times run from the open command to the window on screen. Memory is the physical footprint, the figure Activity Monitor shows.

Comparison table with the 3 app icons: Imagee launches with a 24 MP photo in 475 ms against Preview's 985 ms, opens a 24 MP JPEG in 136 ms against 384 ms and a HEIC in 127 ms against 533 ms, holds 258 MB with 21 images open against 548 MB, and shrinks 100 notes images in 1.0 s against ImageOptim's 98 s, saving 30% against 32%

What the table says:

  • Viewing: Imagee opens a photo 2.1x to 4.2x faster than Preview, and holds half the memory with 21 images open.
  • Optimising: shrink did 100 images from this site in 1.0 s. ImageOptim took 98 s and 595 s of CPU time.
  • ImageOptim saves 2 points more, 32% against 30%. Its extra lossless passes buy those 2 points and cost the 98 s. Its worst image is also a little better.
  • Imagee kept 69 of the 100 images pixel-identical, against 26 for ImageOptim. It leaves a file alone when it can't make it smaller.
  • WebP is the real saving: the web preset cut the same 100 images by 72% in 0.9 s.

1 caveat: Imagee shows its window first and decodes off the main thread, so its pixels arrive about 30 ms after the window. Preview draws its window with the image. With that added, Imagee still wins by 2.5x or more.

Budgets from QA

qa.py measures these on every build:

Step Budget Measured
Open a 24 MP JPEG, app running, first pixels < 80 ms 27 ms
Next image in the folder < 30 ms 1 ms
A 74 MP image at full resolution < 400 ms 77 ms
100 images to WebP at 1,600 px < 3 s 1.7 s
1 image through the CLI, end to end < 250 ms 208 ms
Grid, first screen of thumbnails, cached < 250 ms 23 ms

The grid numbers come from a real folder of 986 images.

How it's built

Stack

  • Swift 6.3, AppKit. No SwiftUI.
  • 1 binary. Imagee cli <command> runs the engine with no window, so the app, the CLI and Claude share 1 engine.
  • ImageIO decodes, and encodes JPEG, PNG, HEIC, AVIF and TIFF. The viewer shows a screen-sized decode first and swaps in full resolution only when the zoom needs it.
  • libwebp for WebP, because macOS can't write it. It's the only third-party code, vendored as a static library, so the app needs no Homebrew.
  • pngquant, an external tool, for lossy PNG. Without it, PNGs stay lossless and a notice says how to fix it.
  • Vision finds the subject for the thumb crop.
  • SQLite for the jobs, the uploads and the thumbnail cache.
  • A Python CLI, standard library only.

Never lose an original

A replace writes a temp file in the same folder, checks that it decodes, moves the original to the Trash, then renames the temp file over the original's name. The new file keeps the creation date and Finder tags. imagee restore takes the original back from the Trash.

Gotchas worth knowing

  • macOS writes JPEG, PNG, HEIC and AVIF, but not WebP. That's why libwebp is in the app.
  • AVIF gave the same size as WebP in the benchmark, at more than 2x the time. WebP stays the web default, AVIF is 1 flag away.
  • HEIC thumbnails are slow: 330 ms each, because the encoder runs 1 image at a time. The grid cache uses JPEG, or WebP when a pixel is see-through.
  • Setting the default app needs a macOS confirmation that only an app can show. imagee default --imagee goes through the app's URL scheme for that reason.
  • AppKit alone takes 65 to 88 MB before an image opens. The memory budget went from 100 MB to 160 MB after the first measurement.

The agent interface

imagee works without the app running, except open. Every command takes --json and prints 1 JSON document, so NicAI can use Imagee inside a task (see What is NicAI):

imagee web shots/ --upload --project blog --json   # run a preset, upload, return the URLs
imagee audit images/ --preset notes --json         # oversize files, metadata, expected saving
imagee info photo.jpg --json                       # format, pixels, bytes, EXIF, GPS
imagee restore photo.png --json                    # the original back from the Trash
imagee browse ~/Pictures --json                    # the folder grid, in the background

Exit codes: 0 success, 1 error, 2 usage, 3 refused (add --yes), 4 the app isn't running.

How it was built

Imagee followed my appee process for apps:

  1. Usage review: Preview's launch count and the images I opened, ImageOptim's settings, my scripts and the apps that call them, the ImageKit library, the images of this site, and a benchmark on 100 copies of them.
  2. Questions: 59, each with a recommended answer, answered on 27th October 2026.
  3. Spec: the decisions, the budgets and the switch-over plan.
  4. Build and QA: version 1.0 on 27th October. 15 unit tests and 96 end-to-end checks in 6 suites. An independent review found 11 defects, all fixed.
  5. Version 1.1 on 28th October: the folder grid, space to pan, and a new icon. A second review found 15 defects, all fixed.

QA runs in a scratch home with a fake ImageKit server. It never touches my real files, my clipboard, my default apps or my ImageKit account.

Launchee and the 3 image actions in Filee: my own file manager for macOS now call imagee instead of my old scripts.

Further reading

The apps Imagee replaces:

Where the uploads go:

The tool I built it with:

NicAI
Written by NicAI, Nic's AI assistant, for his personal knowledge base. Researched and drafted by the model, not hand-written by Nic. Verify anything you plan to act on.