Using Anthropic's Claude Opus 5.5 to build in Rust, Photocraft imitates Photoshop. Open source and free, with no subscription required.

Familiar by design

The menus, shortcuts, panels and tools your hands already know. Productive on day one, no retraining.

Native GPU canvas

Renders on Metal, Vulkan, DirectX 12 and WebGPU. No Electron and no web view, just a fast native compositor.

Real layered files

Opens and saves layered PSD and PSB documents. 134 of 135 real-world test files round-trip byte for byte.

Non-destructive editing

16 adjustment layers, 70+ live-preview filters, smart objects with smart filters, and a full set of layer styles.

On-device selection

Select subjects and objects and refine masks with tools that run on your machine, not someone else's server.

Serious color

8, 16 and 32-bit documents in RGB, CMYK, Lab and Grayscale, with ICC color management and soft proofing.

What's New

182 commits from 183 merged pull requests, including work from 31 community contributors (thank you!), and 146 issues closed.

Your work is safer

  • Recovered unsaved documents survive a second crash.
  • Deeply nested .pcraft files reopen.
  • photocraft-cli batch refuses to overwrite its input folder.
  • Preferences no longer get lost when two windows or tabs save, or when a save fails.
  • Languages: the interface is available in 日本語, 简体中文, 繁體中文, Español, Русский and Čeština (Edit › Preferences › Interface › Language), with CJK fonts and IME input in the Type tool.

Files

  • JPEG and other no-alpha exports composite transparency over white.
  • Formats without colour profiles get sRGB.
  • Truncated JPEGs and multi-frame files open with a warning instead of silently.
  • TGA is offered in Save As and Export As.

Editing

  • Free Transform a Copy and Transform Again on a Copy.
  • Keyboard layer navigation, number keys for opacity, Alt-click colour sampling.
  • New from Clipboard.
  • Undo and redo restore the targeted layer.
  • Shortcuts pressed in quick succession all run, in order.

Automation (CLI, MCP, control channel)

  • Stricter, clearer parameter and flag errors, and --help.
  • Background jobs that agents can wait for or poll.
  • Recorded actions run in batch.

