Skip to content
wmwallacePublic

About

An on-device photo editor for Mac, with an iPhone app on the way. Everything runs on your device.

Topics

Resources

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

The Kelvin app icon

Kelvin

An on-device photo editor for Mac, coming to iPhone.

Apple's Vision framework reads your photograph. Deterministic code writes the edit.
Everything runs on your machine — your photographs never leave it.

Download for macOS

Signed and notarised · macOS 14+ · Apple silicon · about 5 MB

CI Licence: AGPL-3.0-only macOS 14+ Swift 6 Sponsor


Drop in a photo. Kelvin reads the scene and hands you three or four finished edits to choose between. Pick one, tune it, apply it across the shoot.

One photograph, read once, offered as four finished edits: Natural, Soft, Vivid and Dramatic

One frame, four candidate edits. Not four filters over the same numbers — four readings of the photograph, each computed from its own histogram and EXIF.

Why

Most tools give you one answer, or ask you to teach them your style with thousands of past edits first, or repaint your pixels with a generative model.

Kelvin reads one photograph and offers a few defensible interpretations of it. You pick. That choice is the point of the whole app.

The idea underneath: whatever reads the scene never chooses numbers. It answers categorical questions — is there a subject, is it a person, an animal, a sea stack. Every actual value is then computed by ordinary, tested code from the histogram, the EXIF and the masks. Ask a model for exposure: +0.37 and it will invent one, confidently, and you will never know which answers were guesses.

That reader used to be a 1.7 GB vision-language model. Measured against real before-and-after edits, Apple's own Vision framework does the job better — on both of the project's test corpora — in a tenth of a second instead of five, with nothing to download (D27). So that is what reads your photograph now.

Status: pre-alpha

Works today

  • The full editor: the adjustment set, colour mixer and geometry, with a mask kit — subject, sky, radial, graduated, brush, colour range, luminance, skin, per-person
  • On-device scene reading, shown in the panel so you can see what it made of the photograph
  • Candidate generation: three or four finished edits per photograph — and C hands the canvas over to them, two up or four up at full size, because "this one or that one" is a question anyone can answer and squinting at thumbnails is not
  • Culling: keep/reject, a filmstrip that groups a shoot by burst, day, place or near-duplicate, and a scan that marks the sharpest frame of each burst
  • Batch apply across a folder, and exporting every photo you edited in one go — JPEG, HEIC, PNG or 16-bit TIFF, at full size or a chosen long edge, in sRGB, Display P3 or Adobe RGB
  • Sharing a finished frame to Messages or AirDrop through the same render the export path uses, with location off by default and offered only when the frame actually carries it
  • Non-destructive throughout: your originals are never written to

Not yet

  • Kelvin does not learn from which candidate you pick. The pick is recorded; nothing reads it (see docs/DECISIONS.md D18 for why the learner was dropped rather than finished)
  • Auto-masks can be refined and inverted, but not brushed by hand
  • Nothing generative, on purpose

The core and the app each have their own test suite, and CI runs them on every pull request.

The Kelvin window: the photograph, what the model made of the scene, the candidate list, the adjustment panel and the filmstrip

The scene reading is shown rather than hidden — "landscape · golden hour · object", and a sentence explaining what it saw. If it read the photograph wrongly, you can tell at a glance.

The filmstrip grouped into capture days, each with a frame count

A shoot grouped by capture day. It also groups by burst, by place, or by near-duplicate — and under burst or near-duplicate it marks the sharpest frame of each run.

Getting it

Download the latest release — a signed, notarised disk image. Drag it to Applications and open it; there is no right-click-Open dance and no Gatekeeper warning.

It is about 5 MB. Scenes are read by Apple's Vision framework, which is part of macOS, so there is no model to download — not on first run, not ever — and no photograph you open is sent anywhere to be read. (Until 0.9 the app carried a 1.7 GB model inside it; see D27 for why it no longer does.)

The link above always resolves to the newest release. Nothing on this page names a version, so nothing here can quietly go stale the way a pinned download link does.

Building it

macOS 14+, Xcode 16.3+.

make build && make test
make app

The iPhone app is generated with XcodeGen: scripts/make-iphone-project.sh, then open Apps/KelvinPhone/KelvinPhone.xcodeproj. CONTRIBUTING.md has the details and the gotchas.

Opens RAW, JPEG, HEIC, PNG and TIFF.

It runs on your Mac

The editing and the scene reading both happen locally. There's no account, no telemetry, and your photographs are never uploaded. Two small things do use the network — an update check, and place names for geotagged photos — and both are listed below and switchable off. If your library already lives in iCloud then it lives in iCloud — that's your setup, and Kelvin neither adds to it nor takes it away.

Scene reading uses Apple's Vision framework, which is part of macOS, so reading a photograph needs no network and nothing is ever downloaded to do it. A release asks the network two things, both of them switchable off in Settings. The first is whether an update exists. It does that on its own, because an alpha whose fixes only reach the people who agreed to a dialog is an alpha that stays broken for everyone else — the check sends no account, no identifier and nothing about your photographs, and both switches are in Settings ▸ General if you would rather it did not.

The second is place names. If a photograph carries GPS coordinates, Kelvin asks Apple what that place is called, so the filmstrip can group your shoot under “Sunriver, Oregon” rather than under a pair of numbers. The coordinate goes; the photograph does not — not the pixels, not the filename, not an identifier. It is rounded to about 110 m before it is sent, each place is looked up once and remembered, and the switch is in Settings ▸ Scene reading under Network. Turn it off and no coordinate ever leaves your Mac.

That is the whole list. Everything that reads or edits a photograph happens on your machine, which is the promise this app is actually making — your pictures are processed here, not uploaded to be processed somewhere else.

Your originals are never modified: edits are kept in Kelvin's own folder, never beside your files. The one thing that touches them is culling — you can move rejected frames to the Trash from the filmstrip, which asks first and puts them in the Finder's Trash so you can get them back. Exports carry the original metadata by default, including location — there's a switch in the export panel to strip it, with tests that read the file back to check.

Built with

Swift 6 and SwiftUI. Core Image for RAW decoding and rendering, so camera profiles come from Apple. Apple's Vision framework for reading the scene and finding subjects, skies and faces. Edits are stored as small JSON recipes.

Apple platforms only, by choice — the Mac app today and an iPhone app in progress, sharing one engine. See docs/DECISIONS.md.

Documentation

CONTRIBUTING Before your first build or patch
docs/ARCHITECTURE How the pipeline fits together
docs/RECIPE-SCHEMA The data model
docs/DECISIONS Why things are the way they are — read before proposing changes
docs/EVALUATION How edit quality is measured
docs/RELEASING Building a signed, notarised release

Contributing and support

Bug reports and reproductions are welcome and carry no licensing question. For patches, see CONTRIBUTING.md.

If Kelvin earns a place in your workflow, you can sponsor its development. Sponsors are thanked by name inside the app — the list ships in each release, because Kelvin doesn't phone home, not even for a thank-you.

Kelvin is written by its owner working with Claude, and the commit history says so. That history is kept rather than squashed — it records what was measured and why decisions went the way they did.

Licence

AGPL-3.0-only. If you build on this and ship it — as an app or as a service — your source has to be open too.

Contributions are covered by a contributor licence agreement: you keep your copyright, and the maintainer keeps the ability to relicense. Reasoning in docs/DECISIONS.md (D8).

Copyright © 2026 William Wallace.

About

An on-device photo editor for Mac, with an iPhone app on the way. Everything runs on your device.

Topics

Resources

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages