agentleFS
midasmatterhornmidasmatterhorn/artcraft-skills/photocraft/SKILL.md

photocraft

Skill66 starsChanged 8 days agoMITView on GitHub

PhotoCraft is the ArtCraft clean-room, pure-Rust reimplementation of Adobe Photoshop — layers, masks, adjustment layers, layer styles, live type, vectors, smart objects and real PSD read/write, with every action exposed as an engine command that the UI, a headless CLI, a JSON control channel and a 26-tool MCP server all drive. Trigger this skill whenever the user mentions PhotoCraft, asks what it can or cannot do, which file formats it reads or writes, its keyboard shortcuts, how to script, automate or batch it, how to prepare assets for it, how to inspect, verify or repair a .pcraft, PSD, XCF or .ora it produced, or how to troubleshoot it — and also when they never name the app but describe the job, such as "edit this photo", "open this PSD", "make a transparent PNG", "batch-resize a folder of images", "remove the background with a quick selection", "convert these HEIC/NEF/PCX files" or "check what is in this layered file". It is early alpha — never promise Photoshop-grade PSD fidelity, generative AI features or a stable UI, and prefer the headless CLI and MCP over driving the GUI blind.

  • Installs packages

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

5 rules. About 0 are common, 3 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Read this before assigning work — several of these are why agents must not promise Photoshop behaviour.

    line 72
  2. Distinctive:

    Distribution gaps: no in-app bug-report dialog (DIST-220-3 missing), no periodic update recheck while the app stays open (DIST-220-1 …

    line 85
  3. Distinctive:

    Wayland: no drag-and-drop (winit 0.30 limit) and XWayland fractional scaling is blurred (README.md).

    line 86
  4. Very specific:

    Never launch the GUI just to inspect a file — use the CLI.

    line 103
  5. Very specific:

    Version projects: Keep the .pcraft for lossless re-edits and hand Photoshop the PSD/PSB.

    line 170

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

PhotoCraft

Audit basis. Refreshed 2026-11-07 against tag v0.21.0, commit efb7ebd0c0dab1fc108ee4642aa47c22694271a8 — git rev-parse HEAD in the pinned checkout confirms, and the installed bundle matches at 0.21.0 (its photocraft-cli prints photocraft-cli 0.21.0 (efb7ebd0c, 2026-11-06)). The previous release this skill described was v0.20.1 (327c4cc).

v0.20.1 → v0.21.0 delta. 916 files changed (+127,407/−6,129) and the registry grew while the automation method sets stood still. 993 commands now answer (photocraft-cli commands | wc -l on the installed bundle; 953 at v0.20.1) and menu parity is 660/660 (docs/parity-checklist.md:5, floor crates/ui-egui/src/menus/parity.rs:10). New: the Frame tool family layer.frame.{set,setContent,fit,convert,info}; OpenType Numerals (type.openType.numerals.*, 9 ids) and Stylistic Sets 1–20 (crates/engine/src/cmd/type_extra_cmds.rs); memory supervision — file.approveMemory (crates/engine/src/cmd/file_cmds.rs:293) behind a pre-flight gate (crates/engine/src/memory_gate.rs) and native scratch storage (crates/engine/src/scratch.rs), with --approve-high-memory on the CLI. JPEG XL is the 23rd codec format and is export-only (crates/codecs/src/format.rs:110 [Format; 23], :287 read: false, lossless via zune-jpegxl). Actions gained playback/history controls (21 actions.* ids) and the EVENTS table holds 204 rows with a new target_event! family (crates/engine/src/cmd/atn_cmds/events.rs:378). Locale catalogs 26 → 27 (Bosnian). filter.* measures 124 live ids (47 filter.gallery.*, 64 pairwise, 13 workspace/lifecycle) and filter.blur.shapeBlur is new. Unchanged at v0.21.0: control channel 28 methods, MCP 26 tools, headless serve 19 methods, 68 tools, 16 adjustment kinds, 10 layer effects, 34 blend modes, the 14 fail-closed filesystem commands — crates/automation moved only in jobs/progress and workspace internals.

v0.19.0 → v0.20.1 delta. 276 files changed; the wave was the Actions (.atn) surface — recorded Camera Raw Filter steps importing as filter.cameraRaw, string-class handling for Vibrance sets, a strict export of partial Levels edits refused, Stroke steps writing the settings they leave at default, and an Actions panel that records into the selected set (crates/engine/src/actions_record.rs, crates/engine/src/cmd/atn_cmds/). Also editable arrowheads on the Line tool (crates/vector/src/shapes.rs) and buffer-reuse work in the filter path. Older rounds (the bundled CLI and locale wave of v0.18.0, and v0.17.0) are folded into CHANGES.md; the facts from them that still matter live in the sections below.

Verify against your installed version — the ArtCraft Launcher auto-updates, so a newer build may differ; every count quoted here was re-measured at this tag, and code paths that moved were re-cited. The measurement method for each count is in evidence.md.

Overview

PhotoCraft is "Image editing; an open-source, clean-room reimplementation of Adobe Photoshop, rebuilt in pure Rust" (README.md), MIT/Apache-2.0 dual licence, storytold/photocraft. The native app is egui/eframe 0.37 on wgpu, using the shared craft-ui docking, with a CPU compositor kept as the reference oracle; the same engine and UI compile to WebAssembly (apps/photocraft-web). Every menu item, tool and dialog is one engine command, so the UI, photocraft-cli, the loopback JSON control channel and the MCP server run the same code (crates/engine/src/cmd.rs build()). Maturity is early alpha; docs/gaps.md (last updated 2026-11-05) is the ranked shortfall list against Photoshop 2026. All 660 Photoshop menu items are wired to a command (docs/parity-checklist.md:5, floor enforced at crates/ui-egui/src/menus/parity.rs:10); wiring is dispatch, not behaviour.

Capabilities (verified)

Editing core

  • Documents and colour: RGB, Grayscale, CMYK, Lab, Bitmap, Indexed, Multichannel, Duotone at 8/16/32-bit; ICC management in pure Rust with Assign/Convert to Profile, four rendering intents, black-point compensation, soft proofing and Gamut Warning (crates/cms, crates/engine/src/cmd.rs adjustments, CMYK compositing on stored inks).
  • Layers: pixel layers, groups (new-group dialog; new layers join an open group and its clip group), clipping masks, pixel and vector masks with Density/Feather, fill layers (solid/gradient/pattern), adjustment layers, live smart objects with smart filters and lossless transforms/warps (including Cylinder), artboards (New Document can start as an artboard; Artboard from Layers takes a custom size), alpha channels (drag-reorder in the Channels panel), Quick Mask, layer comps, advanced blending with per-layer Transparency Shapes Layer (crates/doc/src/lib.rs, crates/doc/src/effects.rs).
  • 16 adjustment layers: layer.newAdjustmentLayer.{brightnessContrast, levels, curves, exposure, vibrance, hueSaturation, colorBalance, blackWhite, photoFilter, channelMixer, invert, posterize, threshold, gradientMap, selectiveColor, colorLookup} plus the same 16 as destructive image.adjustments.*, all generated from the 16-entry ADJ table (crates/engine/src/cmd.rs:1093). Extra destructive-only: Shadows/Highlights, Replace Color, Match Color, HDR Toning; 32-bit Hue/Saturation and Colorize behave as in Photoshop.
  • 10 layer effects, several instances per kind: DropShadow, InnerShadow, OuterGlow, InnerGlow, Stroke, ColorOverlay, GradientOverlay, PatternOverlay, Satin, BevelEmboss (separate Highlight/Shadow mode dropdowns), driven by layer.layerStyle.* commands (crates/doc/src/effects.rs, crates/engine/src/layer_style.rs); .asl style libraries import.
  • Blend modes: PassThrough + 27 Photoshop modes + 6 Paint.NET-only modes = 34 enum variants (crates/color/src/blend.rs); Shift+Alt+letter picks a blend mode from the keyboard.
  • 68 tools — pub const ALL: [Tool; 68] (crates/ui-egui/src/state/tool.rs:82), every classic Photoshop tool is now present: Art History Brush landed in v0.18.0 (upstream marks it partial, TOOL-213-20, docs/gaps.md G6). Includes Remove, Spot/Healing/Patch, Content-Aware Move, Mixer Brush (renders mixed paint live during the stroke), Magnetic Lasso, Object/Quick Selection, Pen/Freeform/Curvature Pen, Type and Type Mask, Perspective Crop, Frame, Slice; mode dropdowns for Clone/Pattern Stamp, History Brush, Healing and Paint Bucket.
  • Selections: marquee/lasso/wand, select.quick, select.object, select.subject, select.colorRange, select.focusArea, select.refineEdge, select.magneticLasso; Select and Mask refinement is guided-filter matting with Smooth/Feather/Contrast/Shift Edge and colour decontamination (crates/algo/src/matting.rs) — classical, no learned models; Select and Mask stays a dialog, not a workspace (crates/engine/src/cmd/cutout_cmds.rs, docs/gaps.md G7). Remove Background (Properties › Quick Actions) turns Select Subject + edge refinement into a layer mask in one history step.
  • 124 live filter.* command ids (counted from the registry, not from string literals): 47 Filter Gallery filters from the gallery! table in crates/algo/src/artistic.rs:38 (each registered as filter.gallery.<key> by crates/engine/src/cmd/gallery_cmds.rs, plus filter.filterGallery itself), 64 pairwise filters registered in crates/engine/src/filters.rs/filters_ext.rs, and 13 workspace/lifecycle ids (filter.blurGallery.{field,iris,path,spin,tiltShift}, filter.liquify, filter.adaptiveWideAngle, filter.cameraRaw, filter.vanishingPoint, filter.lensCorrection, filter.lastFilter, filter.convertForSmartFilters). filter.blur.shapeBlur is new at v0.21.0. Filters applied to a smart object become re-editable smart filters; 53 PSD filter classes map one-to-one to 53 distinct commands through filterFX (crates/io/src/smart_map/import.rs KNOWN: [Known; 53]) — Diffuse, Trace Contour, Crystallize, Pointillize and Halftone Pattern round-trip like Photoshop. Field/Iris/Tilt-Shift/Spin Blur are on-canvas; Path Blur is still a parameter dialog.
  • Type: point/area/paragraph text on canvas, Character/Paragraph controls (paragraph-direction buttons, partial), manual+optical kerning with PSD round trip, variable-font axes, editable font size/leading/tracking preset menus, font menu with favourites/recents/class filters/live preview, type.warpText, type.resolveMissingFonts; headless editing via type.editText, type.hitTest, type.caret, type.navigate. OpenType Numerals (Adobe's figure styles: type.openType.numerals.{default,lining,oldstyle,proportional,proportionalLining,proportionalOldstyle,tabular,tabularLining,tabularOldstyle}) and Stylistic Sets 1–20 (type.openType.stylisticSets.set1…set20) sit alongside the eight older feature toggles, all in crates/engine/src/cmd/type_extra_cmds.rs. Type on a path follows path edits and PSD round-trips through the file's Txt2 (crates/psd/src/tiff.rs, docs/gaps.md G8).
  • Vectors: Pen/Freeform/Curvature, anchor add/delete/convert, Paths panel, work paths, shape layers with dashed/aligned strokes, corner radii and gradient strokes (gradient stroke turns with the canvas), path↔selection, SVG as editable shape layers or vector smart object (crates/engine/src/cmd/, docs/shape-strokes.md).
  • Actions: 21 live actions.* commands (list/get/record/stop/play/move/delete/toggle/rename/load/save/insert/dialog/assignSet/newSet/setColor/conditional, plus stopMessage, performance, setPlayback, setHistory, createSingleHistoryState) with nesting to 16 levels; 204 rows in the EVENTS table (crates/engine/src/cmd/atn_cmds/events.rs:378) for .atn import/export, built from ev!, adjustment_event!, stylize_event!, selection_event!, clipping_event! and the new target_event!; unsupported event kinds are preserved verbatim and fail at playback by name; actions ending in Save As/Close work (the result is taken at the Save step).
  • History: New Snapshot dialog, History Options with Allow Non-Linear History and undoable visibility changes (crates/engine/src/cmd/, History panel rebuild).
  • Photomerge: file.automate.photomerge (reposition/perspective) as a cancellable background job.
  • Frame tool: five commands — layer.frame.set, layer.frame.setContent, layer.frame.fit, layer.frame.convert, layer.frame.info — for placing and re-fitting a frame's content (new at v0.21.0).
  • Memory supervision: file.approveMemory clears an operation that the pre-flight gate refused, crates/engine/src/memory_gate.rs asking whether an allocation can still be satisfied before it starts (a refusal changes nothing and says what to do), and crates/engine/src/scratch.rs holds the native tile-storage settings outside the preference model; the CLI exposes the same approval as --approve-high-memory.
  • Print: File › Print renders one flattened page and prints through an in-process pure-Rust IPP client, the Linux print portal, the Windows spooler or to a PDF file; file.printers lists queues, "dryRun": true previews (crates/engine/src/cmd/print_cmds.rs, docs/printing.md).
  • Video-lite: 7 timeline.* commands and file.export.renderVideo (PNG sequence or animated GIF); animating GIF and WebP open every frame through New Video Layer from File.
  • Update check: Help › Check for Updates, an opt-out once-per-launch release-feed check, and a startup self-update prompt modal (crates/engine/src/cmd/updates_cmds.rs, self-update delegated to the shared craft-update crate).

Files — read / write

  • Native .pcraft: directory bundle or zip of STORE entries = manifest.json (format version 1; manifests with too many JSON values are refused before parsing) + content-addressed BLAKE3/zstd tiles/+blobs/ + thumb.png + composite preview; incremental, atomic (temp/fsync/rename), crash-recovery autosaves with single-step sidecar replacement (crates/format/src/).
  • Read + write: PSD/PSB/PSDT (PSB chosen by encoded size; spot channels in Photoshop's polarity; MTrn merged transparency; layered TIFF text descriptors keep PSD byte order), layered TIFF including alpha and spot channels as extra samples, plus Photoshop's global layer mask block (crates/io/src/tiff_layers.rs, crates/codecs/src/codecs/tiff/), OpenRaster .ora, PDF write-only one flattened page, and the flat codecs: PNG, JPEG, TIFF, WebP (lossless + own lossy VP8), GIF, BMP, TGA, ICO, Netpbm (PBM/PGM/PPM/PAM/PFM), QOI, DDS (uncompressed or BC1/BC2/BC3 + optional mip chain, exports the document alpha), OpenEXR, Radiance HDR, FITS, DPX, Cineon, Amiga IFF (24-bit ILBM writer) and JPEG XL (lossless export only) (crates/codecs/src/format.rs:110 Format::ALL [Format; 23]).
  • 23 codec formats; every one is read+write except the documented asymmetries (ASYMMETRIC_EXCEPTIONS, crates/codecs/src/format.rs): read-only PCX, XPM and DICOM, JPEG XL write-only (lossless through the pure-Rust zune-jpegxl; JPEG XL reading is tracked separately — crates/codecs/src/format.rs:90), AVIF write-only behind the non-default avif feature, HEIF/HEIC read-only behind heif (on in official builds).
  • Layered imports (read-only): Paint.NET .pdn/PDN3, Krita .kra/.krz, GIMP .xcf/.xcf.gz, Affinity .af*, SVG; writing an import-only target is refused with a naming error in export_stages (crates/io/src/lib.rs).
  • Camera raw: DNG (uncompressed/deflate/lossless-JPEG/lossy-JPEG/floating-point JPEG XL — lossy DNGs now decode, falling back to the JPEG XL preview rather than the tiny thumbnail), CR2, TIFF/EP raws (NEF, ARW, PEF), Nikon compressed NEF, Sony cRAW, Panasonic RW2, uncompressed Olympus ORF, uncompressed Fujifilm RAF; Camera Raw settings sidecars (.xmp, crs: namespace) load, auto-fill the dialog when beside the raw file, and are written by Save Settings (crates/io/src/camera_raw_xmp.rs); Calibration panel, Auto button and live Camera Raw Defaults. CR3 remains preview-only — upstream assessed a clean-room CRX reader as not feasible (docs/gaps.md G14).
  • Export As offers exactly png, jpg, webp, tif, tga, ico (crates/engine/src/cmd/export_preset_cmds.rs:13); Save for Web offers gif, png8, png24, jpeg, wbmp, webp; Quick Export as PNG is a single menu item; the Save As picker lists every supported format.
  • Honest exports: caps(format) and fidelity_warnings report depth reduction, CMYK→RGB, dropped layers and missing fonts before writing; CLI/info/app.save surface them as warnings.

Automation surfaces (counts re-measured at v0.21.0)

  • One command registry, 660/660 menu items live (crates/ui-egui/src/menus/parity.rs, docs/parity-checklist.md:5). The live registry at this tag measures 993 commands (photocraft-cli commands | wc -l on the installed bundle that matches this tag). Table macros still expand per row (the 16-entry ADJ table alone generates 32 commands), so a static count stays uncertain by a few dozen — the CLI remains the authority. README's "500+" and docs/architecture.md's "~700" are floors, not measurements.
  • CLI photocraft-cli — 8 subcommands + help: convert, info, run, batch, droplet, commands, mcp, serve (apps/photocraft-cli/src/args.rs:31; re-verified live from the installed bundle), exit codes 0 ok / 1 failure / 2 usage. 12 export flags shared by convert/run/batch: --format --quality --tiff-layers --tiff-compression --tiff-transparency --tiff-pyramid --tga-bits --dpx-bits --dds-compression --dds-mipmaps --jpeg-format --pcraft-full-composite (the last three are new at v0.21.0; convert/run also take --approve-high-memory and --gpu/--no-gpu). batch folder sources accept every format PhotoCraft opens.
  • Control channel (photocraft --control <port>, loopback only): first frame must be {"id":"auth","method":"auth","params":{"token":"<64 hex>"}}; then 28 methods, unchanged at v0.21.0 — engine.execute, engine.commands, jobs.list, jobs.cancel, ui.inspect, ui.set, ui.menu.invoke, ui.menu.list, ui.pointer, ui.click, ui.move, ui.key, ui.type, ui.resize, ui.focus, ui.screenshot, ui.context.choose, ui.dialog.open/set/confirm/apply/cancel, ui.window.open/close, ui.gpu.simulateLoss, app.open, app.save, app.quit (crates/ui-egui/src/control/dispatch.rs handler chain). Transports: apps/photocraft/src/control_server.rs; 60 s reply timeout, 1 MiB request cap, 16 connections; request paths refuse Windows device names and replacing a non-image file inside the write root. Preferences › Integrations wires Allow Agent Control and the control port in the UI.
  • MCP — 26 tools, unchanged at v0.21.0 (crates/automation/src/server.rs #[tool] entries): session_list, doc_open, doc_place, doc_replace_smart_object, doc_export_layers, doc_export_data_sets, doc_import_data_sets, doc_new, doc_save, doc_export, doc_inspect, doc_render_preview, render_preview, doc_select, doc_close, command_list, command_run, jobs_list, jobs_cancel, command_batch, ui_inspect, ui_screenshot, ui_pointer, ui_menu_invoke, ui_set, control_call — unchanged as a set since 0.16.0, though waited commands now run as jobs with progress and cancel. 2 MCP resources (photocraft://document, photocraft://commands, crates/automation/src/server/conventions.rs). Bridge-only: the five ui_* tools + control_call; headless-only: doc_select, doc_close.
  • Headless server photocraft-cli serve (stdio or --port) answers 19 methods, unchanged at v0.21.0 (crates/automation/src/rpc.rs:42 METHODS): engine.execute, jobs.list, jobs.cancel, engine.commands, session.list, doc.open/place/replaceSmartObject/new/save/exportLayers/exportDataSets/importDataSets/inspect/render/select/close, batch, methods.
  • Automation budgets: 8 MiB reply, 5 MiB PNG, preview max_side 2048, 64 M source pixels for renders, 256 batch steps, 30 s IO timeout, 10 s auth deadline (crates/automation/src/budgets.rs, security.rs).
  • Plug-ins: WebAssembly ABI v1 only — plugin.list/install/remove/reload/run (5 commands), wasmi sandbox, no WASI/filesystem/network/clock, 32 MiB module, 512 MiB memory, 50 M instructions + 4,000 per sample, 60 s per run; duplicate manifest parameters are refused (docs/plugins.md, crates/plugins/src/runtime.rs).
  • Batch/droplets: photocraft-cli batch takes an actions JSON, an Actions set (--action picks by name) or a .atn set, applies it to a folder with {name}/{serial}/{date} output templates, and refuses --out == --in unless --in-place. .pcdroplet droplets run via file.automate.runDroplet.

Platform

  • macOS (universal, signed+notarized), Windows x64/x86/ARM64 (per-user MSI install is now the default policy), Linux x86_64/aarch64 (AppImage, Flatpak, deb, rpm, tarball), FreeBSD 14, and a WebAssembly web build (README.md Downloads; docs/scorecard.md DIST rows — Windows signing is skipped with a warning until the signing material exists).
  • GPU compositor on wgpu (Metal/Vulkan/DX12/WebGPU) with CPU fallback, --safe-gpu, automatic device-loss fallback, one place records why a view left the GPU, and ui.gpu.simulateLoss (with destroy: true) for testing.
  • Pen tablets (docs/hardware-parity.md, crates/tablet): macOS pressure/tilt/barrel-rotation (rotation not applied to tip angle); Windows pressure only (tilt and rotation missing); Linux X11 pressure+tilt with partial rotation; web pressure/tilt/twist; native Wayland tablet-v2 still open.

Known limitations and not-implemented

Read this before assigning work — several of these are why agents must not promise Photoshop behaviour.

  • Alpha, by measurement: docs/gaps.md (updated 2026-11-05) is the ranked shortfall list; the ROADMAP percentages were measured at 0.6.0 and have not been recomputed. Performance scorecard: read docs/scorecard.md for the current pass/budget rows rather than trusting any snapshot here. The ROADMAP's headline rows (menus, tools, formats) are stale — the generated parity checklist and the code win.
  • PSD fidelity is the blocking gap (G1): enforced corpus floors are minimums — Photoshop-authored oracles 190/258, psd-tools 249/308, io corpus 148/169, round trips 258/258-era floors as CI enforces (crates/io/tests/it/corpus.rs:151-159). A re-saved PSD is never byte-identical to its source (only the standalone photocraft-psd crate reproduces corpus files byte for byte), and Photoshop failing to reopen our files is tracked upstream (docs/gaps.md G1).
  • No generative AI: no ONNX runtime or ML crate in the workspace; no Neural Filters, generative fill/expand, sky replacement or generative Remove. Select Subject/Remove Background and Refine Edge are classical algorithms (GrabCut/max-flow segmentation; guided-filter matting — the "local models" are local linear models of the guided filter). Learned segmentation remains open (docs/gaps.md G15).
  • No native Photoshop plug-ins: .8BF, CEP and UXP are not hosted; only the Wasm ABI v1 (ABI v2 with panels/progress still open) (docs/gaps.md G16).
  • Workspaces that are dialogs (G7): Select and Mask is a dialog, no Content-Aware Fill sampling workspace, Vanishing Point has a plane editor but no clone-in-plane, and Path Blur is still a parameter dialog while Field/Iris/Tilt-Shift/Spin are on-canvas.
  • Type depth (G8): OpenType Numerals and Stylistic Sets 1–20 are menu commands at v0.21.0 (they landed after the previous round), and type on a path follows path edits; still open are the RTL visual caret and parts of the paragraph-direction UI (docs/gaps.md G8).
  • Formats absent: Photoshop PDF read; EPS/DCS and generic EPS/AI; Cloud PSD .psdc; JPEG 2000; Pixar; MPO/JPS; PICT; Scitex CT; Photoshop Raw; AVIF read; JPEG XL read (it is export-only). WBMP is not a codec but Save for Web writes it. Affinity, Paint.NET, Krita and XCF are import-only (writable targets are refused in crates/io/src/lib.rs). File › Open takes only a GIF/WebP animation's first frame (use New Video Layer from File for all frames) and per-frame delays are not kept in .pcraft (docs/file-format-parity.md).
  • Camera raw partial: CR3 sensor data no (preview only; clean-room CRX assessed as not feasible), "lossy after split" NEF no, no Fuji colour calibration, Olympus ORF and Fujifilm RAF only uncompressed. Raw .xmp settings sidecars now load and save (camera-raw settings only — not a general XMP metadata writer).
  • Dead preferences: 10 of 192 settings do nothing (docs/scorecard.md:212, generated by the prefs audit; was 12 of 181 at the previous pin, and docs/gaps.md's header still says 11 of 183). CI regenerates that count, so re-read the scorecard rather than trusting this line.
  • Automation is fail-closed: these 14 commands are refused over control/MCP/serve — file.open, file.openAs, file.save, file.saveAs, file.saveACopy, file.export.saveForWebLegacy, pattern.import, layer.smartObjects.{exportContents, replaceContents, relinkToFile, convertToLinked}, measurementLog.export, layer.videoLayers.reloadFrame, edit.colorSettings; path params of other commands (layer.exportAs, filter.distort.displace mapPath, preset imports, plug-in install, layer.setAdjustment {"file": …}, prefs.set on file-backed sections) are refused too, and the desktop app additionally refuses image.mode.* (crates/automation/src/workspace/tests.rs:315 pins the list; workspace.rs enforces it).
  • Localization: UI strings translated, engine messages stay English; 27 locale catalogs at v0.21.0 (crates/ui-egui/src/i18n/*.tsv; Bosnian is new) and some remain partial (ROADMAP.md Languages, docs/gaps.md G13).
  • Distribution gaps: no in-app bug-report dialog (DIST-220-3 missing), no periodic update recheck while the app stays open (DIST-220-1 partial — there is a startup prompt now), Windows signing skipped without secrets (DIST-2 partial).
  • Wayland: no drag-and-drop (winit 0.30 limit) and XWayland fractional scaling is blurred (README.md).
  • Docs lag the code — verify against your installed version before asserting a feature is missing; the generated scorecard/parity-checklist numbers are trustworthy, hand-written prose in the same docs can lag.

How to operate

Launch (macOS)

open -a PhotoCraft                        # normal GUI launch
open -a PhotoCraft /path/to/file.psd      # open a file in the running instance
open -a PhotoCraft --args --control 7878 --control-token-file "$HOME/.photocraft/control.token" \
     --automation-read-root "$PWD" --automation-write-root "$PWD"
  • Binary: Contents/MacOS/PhotoCraft inside the app bundle. The macOS bundle also ships photocraft-cli beside it (Contents/MacOS/photocraft-cli, since 0.18.0); older bundles and other platforms: get the CLI from photocraft-cli-<ver>-macos-universal.zip (signed, notarized), cargo install --path apps/photocraft-cli --locked, or the Linux .deb/.rpm, which install photocraft-cli on PATH.
  • App flags, parsed by clap so a typo is a usage error (exit 2): files, -h/--help, --version, --safe-gpu, --in-window-menus, --new-instance, --present-mode <fifo|vsync|autovsync|novsync|immediate|mailbox|autonovsync>, --frame-latency <1..3>, --stroke-trace <stderr|FILE.csv>, --control <port>, --control-token <64-hex>, --control-token-file <path>, --automation-read-root <dir>, --automation-write-root <dir>, -- (apps/photocraft/src/launch_args.rs). Env equivalents: PHOTOCRAFT_CONTROL_PORT, PHOTOCRAFT_CONTROL_TOKEN(_FILE), PHOTOCRAFT_AUTOMATION_{READ,WRITE}_ROOT, PHOTOCRAFT_CONFIG_DIR, PHOTOCRAFT_NEW_INSTANCE. A token flag given without a value now fails the launch instead of silently falling back (#6429).
  • Without any token flag, a fresh 256-bit one is generated and printed to stderr; a token file is created mode 0600. Treat it as a credential: it grants the whole non-filesystem control surface over unencrypted loopback (crates/automation/src/security.rs server_token, docs/control-protocol.md).
  • Never launch the GUI just to inspect a file — use the CLI. On macOS occluded windows stop rendering, so ui.screenshot raises the window and steals focus (ui.screenshot {focus:false} avoids it).

Headless CLI

photocraft-cli convert in.psd out.pcraft [--format <ext>] [--quality 1-100] [--tiff-layers] \
    [--tiff-compression none|lzw|zip] [--tiff-transparency on|off] [--tiff-pyramid] \
    [--jpeg-format baseline|optimized|progressive] [--pcraft-full-composite] \
    [--tga-bits 24|32] [--dpx-bits 8|10|12|16] [--dds-compression none|bc1|bc2|bc3] [--dds-mipmaps] \
    [--in-place] [--approve-high-memory]
photocraft-cli info out.pcraft [--compact]              # JSON: size, mode, depth, layer tree, warnings
photocraft-cli run in.png --cmd layer.new.layer --params '{"name":"Ink"}' \
                        --cmd filter.blur.gaussianBlur --params '{"radius":3}' \
                        --out out.psd <same export flags>
photocraft-cli run --new '{"width":800,"height":600,"background":"white"}' --cmd document.inspect --out new.pcraft
photocraft-cli batch --actions actions.json [--action <name>] --in ./raw --out ./graded [--format jpg] [--in-place]
photocraft-cli droplet job.pcdroplet ./images [--out ./done]
photocraft-cli commands [--json] [--filter blur]
photocraft-cli mcp [--bridge 127.0.0.1:7878] [--control-token <hex> | --control-token-file <path>] \
                   [--automation-read-root <dir>] [--automation-write-root <dir>]
photocraft-cli serve [--port <port>] [--control-token <hex> | --control-token-file <path>] \
                   [--automation-read-root <dir>] [--automation-write-root <dir>]

Behaviour that bites: each --params belongs to the --cmd before it; run needs exactly one of <FILE> or --new, and at least one --cmd or --out; command results are one JSON line each on stdout while warnings go to stderr; convert/run refuse an <OUT> that is the <IN> unless --in-place; batch refuses an --out equal to --in (canonicalised, so symlinks count), refuses to overwrite a same-named output, and fails the file whose nested action fails; --quality sets JPEG and lossy WebP (without it WebP is lossless); an operation the memory gate refuses needs --approve-high-memory here, or file.approveMemory over automation; MCP --bridge and serve --port refuse automation roots/token flags they cannot honour.

Document and window model

One window holds the open documents as tabs (the control channel exposes them as window.document.<index> in tab order, active one checked); ui.window.open adds an extra window. On Windows and Linux a second launch hands its files to the running instance as new tabs; --new-instance and any --control launch start a separate process (macOS relies on LaunchServices).

Open / save / export flow

  • Open: File › Open (Cmd+O), drag-and-drop, open -a PhotoCraft <file>, photocraft-cli, or app.open/doc.open over automation. Save (Cmd+S) writes back to the document's own PSD/PSB/.pcraft; Save As (Cmd+Shift+S) picks the format from the extension — .pcraft for lossless native, PSD/PSB for Photoshop handoff, any writable codec extension for flat output, .pdf for one flattened page, .cin for Cineon, .iff for Amiga IFF, .jxl for lossless JPEG XL, .dds with DDS Options. .pcraft output can carry the flattened document at canvas size as composite/full.png (--pcraft-full-composite, or check the manifest's full_composite member). Long opens/saves run as cancellable background jobs with progress. PSD/PSB open reads channel data as decoded, in bands, without loading the whole file.
  • Over the control channel/MCP use app.open/app.save (desktop) or doc.* (serve/MCP) with paths relative to the automation roots; the refused ambient commands are listed above. Embedded smart objects are the exception that works: layer.smartObjects.editContents, saveContents, convertToLayers run pathless, and the capability-scoped doc_place (MCP), doc.replaceSmartObject (serve) and doc_replace_smart_object read beneath the read root.
  • Modal workspaces gate menu invocation: while Camera Raw, Liquify, Content-Aware Fill, Filter Gallery or Adaptive Wide Angle is open, ui.menu.invoke refuses every other item and accepts only that workspace's {"ui":{…}} requests — finish with {"ui":{"commit":true}} or {"ui":{"cancel":true}} first (docs/control-protocol.md). engine.execute is not gated.
  • Keyboard shortcuts: authoritative tables are crates/engine/src/shell_commands.rs (shell + tool defaults) and the menu catalogue. Verified examples: Cmd+O/Cmd+S/Cmd+Shift+S, Cmd+Alt+Shift+W Export As, Cmd+F Search…, Cmd+J Layer via Copy, Cmd+D Deselect, F5 Brush Settings, F6 Color, F7 Layers; Shift+Alt+letter selects a blend mode. Photoshop .kys sets import/export through edit.keyboardShortcuts.

State on disk

  • Settings: macOS ~/Library/Application Support/Photocraft/ (preferences.json, Presets/ with .pcbrushes, actions.json, gradient/style presets, .asl style libraries, ui.ron for window and dock geometry); Windows %APPDATA%\Photocraft; Linux $XDG_CONFIG_HOME/photocraft or ~/.config/photocraft. Override with PHOTOCRAFT_CONFIG_DIR; portable mode (portable.txt or PhotoCraft.portable beside the executable) keeps everything in <exe dir>/PhotoCraftData (apps/photocraft/src/app_dirs.rs).
  • Crash recovery: <data dir>/Recovery/<key>.pcraft directory bundles plus <key>.json metadata, offered at the next launch and deleted when the document is saved or closed. Autosave interval is preference fileHandling.autosaveMinutes, default 10, valid 1–240.

Working with an AI agent

Preferred ladder — use the highest rung that answers the question:

  1. Headless CLI for convert/inspect/batch; no GUI, no token (photocraft-cli convert|info|run|batch|droplet|commands).
  2. MCP headless (photocraft-cli mcp --automation-read-root … --automation-write-root …) for command sequences plus inspection; without roots it has no file authority (by design).
  3. Control channel on a live app (--bridge, or photocraft --control) when UI state, dialogs, pointer gestures or screenshots are genuinely required.
  4. GUI pointer events last — ui.pointer/ui.key are validated and replayable but depend on window focus on macOS.

Legitimate work:

  • Prepare inputs: convert any supported source to .pcraft/PSD/PNG (or DDS textures with --dds-compression/--dds-mipmaps), resize/grade via batch, generate actions JSON or droplets, pre-export assets for other Craft apps. HEIC, NEF/CR2/DNG, XCF, KRA, PDN and Affinity files are sources, not deliverables.
  • Read and interpret documents: photocraft-cli info <file> JSON, or document.inspect/layer.list/document.pixel over MCP; .pcraft manifest.json is plain JSON and can be read directly.
  • Verify exports: reopen with photocraft-cli info, read stderr warnings, probe pixels, compare size/alpha. Do not byte-compare a re-saved PSD to its source — PhotoCraft rewrites image resources, layer records and the composite, so only reopening the file tells you it is right.
  • Repair by regeneration, not by hand: .pcraft tiles/blobs are content-addressed zstd objects — never edit them in place. Rebuild from the source image, an earlier bundle or the app; a bundle with a newer format_version is refused with a clear error (crates/format/src/migrate.rs).
  • Batch safely: batch will not silently overwrite and fails a file whose nested action fails; MCP command_batch is not atomic (earlier steps stay applied, no rollback), so inspect history afterwards and undo per entry. Long steps accept wait: false and are polled/cancelled with jobs.list/jobs.cancel.

Do not: assign generative-AI work, expect Photoshop to always open our PSD exports, assume a format is supported because Photoshop has it, drive the GUI blind when a headless command exists, use image.mode.* from desktop automation, assume XCF/KRA/PDN/Affinity files can be saved back, or trust doc statements that the code contradicts.

Verification protocol

PhotoCraft is alpha: verify every artefact, never trust a silent export.

  1. Round-trip smoke test in a scratch directory: photocraft-cli run --new '{"width":64,"height":64,"background":"white"}' --cmd layer.new.layer --out t.pcraft, then photocraft-cli info t.pcraft, then photocraft-cli convert t.pcraft t.png and open the PNG in another viewer. For edits, insert a command between --new and --out and read each command's JSON line.
  2. Read the warnings. Depth reduction, CMYK→RGB, dropped layers, clipped values and missing fonts print to stderr on convert/run/batch and appear in info/app.save warnings. An export with no warning is the only export you should believe.
  3. Version projects. Keep the .pcraft for lossless re-edits and hand Photoshop the PSD/PSB; keep the original source. Re-saved PSDs are not byte-identical, and .pcraft migrates on load — never downgrade a bundle.
  4. Update only between projects. This skill documents 0.21.0 (v0.21.0, commit efb7ebd0); a launcher auto-update can change how files save. If the installed app differs, re-verify formats and counts (photocraft --version prints version, commit and build date — crates/engine/src/build_info.rs; the bundled photocraft-cli --version prints the same triple).
  5. Prefer reversible operations. Work on copies (image.duplicate, or history.newDocument which creates a new active document by default), inspect document.inspect history, and remember automation saves never fire script events.

Sources & evidence

  • Repo: https://github.com/storytold/photocraft — inspected at tag v0.21.0, commit efb7ebd0c0dab1fc108ee4642aa47c22694271a8, inspection date 2026-11-07; the v0.20.1 tree (327c4cc82e737a3e0af7c147a477126d77525495) was read for the delta and for counting both sides of it.
  • Installed app: /Applications/PhotoCraft.app — version 0.21.0, bundle id ai.storyteller.photocraft, minimum macOS 11.0; Contents/MacOS holds PhotoCraft and the bundled photocraft-cli, which was run read-only (--version, commands, --help) and prints photocraft-cli 0.21.0 (efb7ebd0c, 2026-11-06); the GUI was not launched.
  • Key files read: README.md, docs/gaps.md, docs/scorecard.md, docs/parity-checklist.md, docs/{control-protocol,mcp,file-format-parity,plugins,printing,batch-naming}.md, Cargo.toml, apps/photocraft/src/launch_args.rs, apps/photocraft-cli/src/args.rs, crates/engine/src/{cmd,actions_record,memory_gate,scratch,shell_commands,build_info}.rs, crates/engine/src/cmd/{gallery_cmds,file_cmds,export_preset_cmds,web_cmds,type_extra_cmds,cutout_cmds,updates_cmds}.rs, crates/engine/src/cmd/atn_cmds/events.rs, crates/engine/src/{filters,filters_ext}.rs, crates/ui-egui/src/state/tool.rs, crates/ui-egui/src/menus/parity.rs, crates/ui-egui/src/control/dispatch.rs, crates/ui-egui/src/i18n/, crates/doc/src/effects.rs, crates/color/src/blend.rs, crates/algo/src/{artistic,matting}.rs, crates/codecs/src/format.rs, crates/codecs/src/codecs/{tiff/,iff.rs}, crates/io/src/{lib,camera_raw_xmp,tiff_layers}.rs, crates/io/src/smart_map/import.rs, crates/io/tests/it/corpus.rs, crates/format/src/manifest.rs, crates/raw/src/lib.rs, crates/automation/src/{server,server/conventions,rpc,security,budgets}.rs, crates/automation/src/workspace{,/tests.rs}, crates/plugins/src/runtime.rs, crates/vector/src/shapes.rs.
  • Shared libraries: storytold/craft-libs, all craft crates pinned to one revision in Cargo.toml (craft-ui, craft-print, craft-docpath, craft-jpeg, craft-update); only the pinning relationship was consulted, not shared-library behaviour.
  • Per-claim evidence, the count methods and this round's corrections: evidence.md next to this file.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.