Other Changes

  • perf(compose): avoid unnecessary backdrop snapshots by @MikeeI in #109
  • perf(compose): prepare gradient stops outside pixel loops by @MikeeI in #103
  • Fix stale effect maps after default-only mask changes by @MikeeI in #105
  • Preserve HDR samples when importing white-matted PSD composites by @MikeeI in #106
  • Mix pass-through group coverage in premultiplied space by @MikeeI in #108
  • perf(compose): avoid redundant effect-halo rendering by @MikeeI in #110
  • Preserve merged PSD alpha at the exported sample precision by @MikeeI in #111
  • perf(compose): reuse compiled vector masks within each render by @MikeeI in #112
  • perf(compose): reuse bounded pattern preparation across render tiles by @MikeeI in #104
  • fix(ui): pasting an image copied in another app never ran by @tiredIsa in #102
  • fix(ui): make Move transform controls interactive by @Ni-zav in #99
  • Menu overlap and overflow #92 by @Ni-zav in #98
  • PR #96 – Liquify undo by @Ni-zav in #97
  • fix(ui): shape tools show the shape while dragging by @sommerper in #87
  • security: bound automation previews and reply resources by @Gh0stlyKn1ght in #93
  • Japanese support: IME input in the Type tool and CJK glyphs in the UI by @kntrttm in #101
  • Community batch follow-ups: on-demand OS clipboard paste; fmt + egui 0.36 test port by @echelon in #134
  • perf(ui): borrow the active layer from its document snapshot by @MikeeI in #121
  • perf(ui): reuse exact cached content bounds by @MikeeI in #116
  • perf(ui): skip offscreen layer thumbnail generation by @MikeeI in #117
  • perf(ui): retain channel thumbnails across view-only revisions by @MikeeI in #120
  • fix(ui): prune thumbnails for removed layers and documents by @MikeeI in #119
  • fix(ui): prune closed-document display and preview resources by @MikeeI in #118
  • Disambiguate colliding document identities at session admission by @MikeeI in #114
  • Warn when the PSD channel limit drops a Quick Mask by @MikeeI in #115
  • Preserve compositing properties in single-layer flat export by @MikeeI in #122
  • Preserve selected real masks during PSD import by @MikeeI in #130
  • Scale artboard bounds in proxy documents by @MikeeI in #131
  • Crop tool: move and resize the crop frame, Space repositions while drawing by @echelon in #132
  • Fix flaky canvas_geom undo test (process-wide text gamma raced by another test) by @echelon in #135
  • Dock: fixed-height panel groups, splitters, collapse, reorder; panels never vanish by @echelon in #139
  • Brush Settings panel: Photoshop structure and depth, edits through tools.setBrush by @echelon in #136
  • Selecting current bit depth must preserve redo by @MikeeI in #133
  • Detect PhotoCraft archives independent of ZIP entry order by @MikeeI in #137
  • Type tool: caret/selection land on the glyph under the pointer; font size is live, one undo step, ~60x faster (#123, #124) by @echelon in #142
  • Layers groups expand/collapse (#126); every displayed shortcut fires (#127) by @echelon in #141
  • Layers rows: names never run under the indicators; fx triangle; Collapse All Groups; designer PSD for QA by @echelon in #167
  • fix(geom): saturate Rect::translate and inflate on i32 overflow by @kevin9327 in #159
  • fix(ui): make tall menus scrollable on short displays by @Ni-zav in #160
  • PSD type layers: bounds regression tests; #148 is the layer's vector mask, not text bounds by @echelon in #165
  • Flatpak single-file bundles as release artifacts by @echelon in #163
  • Roadmap: honest parity assessment (2026-10-05) by @echelon in #182
  • AGENTS.md: no Tauri, Electron or webview shells by @echelon in #184
  • Menus scroll and navigate by keyboard on small displays; Color Range dialog on the no-GPU path (#145, #138) by @echelon in #168
  • Docs: where we stand and where we're going (roadmap, README, AGENTS.md) by @echelon in #186
  • Brushes: Tilt Scale, Brush Projection, Spacing checkbox, section locks, Mixer Wetness/Mix; Brushes grid + drag and drop; options bar through tools.setBrush by @echelon in #174
  • fix(ui): refresh Liquify preview after undo by @Ni-zav in #175
  • fix(ui): sample eyedropper colours while dragging by @Ni-zav in #176
  • fix(ui): keep Curves endpoint handles inside the graph area by @Ni-zav in #177
  • fix(ui): avoid duplicate sliders for wide filter ranges by @Ni-zav in #179
  • Dock polish: Layers gets the height, Character/Paragraph group, eliding tab strips, reveal the active layer (#147, #150, #151, #152) by @echelon in #181
  • Move/Free Transform modifier keys (#90); sharp full-resolution transform preview (#91) by @echelon in #183
  • CJK UI font fallback: Simplified/Traditional Chinese and Korean, lazily loaded in locale order (#149) by @echelon in #185
  • Layers mask thumbnails + chains; Channels/Paths temporary rows and footers (#153, #154) by @echelon in #191
  • GPU compositor: paged residents and effect maps, so 20k+ documents refresh on the GPU (#49) by @echelon in #187
  • Properties: uniform sections, per-kind Quick Actions, full-width controls (#155) by @echelon in #192
  • PSD corpus: psd-tools set (pinned, verified), an oracle for every file, and the fixes it found by @echelon in #195
  • Tool feedback: selection-mode cursor badges, scrubby zoom, contrasting outlines, Shift lines by @echelon in #188
  • PSD fidelity: 16/32-bit colour modes, Lab, Levels, Exposure, Dissolve oracle (corpus 133 → 140, psd-tools 212 → 222) by @echelon in #202
  • Fix tests on FreeBSD with RADV by @mekanix in #194
  • fix(clipboard): use the wayland clipboard for images by @nuIIpointerexception in #222
  • FreeBSD: build and test the workspace in a FreeBSD VM by @echelon in #223
  • Fix automatic UI scaling on 4K monitors by @john8675309 in #225
  • FreeBSD: serialise canvas GPU tests, CI template, RAM detection, CJK font paths by @echelon in #227
  • Title bar: never draw the window title over the menus or controls by @echelon in #241
  • Packaging: Linux runtime deps + start-up library check (#201); wasm 26.3 -> 18.8 MiB (#198) by @echelon in #237
  • Fix live brush preview drawing a polygon (#189) by @echelon in #240
  • PSD effects fidelity: spread metric, emboss, gradient geometry, text gamma (113 -> 118 oracle passes) by @echelon in #224
  • Scorecard: cargo xtask perf + scorecard, budgets, checklists, nightly perf (#221) by @echelon in #239
  • Layout documents: fix GPU device loss, live Move tool, local damage, no per-frame work (#125, #128) by @echelon in #226
  • PSD export: write tagged blocks other readers can parse (#200) by @echelon in #236
  • CR2: measure the colour filter row phase instead of assuming RGGB (#193) by @echelon in #244
  • Atomic saves: one crash-safe atomic_write for every document write by @echelon in #230
  • Preferences: wire tooltips, Home screen, recent files; hide what nothing reads by @echelon in #245
  • Eraser on locked layers: no lock-out from the simple lock button; Stroke Path erases to the background colour (#76) by @echelon in #229
  • Retouch tools paint the mask/channel target; Sample All Layers for Blur/Sharpen/Smudge; premultiplied Smudge (#207) by @echelon in #234
  • Free Transform: selection moves only its part of a linked mask; masked preview; target masks and channels (#205) by @echelon in #242
  • Vertical type (tategaki): lay out, render, edit and round-trip (#199) by @echelon in #246
  • PSD stroke effects: outlines of filled shapes, vector stroke above interior effects, joined subpaths by @echelon in #233
  • Live gradients: Gradient tool makes editable Gradient Fill layers (on-canvas handles, stops, midpoints) + Classic mode (#180) by @echelon in #197
  • Marquee: Shift squares, Alt draws from the centre, live W × H readout (#208) by @echelon in #247
  • GPU: crash-safe startup and device-loss fallback (#243, #4) by @echelon in #252
  • Text: deterministic font family order; hide private system families (fixes a flaky test) by @echelon in #264
  • Photoshop oracles via storytold/photocraft-corpus: pinned corpora, corpus feature, test-corpus, CI job by @echelon in #190
  • Masks: Alt-click to view mask, Cmd-click vector mask to select, vector-mask target brackets (#196) by @echelon in #256
  • Stylus pressure, tilt, rotation and eraser on macOS and X11 by @echelon in #255
  • Fix Windows MSI advertised shortcut icons by @CQMHV in #238
  • Windows taskbar icon: .exe icon id for the MSI shortcut + icon regression tests (#248) by @echelon in #269
  • Colours: handle non-hex Unicode values without an internal error by @storybored379 in #261
  • Align the CJK fallback font's baseline with Latin text by @kntrttm in #260
  • UI: platform shortcut notation in every label and tooltip (#251) by @tiredIsa in #262
  • New Document: a typed Width/Height reaches Create (#254) by @echelon in #270
  • Menus are as tall as their items; scroll only when the window is too short (#235) by @echelon in #272
  • Portable mode: keep settings beside the exe in the Windows portable zip (#228) by @echelon in #267
  • Brush Settings for every brush: options-bar toggle and real preset picker (#258) by @echelon in #268
  • Ctrl+Alt-drag resizes the brush on the canvas (#231) by @echelon in #271
  • Shift rubber band: preview the straight line before the click (#257) by @echelon in #273
  • Selection drag previews: regression tests for #253 (visible mid-drag, 1x and 2x) by @echelon in #274
  • Shortcuts: rebindable fill keys, D/X and held temporary tools (#249) by @echelon in #275
  • PSD manual and optical kerning: import, export, render, edit (#206) by @echelon in #259
  • Localise the UI: i18n foundation and a Japanese catalog (menus, dialogs, panels) by @kntrttm in #169
  • Pencil tool, Edit › Fill… dialog and "Rasterize?" prompt (#213) by @echelon in #279
  • Fast Select › Modify › Smooth and Feather (part of #211) by @echelon in #280
  • Compositor: effect maps never block inside parallel tiles (fixes #276 deadlock) by @echelon in #281
  • FreeBSD release tarball and README platform lines by @echelon in #284
  • fix: forward document index in bridge inspection by @kuishou68 in #287
  • Marquee: stop the selection at the canvas edge by @Multipad-cyber in #263
  • Background layer: double-click, masks and cut behave like Photoshop by @Multipad-cyber in #266
  • i18n: add Simplified Chinese localization by @CQMHV in #282
  • Enable dictionary segmentation for Japanese type by @midasdf in #250
  • Smart Objects and Smart Filters survive PSD save and open by @echelon in #288
  • Apply EXIF orientation on open, write Orientation = 1 on export (#285) by @echelon in #318
  • PSD export: 32-bit files open in Photoshop (HDR toning Color Mode Data, #291) by @echelon in #327
  • Windows on ARM64: release builds, PE header check, install test on ARM64 hardware by @echelon in #333
  • Fix preference usage scanning on CRLF checkouts by @CQMHV in #331
  • Windows: Alt-click clone hint and Ctrl+N channel errors (#251 follow-up) by @bommerts in #336
  • Move tool: Auto-Select on by default; a click picks and drags the layer under the pointer (#296) by @echelon in #330
  • Cmd+Enter (Ctrl+Enter) loads the path as a selection (#306) by @echelon in #329
  • Layers panel: rename commits on click elsewhere, Enter or Tab; one at a time (#314) by @echelon in #326
  • Keyboard Shortcuts: Ctrl+F records as Ctrl+F, not Ctrl+ControlLeft (#292) by @echelon in #323
  • macOS CLI: verify the shipped CLI is Developer ID signed and notarized in the release workflow (#308) by @echelon in #320
  • fix(ui): feed every pointer move per frame so fast strokes stay smooth by @leonaci in #317
  • Fix logic Show the clone crosshair only while Option is held by @juansebsol in #301
  • i18n: add Traditional Chinese (zh-hant) UI catalog by @WildfootW in #302
  • Add a Spanish catalog (menus, dialogs, panels) by @Mawfyy in #299
  • Localise the UI into Russian: a complete catalog and the missed tl! call sites by @tiredIsa in #298
  • Preferences: add an Apply button by @CQMHV in #325
  • i18n: add Czech (cs) UI translation by @petrleocompel in #328
  • Menus: no menu or submenu covers the menu bar (#319) by @echelon in #337
  • Menus stay above the taskbar; oversized windows open maximized (#315) by @echelon in #343
  • Background jobs: engine job API, progress and cancel (part of #210) by @echelon in #289
  • Background jobs in the app: progress, Cancel, open-as-job (part of #210) by @echelon in #373
  • Harden EXIF orientation: limits after rotation, fallible allocation, strict IFD parsing by @echelon in #345
  • Fonts: use craft-fonts as an optional build input; move the Japanese fonts out by @echelon in #353
  • Stamp Visible (Cmd+Alt+Shift+E) and Stamp Down; Alt+Merge keeps the originals (#217) by @echelon in #356
  • Right-click on the canvas lists the layers under the pointer (#307) by @echelon in #360
  • Canvas scrollbars, and Preferences > Tools > Overscroll works (#300) by @echelon in #367
  • Alt+right-drag resizes the brush and changes its hardness (#297) by @echelon in #370
  • Alt+scroll zooms the canvas in 5% steps around the pointer (#293) by @echelon in #371
  • ui.set: reject unknown fields; the theme error names all five themes (#412, #413) by @bflatastic in #437
  • serve: methods lists jobs.list and jobs.cancel (#414) by @bflatastic in #438
  • MCP command_batch and serve batch honour each step's wait (#415) by @bflatastic in #439
  • Headless saves without path never flatten over the opened file (#416) by @bflatastic in #447
  • Alt-click with the Brush, Pencil, Gradient or Paint Bucket samples a colour (#417) by @bflatastic in #450
  • Layers panel: double-click beside a layer's name opens Layer Style (#350) by @bflatastic in #452
  • Batch runs report inputs that share an output name instead of overwriting (#420, #422) by @bflatastic in #448
  • New from Clipboard, and Paste with nothing open makes a document (#368) by @bflatastic in #458
  • CLI: unknown flags are usage errors, --help prints usage, usage lists --quality (#421, #423) by @bflatastic in #460
  • Liquify remembers its brush settings between uses and launches (#418) by @bflatastic in #461
  • The main window opens centred on the screen (#419) by @bflatastic in #462
  • Keyboard layer navigation: Alt+[ / Alt+] / Alt+, / Alt+. and Shift to add (part of #352) by @bflatastic in #470
  • Transform Again on a Copy (Cmd+Alt+Shift+T): step and repeat (part of #352) by @bflatastic in #474
  • Number keys set opacity, Shift+[ / Shift+] step hardness, Shift+Cmd+A opens Camera Raw (part of #352) by @bflatastic in #473
  • Export: TGA in Save As and Export As (#363) by @Pedroj-64 in #377
  • Docs and MCP schema: use the real Gaussian Blur id (#378) by @floflo777 in #390
  • Image Size shows the one-pixel minimum it applies (#441) by @HEOJUNFO in #468
  • prefs.reset resets a single colorSettings key (#445) by @HEOJUNFO in #467
  • Content-Aware Scale: enlarging a 1 px wide or tall layer no longer panics by @Ar-maan05 in #387
  • Build desktop app by default (#392) by @agorevski in #425
  • fix(engine): use wasm-safe timing for Liquify by @naumanAhmed3 in #393
  • Profile mismatch: compare profiles by colour, not bytes (sRGB vs sRGB prompt) by @ljkx in #394
  • Type: dragging a paragraph box handle resizes the box (#351) by @Pedroj-64 in #376
  • docs: correct VectorCraft sibling name by @agorevski in #429
  • Free Transform a Copy (Cmd+Alt+T); Esc takes the copy back (part of #352) by @bflatastic in #482
  • Raise rust-version to 1.95, the minimum egui 0.36 needs by @carterwsmith in #471
  • docs: add star history chart to README by @coygeek in #469
  • Move drag reveals a larger-than-canvas layer's off-canvas pixels by @sommerper in #526
  • Spanish: add missing tool, filter and path translations by @neversaynv3r in #488
  • Dialogs keep their top-left when their content resizes by @sommerper in #487
  • PSD export selects PSB above size limit (#212) by @agorevski in #431
  • 32-bit documents: Exposure works on the stored linear values by @floflo777 in #400
  • Ctrl+Insert copies and Shift+Insert pastes on Linux; Shift+Insert pastes images on Windows by @sommerper in #531
  • Docs: roadmap, scorecard and README after the 2026-10-07 fixes by @bflatastic in #538
  • CLI batch: recorded-action steps, --format .ext, strict --quality, refuse --out = --in (#489, #490, #491, #492) by @bflatastic in #545
  • Gradients honour explicit transparency stops; smart filter commands accept an explicit layer target (#465, #466) by @bflatastic in #544
  • Recovered documents keep their recovery data until saved or closed (#444) by @bflatastic in #549
  • History: tool and preset names, Frame from Layers as one step, undo/redo restore the targeted layers (#513, #528, #446, #496, #495) by @bflatastic in #551
  • Shortcuts run in the order pressed; Shift+Delete fills on Windows; colour pickers stay put while dragging (#440, #530, #534) by @bflatastic in #552
  • Control channel: menu/dialog requests wait for their job; right-click menus at the point; MCP ui_pointer button (#510, #511, #512, #514) by @bflatastic in #548
  • Automation: non-object params rejected; headless sees finished jobs; serve stdio survives a bad line; MCP batch keeps results (#503, #504, #505, #506, #529) by @bflatastic in #546
  • Formats: deep .pcraft groups reopen; zero-size PSD rejected; JPEG mattes over white; no-ICC formats get sRGB (#517, #519, #521, #522) by @bflatastic in #555
  • Preferences merge with other tabs/windows and retry failed saves; web startup shows a Reload hint (#475, #476, #477) by @bflatastic in #561
  • FreeBSD CI: run the GPU integration tests one at a time by @bflatastic in #576
  • Import warns when it keeps only the first frame or page, or a JPEG ends early (#518, #523) by @bflatastic in #563
  • Linux: AppImage update information and a .zsync beside it (#349) by @ianswope in #399
  • Color Picker and Color panel fields accept typed values by @carterwsmith in #485
  • Release 0.3.0 by @bflatastic in #577