Skip to main content

Automate PhotoCraft with the CLI and MCP

Batch-convert PSDs with photocraft-cli and connect Claude Code, Claude Desktop or Cursor to PhotoCraft's open-source MCP server, with scoped file access.

Unofficial community guideUpdated Oct 11, 2026

You can automate PhotoCraft in two ways. photocraft-cli, the command-line tool that comes with every desktop release, converts, inspects and batch-processes images without opening a window. photocraft-cli mcp starts an MCP server, so AI assistants such as Claude Code, Claude Desktop and Cursor can open documents, run any of PhotoCraft's 500+ engine commands, look at a preview and save the result. The server runs either as a headless session or as a bridge that drives the PhotoCraft window you have open. Both routes run the same commands as the menus. This page describes v0.7.0 (11 October 2026). Automation is still changing quickly, so check photocraft-cli --help for your version.

Where is photocraft-cli?

There is no separate download on Windows or Linux. The CLI ships inside the normal packages, and only macOS has its own CLI file:

PackageWhere the CLI is
Windows MSIC:\Program Files\PhotoCraft\photocraft-cli.exe, or wherever you installed PhotoCraft. Not on PATH
Windows portable zipphotocraft-cli.exe, next to photocraft.exe in the unzipped folder
macOSThe separate photocraft-cli-<ver>-macos-universal.zip. The DMG's PhotoCraft.app contains only the desktop app
Linux .deb / .rpm/usr/bin/photocraft-cli
Linux tarball (x86_64, aarch64, riscv64)bin/photocraft-cli inside the unpacked folder
Linux FlatpakInside the sandbox: flatpak run --command=photocraft-cli ai.storyteller.photocraft
Linux AppImageNot reachable: the AppImage starts the desktop app only
FreeBSD tarballbin/photocraft-cli

The 32-bit x86 MSI installs to Program Files (x86)\PhotoCraft on 64-bit Windows. The macOS CLI is signed and notarized. It is a universal binary for Apple silicon and Intel, and macOS checks the notarization online the first time you run it. Install steps for each system are in Windows, macOS and Linux, and every file is on the download page.

Check that it works:

photocraft-cli --version
photocraft-cli --help

The command-line tool

Subcommands

CommandWhat it does
convert <in> <out>Open one file and save it in another format, chosen by the extension (.pcraft, .psd, .png, .jpg, .tif, .webp, .exr, …)
info <file>Print the document as JSON: size, mode, depth and layer tree. --compact prints one line
runOpen a file (or create one with --new <json>), run engine commands in order, and optionally save with --out
batchApply an action to every image in one folder
dropletRun a .pcdroplet file on files or folders
commandsList the command registry. --filter <text> narrows it, --json adds the parameter docs
mcpStart the MCP server on stdio
serveKeep a headless session open and answer JSON lines on stdio or a loopback port

convert, run and batch also take --format <ext>, --quality <1-100> (JPEG and WebP; a WebP saved with a quality is lossy, without one it is lossless) and --tiff-layers (TIFF output is flat unless you ask for layers). photocraft-cli <subcommand> --help prints the full usage.

The README's example chains two commands and exports a PNG:

photocraft-cli run wave.psd \
  --cmd filter.sharpen.smartSharpen     --params '{"amount":80}' \
  --cmd layer.newAdjustmentLayer.curves --params '{"points":[[0,0],[64,48],[192,212],[255,255]]}' \
  --out wave-final.png

Each --params belongs to the --cmd before it. run prints one JSON line per command result. Find command IDs and their parameters with photocraft-cli commands --filter blur (or --json for the parameter docs), and see shortcuts for the menu names behind them.

Exit codes and typos

The CLI exits with 0 on success, 1 when the job failed and 2 for a usage error. A flag the subcommand doesn't take, such as --fromat, is a usage error rather than being silently ignored. In batch, one failed file makes the whole run exit with 1, but the other files are still processed.

Missing font reports

Since v0.6.0 (#1299), the CLI tells you when a type layer uses a font family that isn't installed, so a fallback rendering isn't passed off as exact:

  • convert and run write warning: font '<family>' is not installed; text may render using a fallback face to standard error before exporting.
  • info --compact puts the same text in its warnings JSON array instead of standard error.
  • run also adds warnings to the JSON result of the command where the missing family first appears, and reports each family once.

The warnings don't stop the export and don't change the saved font names. To list or replace missing families on purpose, run the engine command type.resolveMissingFonts.

Batch: one action, a whole folder

photocraft-cli batch --actions grade.json --in ./raw --out ./graded
photocraft-cli batch --actions actions.json --in photos/ --out done/ --format jpg

How it behaves, as of v0.7.0:

  • The actions file. It holds the steps of an action: [["<id>", {…}], …], [{"command": "<id>", "params": {…}}, …] or bare IDs, either as a plain list or wrapped in {"actions": …} or {"steps": …}. A .pcdroplet file works too.
  • Inputs. Only image files directly inside --in are processed, in name order. Subfolders are not read.
  • Outputs. Each result is saved as <out>/<name>.<ext>. The extension comes from --format, or from the input file when there's no --format. --out is created if it doesn't exist.
  • No silent overwrites inside a run. If two inputs would produce the same output name (for example a.png and a.jpg saved as JPEG), the second one is reported as a failure instead of replacing the first.
  • Originals are protected. batch refuses an --out that is the same folder as --in, unless you pass --in-place.
  • Output. Each file prints ok <in> -> <out> or FAIL <in>: <error>, and a summary line follows.

Actions and droplets

Record an action in the desktop Actions panel, select it, then:

  • File › Automate › Batch… runs it on a folder from inside the app. The dialog suggests a batch output folder and lets you pick the format: same, png, jpg, psd or tiff.
  • File › Automate › Create Droplet… saves it as a .pcdroplet file, which photocraft-cli can run later. On macOS, Linux and FreeBSD it also writes a small .command script next to the droplet. You can drop files on that script or pass them to it, and it calls photocraft-cli droplet (it uses the PHOTOCRAFT_CLI environment variable if set, otherwise photocraft-cli from your PATH).
photocraft-cli droplet grade.pcdroplet ./raw --out ./graded

Without --out, a droplet writes to its saved output folder, or else to droplet-output next to the first input.

What changed in v0.7.0:

  • Actions that call other actions work in Batch. File › Automate › Batch now gives every file a copy of your whole Actions list. A batched action can therefore call another action (a Play Action step, actions.play), and a step that fails inside the called action fails that file instead of being reported as done (#2783). The same check now applies to scripts run with File › Scripts › Browse.
  • Recorded saves are replaced by the destination. Actions can now record File › Save and Save As (#2746). Batch and Create Droplet drop those steps, because the output folder decides where files go, as Photoshop's "Override Action 'Save As' Commands" does.
  • Zoom and fit steps are skipped. Batch and droplets no longer reject an action that contains recorded View steps such as Zoom In or Fit on Screen (#2761). Older droplets that contain them now run.

One limit as of v0.7.0: photocraft-cli batch and photocraft-cli droplet start with an empty Actions list, so a Play Action step has nothing to call there. For the CLI, use an action that doesn't call other actions.

The MCP server

Headless or bridge

HeadlessBridge
Startphotocraft-cli mcp --automation-read-root <dir> --automation-write-root <dir>photocraft-cli mcp --bridge 127.0.0.1:<port> --control-token-file <path>
EngineRuns inside the CLI process, with no window and no GPUThe desktop app, started with --control <port>
You see the editsNo. Ask for previewsYes, live in the window
File accessThe roots passed to the CLIThe roots passed to the desktop app
Extra toolsdoc_select, doc_closeui_inspect, ui_screenshot, ui_pointer, ui_menu_invoke, ui_set, control_call

Both modes speak MCP over stdio, so the headless server opens no network port. Use headless mode for unattended batch work, and bridge mode when you want to watch the edits or have the assistant use tools and dialogs in the real UI.

File roots: what the assistant can touch

File access is off unless you grant it when the server starts:

  • --automation-read-root <dir> lets the server open files beneath <dir>.
  • --automation-write-root <dir> lets it save and export beneath <dir>.

Read and write are separate. If you leave a flag out, that direction is denied, and requests fail with a message such as automation filesystem access is not granted: read authority is absent. The README's bare photocraft-cli mcp starts a server that can create and edit documents in memory but can't open or save any file. For headless mode you must pass the flags: the PHOTOCRAFT_AUTOMATION_READ_ROOT and PHOTOCRAFT_AUTOMATION_WRITE_ROOT environment variables only configure the desktop app. Use absolute paths to a folder you chose for this purpose, such as a dedicated photocraft-work folder, never your whole home directory.

Paths in tool calls can be:

  • Relative to the root, with forward slashes: in/cat.psd.
  • Absolute, beneath the root. Since v0.7.0 (#2216, fixing #2176), C:/work/in/cat.psd or C:\work\in\cat.psd is accepted when the root is C:\work. Earlier versions only accepted relative paths.

The absolute-path check is deliberately strict. PhotoCraft compares the request with the root as text, component by component, and only the drive letter ignores case. It never resolves the path on disk. Everything else is refused before any file is touched: paths outside the root, .., the root itself, Windows device names such as CON, alternate data streams such as a.bin:hidden, other spellings of the same place (\\?\C:\…, 8.3 short names, or a root reached through a symlink) and symbolic links that lead out of the root. The file is then opened through the same directory handle as a relative path. Follow-up tests in #2528 cover look-alike sibling folders and sub/../.. climbs. The folder that will hold a new output file must already exist.

Engine commands that take their own file paths are blocked over automation, with the error automation command `…` uses ambient filesystem paths and is disabled; use capability-scoped document methods. That covers almost every file.* command, including file.open, file.save and file.automate.batch, and path parameters such as layer.exportAs {path}. Use the doc_open, doc_save and doc_export tools instead. A few path-free file.* commands stay available, such as file.new and file.automate.fitImage.

Register the server with Claude Code

Since v0.7.0 the MCP docs show how to register an installed release (#2185). Replace <dir> with your work folder:

# Windows, default install folder
claude mcp add photocraft -- "C:\Program Files\PhotoCraft\photocraft-cli.exe" mcp --automation-read-root <dir> --automation-write-root <dir>
# Linux, or macOS with the CLI unzipped onto PATH
claude mcp add photocraft -- photocraft-cli mcp --automation-read-root <dir> --automation-write-root <dir>

You can also check a .mcp.json into a project root. This is the upstream example. The first entry is headless, the second is the bridge described below. Upstream writes a source-build path for command, so replace it with your installed CLI (for example /usr/bin/photocraft-cli):

{
  "mcpServers": {
    "photocraft": {
      "command": "/path/to/photocraft/target/release/photocraft-cli",
      "args": ["mcp", "--automation-read-root", "/absolute/path/to/trusted/workspace", "--automation-write-root", "/absolute/path/to/trusted/workspace"]
    },
    "photocraft-live": {
      "command": "/path/to/photocraft/target/release/photocraft-cli",
      "args": ["mcp", "--bridge", "127.0.0.1:7878", "--control-token-file", "/private/path/photocraft-control.token"]
    }
  }
}

Claude Desktop

Upstream documents Claude Code only. Claude Desktop reads the same mcpServers block from its own claude_desktop_config.json, which you can open from Claude Desktop's settings. Give the full path to the CLI, then restart Claude Desktop. On Windows, backslashes in JSON must be doubled:

{
  "mcpServers": {
    "photocraft": {
      "command": "C:\\Program Files\\PhotoCraft\\photocraft-cli.exe",
      "args": ["mcp", "--automation-read-root", "C:\\Users\\you\\Pictures\\photocraft-work", "--automation-write-root", "C:\\Users\\you\\Pictures\\photocraft-work"]
    }
  }
}

On macOS, set command to wherever you put the unzipped binary, such as /usr/local/bin/photocraft-cli. On Linux with the .deb or .rpm, use /usr/bin/photocraft-cli.

Cursor and other MCP clients

Upstream has no Cursor-specific instructions as of v0.7.0. Any client that starts stdio MCP servers from a command and an argument list can use the same command and args values shown above. Check your client's documentation for where its config file lives. Since v0.6.0 the tool schemas contain no $ref, $defs or boolean schemas (#1845), because some strict LLM providers rejected the whole request when they did (#1782).

With the Flatpak, the CLI runs inside the sandbox, so the command is flatpak with run --command=photocraft-cli ai.storyteller.photocraft mcp … as arguments. The sandbox can only see your Pictures and Documents folders, so put the roots there.

Bridge mode: drive the running app

  1. Start PhotoCraft with the control channel, a private token file and the roots:

    photocraft --control 7878 --control-token-file /private/path/photocraft-control.token \
      --automation-read-root /work/project --automation-write-root /work/project
    

    On Windows the app is C:\Program Files\PhotoCraft\photocraft.exe. In a macOS install it is /Applications/PhotoCraft.app/Contents/MacOS/PhotoCraft. If the token file doesn't exist, PhotoCraft creates it with a fresh 256-bit token (mode 0600 on Unix; on Windows, restrict the file to your user yourself). With no token file and no token, PhotoCraft makes one for that launch and prints it to standard error.

  2. Point the MCP client at the bridge, with the same token file:

    photocraft-cli mcp --bridge 127.0.0.1:7878 --control-token-file /private/path/photocraft-control.token
    

In bridge mode the desktop app owns the file roots, so set them on photocraft, not on the bridging CLI. The bridge only connects to loopback addresses. If a request fails in transit, for example after a timeout, the bridge reports that the edit may have happened and does not send it again (#1527). Inspect the document before retrying. The app waits up to 60 seconds for each reply. On Wayland, a sleeping display or a fully covered window can make every request time out even though the app is fine.

doc_save in bridge mode saves with the app's current settings. Since v0.6.0 it refuses format, quality, tiffLayers and index instead of quietly ignoring them (#1138). The Flatpak's sandbox has no network access, so the control port isn't reachable from outside it. The Flatpak manifest notes that flatpak override --user --share=network ai.storyteller.photocraft exposes it to agents on the host.

Tools

Upstream calls these five the shared core tools: command_list, command_run, command_batch, doc_inspect and render_preview. The full list as of v0.7.0 (documented since #1573):

ToolWhat it doesMode
command_listEngine command IDs, labels, menu paths, parameter docs and whether each can run now. Takes filter and enabled_onlyBoth
command_runRun one command: id, optional params and waitBoth
command_batchRun up to 256 steps in order, with stop_on_error (default true). One history step per command, not an atomic transactionBoth
doc_inspectLayer tree, history and selection as JSONBoth
render_preview, doc_render_previewFlattened PNG preview (index, max_side)Both; a window screenshot in bridge mode
session_listOpen documents and the active oneBoth
doc_openOpen a file beneath the read rootBoth
doc_newNew document (default 1920×1080, RGB, 8-bit, white)Both
doc_save, doc_exportSave or export beneath the write root. The extension picks the format, and there are quality and tiffLayers optionsBoth (options headless only)
doc_select, doc_closeSwitch to or close a document (closing doesn't save)Headless only
jobs_list, jobs_cancelWatch and cancel background jobsBoth
ui_inspect, ui_screenshotLive UI state, and a window screenshotBridge only
ui_pointer, ui_menu_invoke, ui_setPointer or pen strokes in document coordinates, menu items, tool and panel stateBridge only
control_callAny control-protocol methodBridge only

doc_save without a path only writes back to a PSD, PSB or .pcraft file in its own format. Any other save needs a path, so a flattened or converted copy never replaces the file you opened. Unknown tool arguments are rejected before anything runs. The resources photocraft://document and photocraft://commands return the same live JSON as doc_inspect and command_list.

Long commands: jobs and Render Video

Filters, Content-Aware Fill and Scale, Photomerge and brush imports can take a while. By default command_run waits for them to finish. With "wait": false the result is a job ID at once. Poll it with jobs_list, which shows progress from 0 to 1, or stop it with jobs_cancel. A cancelled or failed job leaves the document unchanged, and other edits to the same document fail until the job ends.

Since v0.6.0 (#1668), a headless command_run of file.export.renderVideo reports progress per frame and can be cancelled. Create a document and a timeline first (doc_new, then timeline.create). The upstream example writes a PNG sequence into frames beneath the write root:

{"jsonrpc":"2.0","id":20,"method":"tools/call","params":{"name":"command_run","arguments":{"id":"file.export.renderVideo","params":{"dir":"frames","format":"png"}},"_meta":{"progressToken":"export-20"}}}
{"jsonrpc":"2.0","method":"notifications/cancelled","params":{"requestId":20}}

Progress notifications come only when the client sends a progressToken, and at most ten per second. Cancelling stops at a frame boundary and removes only the files this job created. Existing files with the same names are refused up front, so an earlier export is never replaced. PNG sequences and animated GIF use the same renderer. Render Video stays synchronous even with wait: false. It isn't available in bridge mode or from inside actions, and steps in command_batch get no progress or per-step cancel. Whether you can cancel a running tool call depends on your MCP client.

Previews

render_preview returns a flattened PNG. max_side defaults to 1024 and goes up to 2048, and 0 asks for full size within that limit. In headless mode index previews another open document without switching to it. Since v0.6.0, an index that doesn't exist, or any index in bridge mode, is an error rather than a wrong picture (#1600). Headless previews are also capped at 67,108,864 source pixels and a 5 MiB PNG. In bridge mode the preview is a screenshot of the app window. For checking an edit, doc_inspect is often better than a picture: it reports layer kinds, bounds, masks, effects, smart filters, type text and adjustment settings.

Other ways in: control channel, serve and scripts

  • Control channel. photocraft --control <port> accepts authenticated JSON lines on 127.0.0.1 from any script, not just MCP. The first line must be {"id": "auth", "method": "auth", "params": {"token": "<64 hexadecimal characters>"}}. It can do everything the bridge tools do, including ui.pointer, ui.screenshot and engine.execute. The README's screenshots were rendered this way. Every method is listed in control-protocol.md.

  • photocraft-cli serve. One headless session that answers JSON lines (doc.open, engine.execute, batch, doc.save, …) on stdio, or on a loopback port with --port and a token. It is faster than MCP for scripts that make many edits, and it uses the same root flags:

    printf '%s\n' \
      '{"id":1,"method":"doc.open","params":{"path":"in.jpg"}}' \
      '{"id":2,"method":"batch","params":{"steps":[{"command":"image.adjustments.invert"},{"command":"filter.blur.gaussianBlur","params":{"radius":3}}]}}' \
      '{"id":3,"method":"doc.save","params":{"path":"out.png"}}' | \
      photocraft-cli serve --automation-read-root /work/project --automation-write-root /work/project
    
  • Scripts in the app. File › Scripts › Browse… runs a script file: a JSON action, or plain text with one command.id {json params} per line and # comments. File › Scripts › Script Events Manager… runs a script on events such as opening or saving a document. Opens and saves made through automation never fire script events.

The web build, including the online editor, can't be automated this way, because a browser can't listen on a port. Use a desktop build.

Recipes

Convert a folder of PSDs to PNG

convert handles one file at a time, so loop over the folder:

mkdir -p png
for f in psd/*.psd; do
  photocraft-cli convert "$f" "png/$(basename "${f%.psd}").png"
done
$cli = "C:\Program Files\PhotoCraft\photocraft-cli.exe"
New-Item -ItemType Directory -Force png | Out-Null
Get-ChildItem psd\*.psd | ForEach-Object { & $cli convert $_.FullName "png\$($_.BaseName).png" }

Watch standard error for warning: lines, which cover missing fonts and anything PNG can't hold.

Resize a folder and export JPEGs

Save this as resize.json. file.automate.fitImage scales each image to fit inside the box, keeps the aspect ratio, and with dontEnlarge leaves smaller images alone:

[["file.automate.fitImage", {"width": 1600, "height": 1600, "dontEnlarge": true}]]
photocraft-cli batch --actions resize.json --in ./photos --out ./web --format jpg --quality 85

To set an exact width instead, use ["image.imageSize", {"width": 1200}]. With only width, the height follows the aspect ratio.

Run a recorded action on many files

  1. Record the action in the Actions panel and select it.

  2. File › Automate › Create Droplet… saves it as a .pcdroplet.

  3. Run it from a terminal, a scheduled task or another script:

    photocraft-cli droplet grade.pcdroplet ./raw --out ./graded
    # or with the batch options:
    photocraft-cli batch --actions grade.pcdroplet --in ./raw --out ./graded --format png
    

If the action calls another action, run it from File › Automate › Batch… in the app instead (see Actions and droplets).

Ask an AI assistant to resize and export

With the headless server registered and photocraft-work as both roots, put the files in photocraft-work/in, create photocraft-work/out, and ask something like:

Open in/cover.psd, fit it inside 1600×1600 without enlarging it, show me a preview, then export out/cover.jpg at quality 85.

A capable assistant calls doc_open, then command_run with file.automate.fitImage, then render_preview and doc_export with quality: 85. For several edits in one round trip it can use command_batch:

{"steps": [{"id": "file.automate.fitImage", "params": {"width": 1600, "height": 1600, "dontEnlarge": true}}, {"id": "filter.sharpen.smartSharpen", "params": {"amount": 80}}], "stop_on_error": true}

For many files, tell the assistant the file names, or let it list the folder with its own tools (Claude Code can). PhotoCraft's MCP server has no tool for listing a directory, and file.automate.batch is blocked over automation, so the assistant processes one file after another: open, edit, export, doc_close. For a fixed recipe on a big folder, photocraft-cli batch is faster and doesn't depend on the model.

Limits and safety

  • The CLI subcommands are not sandboxed. convert, run, batch and droplet take ordinary operating-system paths and can read and write anywhere your account can. Only the MCP server and serve are limited to the roots. Run action files and droplets from untrusted sources in an isolated account or machine.
  • A token is not a permission system. Anyone with the control token gets the whole non-file control surface: commands, pointer and keyboard input, and quitting the app. There are no per-tool scopes yet, and the tools' annotation hints don't grant permission. Keep token files private, don't commit or log them, and avoid --control-token on shared machines where other users can see command lines.
  • Keep it on your machine. The control protocol is unencrypted and listens on loopback only. Don't tunnel, proxy or expose it, or the stdio server, to another host or an untrusted broker. Upstream advises against leaving the control port on permanently.
  • Treat content as untrusted. Document text, layer names and tool descriptions can contain instructions aimed at an AI. Grant the narrowest roots, prefer separate input and output folders, and keep secrets out of file names, metadata and command parameters.
  • Ceilings. command_batch takes at most 256 steps. Tool results are capped at 8 MiB. TCP request lines are capped at 1 MiB (MCP over stdio has no request cap), with 16 connections per listener and a 30-second socket timeout. A batch that runs out of reply budget stops, and edits it already made are not rolled back. Inspect the document before retrying.
  • Bounded output is not bounded cost. There is no session memory budget or general command timeout, so a huge document or an expensive filter can still take a long time.
  • Alpha software. PhotoCraft is early alpha, and command parameters can change between releases. Ask the assistant to call command_list instead of relying on remembered IDs.

Common errors

Message (excerpt)Meaning
automation filesystem access is not granted: read authority is absentThe server was started without --automation-read-root (or write for saves)
absolute paths must be inside the automation rootThe absolute path isn't beneath the root as written. Check spelling, the drive letter and symlinks
automation command `…` uses ambient filesystem paths and is disabledA file.* command or path parameter was used. Use doc_open, doc_save or doc_export
… drives the live GUI and needs bridge modeA ui_* tool or control_call was used in headless mode
… is still running on this documentA background job holds the document. Wait for it, or call jobs_cancel

Found a bug in the CLI or MCP server? Report it on GitHub with your OS, PhotoCraft version, the exact command or tool call, and the error.

Related guides