editmamei 0.17.3 → 0.17.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -1363
- package/dist/bin/editmamei-core-darwin-arm64 +0 -0
- package/dist/bin/editmamei-core-darwin-x64 +0 -0
- package/dist/bin/editmamei-core-win-x64.exe +0 -0
- package/dist/delivery/signing.js +3 -3
- package/dist/license/env-activation.js +46 -7
- package/dist/skills/editmamei-skill.zip +0 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,1391 +1,54 @@
|
|
|
1
1
|
# Editmamei
|
|
2
2
|
|
|
3
|
-
**Unlock Photoshop with natural-language photo editing.**
|
|
3
|
+
**Unlock Photoshop with natural-language photo editing.** AI orchestration, not generation.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
(Pronounced like _edamame_. Yes, the snack.)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
> Independent project, not affiliated with or endorsed by Adobe Inc.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
[](./LICENSE)
|
|
12
|
-
[](https://www.typescriptlang.org/)
|
|
9
|
+
[](https://www.npmjs.com/package/editmamei)
|
|
10
|
+
[](https://editmamei.com/license)
|
|
13
11
|
[]()
|
|
14
12
|
|
|
15
|
-
You describe the edit in plain words
|
|
16
|
-
|
|
17
|
-
Editmamei is a Model Context Protocol (MCP) server. It plugs into Claude Desktop, Cursor, or any MCP-compatible client; your AI assistant is the interface and Editmamei drives Photoshop underneath.
|
|
18
|
-
|
|
19
|
-
## How It Works
|
|
20
|
-
|
|
21
|
-
**You talk. Photoshop works.**
|
|
22
|
-
|
|
23
|
-
1. **You describe the edit** in plain language ("warm up the golden hour, lift the shadows, clean up the horizon").
|
|
24
|
-
2. **The AI plans the steps:** which adjustments, which selections, in what order.
|
|
25
|
-
3. **Your Photoshop does the editing** on your machine, using its own standard tools.
|
|
26
|
-
4. **You get a finished photo** that's fully layered, maskable, and editable. Nothing baked in.
|
|
27
|
-
|
|
28
|
-
The AI looks at the result and refines it; Photoshop performs every actual change.
|
|
29
|
-
|
|
30
|
-
### Edited, not generated
|
|
31
|
-
|
|
32
|
-
Most "AI photo" tools are _generative_. They invent new pixels: skies, objects, even faces that were never in your shot. **Editmamei doesn't do that.** It works only with the pixels you captured, using the same non-generative Photoshop tools professionals have used for years: adjustment layers, masks, selections, filters. The AI is the director, not the artist. Your photo is yours, just finished faster.
|
|
13
|
+
Editmamei is a Model Context Protocol (MCP) server that drives the Adobe Photoshop you already have. You describe the edit in plain words; your AI assistant plans the steps; your own copy of Photoshop carries them out with its standard adjustment layers, masks, selections, and filters. The AI directs; Photoshop edits. No generative model touches your pixels.
|
|
33
14
|
|
|
34
|
-
|
|
15
|
+
**[editmamei.com](https://editmamei.com)** · [Docs](https://github.com/editmamei/editmamei-wiki) · [Report a bug](https://github.com/editmamei/editmamei-wiki/issues)
|
|
35
16
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Editmamei does report anonymous, content-free usage telemetry (which tools you run, whether they succeed, how long they take, and your version/OS/Photoshop version) so a small team can see what's breaking and what's used. It carries no images, no paths, and no personal data. It's on by default and easy to turn off: `editmamei config set telemetry.usage false` (or edit `~/.editmamei/settings.json`). Optional diagnostic detail for bug-hunting is off until you opt in with `editmamei config set telemetry.diagnostics true`.
|
|
39
|
-
|
|
40
|
-
When your AI assistant needs to see the result — to verify an edit, say — Editmamei sends it a downscaled preview: to _that AI provider_, the cloud assistant you chose, the same as dropping a photo into a chat with it. That's how the AI judges its own work; it's a property of using a cloud AI, not a hop Editmamei adds.
|
|
41
|
-
|
|
42
|
-
## Features
|
|
43
|
-
|
|
44
|
-
- ✅ **Works on both Windows and macOS**
|
|
45
|
-
- ✅ **Tested on Photoshop 2026 (v27.x)** — earlier versions may work but are unverified. Editmamei's ActionManager descriptor specs are pinned to PS 27.x ScriptListener captures, and Adobe is known to rotate event IDs between major versions; descriptor-shape workarounds for the PS 27.x bugs identified during testing are documented in [docs/20260530-ps27-cross-platform-bug-analysis.md](docs/20260530-ps27-cross-platform-bug-analysis.md).
|
|
46
|
-
- ✅ **ExtendScript API**: Universal compatibility via AppleScript/COM automation
|
|
47
|
-
- ✅ **Auto-Detection**: Finds Photoshop installation on your system
|
|
48
|
-
- ✅ **Comprehensive tool surface**: 80+ Photoshop operations exposed as MCP tools, each with structured input/output, schema validation, and context awareness
|
|
49
|
-
- ✅ **Smart selections**: Sensei-backed Select Subject / Select Sky, plus Color Range, Magic Wand, and a rich `selection_info` feedback bundle on every selection op
|
|
50
|
-
- ✅ **Pipeline export**: PSD copy, JPEG/PNG export with sRGB conversion and resize
|
|
51
|
-
- ✅ **Non-destructive adjustments**: Adjustment layers (curves/levels/HSL/B&C) and layer styles (shadow/stroke/glow)
|
|
52
|
-
- ✅ **Live preview**: Downscaled flattened image returned inline so the AI can see what just happened
|
|
53
|
-
- ✅ **Templates**: Freeze a finished edit as a reproducible recipe; apply it to a new photo by name
|
|
54
|
-
- ✅ **Session telemetry**: NDJSON log of every tool call for debugging + template evidence
|
|
55
|
-
- ✅ **Document management**: Create, open, save, close, crop documents
|
|
56
|
-
- ✅ **Layer operations**: Create, delete, duplicate, merge, transform layers
|
|
57
|
-
- ✅ **Layer properties**: Opacity, blend modes, visibility, locking
|
|
58
|
-
- ✅ **Text formatting**: Font, size, color, alignment controls
|
|
59
|
-
- ✅ **Image placement**: Place images, open files, fit to document
|
|
60
|
-
- ✅ **Filters**: Gaussian Blur, Sharpen, Noise, Motion Blur
|
|
61
|
-
- ✅ **Color adjustments**: Brightness/Contrast, Hue/Saturation, Auto Levels/Contrast
|
|
62
|
-
- ✅ **Selections & masks**: Rectangular selections, layer masks
|
|
63
|
-
- ✅ **History control**: Undo/Redo operations, view history states
|
|
64
|
-
- ✅ **Actions**: Play recorded actions, execute custom scripts
|
|
65
|
-
- ✅ **Auto-rasterize**: Converts layers when needed for filters
|
|
66
|
-
- ✅ **Context tracking**: Returns document/layer state after each operation so the AI keeps a working mental model
|
|
67
|
-
|
|
68
|
-
## Installation
|
|
69
|
-
|
|
70
|
-
End users install from npm — see the public install guide at [editmamei-ce/docs/installation.md](https://github.com/editmamei/editmamei-wiki/blob/main/docs/installation.md):
|
|
17
|
+
## Install
|
|
71
18
|
|
|
72
19
|
```bash
|
|
73
20
|
npm install -g editmamei
|
|
74
|
-
editmamei install
|
|
75
|
-
editmamei status
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
> **Note for early adopters:** `editmamei` on npm currently publishes the `0.0.0-placeholder` stub. The full release lands at v1.0.0. Until then, follow the source-build instructions below to use the current `main`.
|
|
79
|
-
|
|
80
|
-
### Source build (contributors and pre-v1.0 users)
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
git clone https://github.com/editmamei/editmamei.git
|
|
84
|
-
cd editmamei
|
|
85
|
-
npm install
|
|
86
|
-
npm run build # produces dist/
|
|
87
|
-
npm install -g . # makes the `editmamei` CLI available system-wide
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
After this, `editmamei install` and `editmamei status` work identically to the npm-installed flow.
|
|
91
|
-
|
|
92
|
-
## Configuration
|
|
93
|
-
|
|
94
|
-
When you're running from a source build, `editmamei install` still wires Claude Desktop correctly. If you'd rather hand-edit the MCP client config, point it at the built `dist/index.js`. Replace the path below with the absolute path on your machine.
|
|
95
|
-
|
|
96
|
-
### Claude Desktop
|
|
97
|
-
|
|
98
|
-
Edit `%APPDATA%\Claude\claude_desktop_config.json` (Windows) or `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
|
|
99
|
-
|
|
100
|
-
```json
|
|
101
|
-
{
|
|
102
|
-
"mcpServers": {
|
|
103
|
-
"editmamei": {
|
|
104
|
-
"command": "node",
|
|
105
|
-
"args": ["C:\\absolute\\path\\to\\Editmamei\\dist\\index.js"],
|
|
106
|
-
"env": {
|
|
107
|
-
"LOG_LEVEL": "1"
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Cursor
|
|
115
|
-
|
|
116
|
-
Add to your Cursor settings (`.cursor/config.json` or workspace settings):
|
|
117
|
-
|
|
118
|
-
```json
|
|
119
|
-
{
|
|
120
|
-
"mcpServers": {
|
|
121
|
-
"editmamei": {
|
|
122
|
-
"command": "node",
|
|
123
|
-
"args": ["C:\\absolute\\path\\to\\Editmamei\\dist\\index.js"],
|
|
124
|
-
"env": {
|
|
125
|
-
"LOG_LEVEL": "1"
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### Environment Variables
|
|
133
|
-
|
|
134
|
-
- `PHOTOSHOP_PATH`: (Optional) Specify custom Photoshop installation path
|
|
135
|
-
- `LOG_LEVEL`: Logging level (0=DEBUG, 1=INFO, 2=WARN, 3=ERROR)
|
|
136
|
-
|
|
137
|
-
## Example Prompts
|
|
138
|
-
|
|
139
|
-
Drive Editmamei through Claude using natural language:
|
|
140
|
-
|
|
141
|
-
<details>
|
|
142
|
-
<summary>🎨 Basic Design Creation</summary>
|
|
143
|
-
|
|
144
|
-
```
|
|
145
|
-
Create a 1920x1080 Photoshop document with RGB color mode.
|
|
146
|
-
Add a light blue background layer and fill it with RGB(240, 248, 255).
|
|
147
|
-
Add centered text "Welcome" in 64pt font.
|
|
148
|
-
Save as welcome.psd to my Desktop.
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
</details>
|
|
152
|
-
|
|
153
|
-
<details>
|
|
154
|
-
<summary>🖼️ Stock Image Design (with Pexels MCP)</summary>
|
|
155
|
-
|
|
156
|
-
```
|
|
157
|
-
Search Pexels for "mountain sunset" images.
|
|
158
|
-
Create a 1920x1080 Photoshop document.
|
|
159
|
-
Place the downloaded image and fit it to fill the entire canvas.
|
|
160
|
-
Apply a subtle Gaussian blur of 3px.
|
|
161
|
-
Increase brightness by 15 and contrast by 10.
|
|
162
|
-
Add white text "Adventure Awaits" centered at the top in 72pt.
|
|
163
|
-
Set the text opacity to 90% and blend mode to OVERLAY.
|
|
164
|
-
Save as adventure.jpg with quality 10.
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
</details>
|
|
168
|
-
|
|
169
|
-
<details>
|
|
170
|
-
<summary>✨ Photo Enhancement</summary>
|
|
171
|
-
|
|
172
|
-
```
|
|
173
|
-
Open photo.jpg from my Desktop in Photoshop.
|
|
174
|
-
Apply auto levels and auto contrast.
|
|
175
|
-
Apply unsharp mask with amount 120%, radius 1.5, threshold 0.
|
|
176
|
-
Increase saturation by 15.
|
|
177
|
-
Crop to remove 100px from each edge.
|
|
178
|
-
Save as enhanced-photo.jpg with quality 12.
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
</details>
|
|
182
|
-
|
|
183
|
-
<details>
|
|
184
|
-
<summary>🎭 Layer Effects & Blending</summary>
|
|
185
|
-
|
|
186
|
-
```
|
|
187
|
-
Create a 1200x800 document.
|
|
188
|
-
Add a new layer named "Background" and fill with RGB(50, 50, 50).
|
|
189
|
-
Place logo.png at position (100, 100).
|
|
190
|
-
Fit the logo layer to 50% of its current size.
|
|
191
|
-
Set blend mode to SCREEN and opacity to 85%.
|
|
192
|
-
Add another layer, fill with RGB(255, 100, 50).
|
|
193
|
-
Set this layer's blend mode to MULTIPLY and opacity to 60%.
|
|
194
|
-
Merge all visible layers.
|
|
195
|
-
Save as composite.psd.
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
</details>
|
|
199
|
-
|
|
200
|
-
<details>
|
|
201
|
-
<summary>📝 Text Poster Design</summary>
|
|
202
|
-
|
|
203
|
-
```
|
|
204
|
-
Create a 1080x1350 portrait document (Instagram story size).
|
|
205
|
-
Add a layer and fill with gradient-like color RGB(120, 40, 200).
|
|
206
|
-
Add text "SUMMER" at (540, 300) in 96pt.
|
|
207
|
-
Change text color to white RGB(255, 255, 255).
|
|
208
|
-
Set text alignment to CENTER.
|
|
209
|
-
Add another text "2026" at (540, 450) in 128pt, white color.
|
|
210
|
-
Apply Gaussian blur 2px to the background layer.
|
|
211
|
-
Save as summer-poster.png.
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
</details>
|
|
215
|
-
|
|
216
|
-
<details>
|
|
217
|
-
<summary>🎬 Batch Processing</summary>
|
|
218
|
-
|
|
219
|
-
```
|
|
220
|
-
Open image1.jpg.
|
|
221
|
-
Resize to 1920x1080.
|
|
222
|
-
Apply auto contrast.
|
|
223
|
-
Apply subtle sharpen (amount 80%, radius 1.0).
|
|
224
|
-
Save as processed-1.jpg with quality 10.
|
|
225
|
-
Close without saving changes to original.
|
|
226
|
-
|
|
227
|
-
Repeat for image2.jpg and image3.jpg.
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
</details>
|
|
231
|
-
|
|
232
|
-
<details>
|
|
233
|
-
<summary>🖌️ Creative Manipulation</summary>
|
|
234
|
-
|
|
235
|
-
```
|
|
236
|
-
Create a 2000x2000 square document.
|
|
237
|
-
Place abstract-pattern.jpg and fit to fill document.
|
|
238
|
-
Duplicate the layer.
|
|
239
|
-
On the duplicate, apply motion blur at 45 degrees, radius 50px.
|
|
240
|
-
Set blend mode to OVERLAY and opacity to 70%.
|
|
241
|
-
Add centered text "MOTION" in 120pt white.
|
|
242
|
-
Apply a rectangular selection from (200, 200) to (1800, 1800).
|
|
243
|
-
Invert the selection and delete (to create a border effect).
|
|
244
|
-
Flatten the image.
|
|
245
|
-
Save as motion-art.jpg.
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
</details>
|
|
249
|
-
|
|
250
|
-
<details>
|
|
251
|
-
<summary>🎯 Advanced Workflow</summary>
|
|
252
|
-
|
|
253
|
-
```
|
|
254
|
-
Create a 3000x2000 document at 300 DPI for print.
|
|
255
|
-
Place hero-image.jpg and fit to fill the canvas.
|
|
256
|
-
Duplicate the image layer.
|
|
257
|
-
On the duplicate, desaturate it completely.
|
|
258
|
-
Set blend mode to LUMINOSITY and opacity to 50%.
|
|
259
|
-
Create a new layer named "Overlay".
|
|
260
|
-
Fill with RGB(255, 150, 0) and set blend mode to SOFTLIGHT at 30% opacity.
|
|
261
|
-
Add text "PORTFOLIO" at top center (1500, 200) in 96pt.
|
|
262
|
-
Set text color to white.
|
|
263
|
-
Add subtext "2026 Collection" at (1500, 320) in 36pt.
|
|
264
|
-
Create a rectangular selection around the text area.
|
|
265
|
-
Create a layer mask on the overlay layer.
|
|
266
|
-
Merge visible layers.
|
|
267
|
-
Save as portfolio-cover.psd.
|
|
268
|
-
Export as portfolio-cover.jpg at quality 12.
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
</details>
|
|
272
|
-
|
|
273
|
-
<details>
|
|
274
|
-
<summary>🔄 Using Actions</summary>
|
|
275
|
-
|
|
276
|
-
```
|
|
277
|
-
Open my-photo.jpg.
|
|
278
|
-
Play the "Vintage Look" action from "My Actions" set.
|
|
279
|
-
Adjust brightness by -10 to darken slightly.
|
|
280
|
-
Save as vintage-photo.jpg.
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
</details>
|
|
284
|
-
|
|
285
|
-
<details>
|
|
286
|
-
<summary>⚡ Custom Script Execution</summary>
|
|
287
|
-
|
|
288
|
-
```
|
|
289
|
-
Execute this custom ExtendScript code:
|
|
290
|
-
app.beep();
|
|
291
|
-
alert('Processing started!');
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
</details>
|
|
295
|
-
|
|
296
|
-
<details>
|
|
297
|
-
<summary>⏮️ Undo/Redo Operations</summary>
|
|
298
|
-
|
|
299
|
-
```
|
|
300
|
-
Apply Gaussian blur 15px to the active layer.
|
|
301
|
-
[Wait for result]
|
|
302
|
-
Actually, that's too much blur. Undo that.
|
|
303
|
-
Apply Gaussian blur 5px instead.
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
Or:
|
|
307
|
-
|
|
308
|
-
```
|
|
309
|
-
Get the history states to see what operations were performed.
|
|
310
|
-
Undo the last 3 operations.
|
|
311
|
-
Redo 1 step to bring back one operation.
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
</details>
|
|
315
|
-
|
|
316
|
-
## Available Tools
|
|
317
|
-
|
|
318
|
-
### Tool surface conventions
|
|
319
|
-
|
|
320
|
-
Every tool follows the same shape so MCP clients (and the LLMs they host) can plan and validate without guesswork:
|
|
321
|
-
|
|
322
|
-
- **Input fields are snake_case** (`file_path`, `blend_mode`, `font_size`, `target_layer_name`, etc.). Older camelCase aliases are NOT accepted as of 2026-05-27.
|
|
323
|
-
- **Annotations** (`title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) are set on every tool so clients can decide what's safe to call unprompted.
|
|
324
|
-
- **Output schemas + `structuredContent`** are returned on every call. The LLM can program against parsed JSON without string-parsing.
|
|
325
|
-
- **Context tracking**: tools that change _what is active_ or _what exists_ include `context: getContextInfo()` in their structured response (active document, active layer, selection state). Pure setters/filters/selectors are exempt — the LLM's mental model of "what's active" is preserved.
|
|
326
|
-
- **Escape hatch**: `photoshop_execute_script` is tagged `destructiveHint + openWorldHint` and its description leads with "ESCAPE HATCH — prefer a dedicated tool when one exists." As of 2026-05-31 it ships in **Pro only** — see [docs/20260531-tool-removals.md](docs/20260531-tool-removals.md) for the tier-flip rationale.
|
|
327
|
-
- **Editions**: every tool is classified `community` or `pro` in [src/core/tool-tiers.ts](src/core/tool-tiers.ts) (Pro: `photoshop_get_histogram`, `photoshop_select_subject`, `photoshop_select_sky`, `photoshop_template_create_evidence`, `photoshop_template_save`, `photoshop_template_delete`, `photoshop_execute_script`; all others community). The CE bundle excludes Pro tools at build time; runtime registration enforces the same gate as defense-in-depth. The user-facing Pro/CE split is at [editmamei-ce/docs/pro-features.md](https://github.com/editmamei/editmamei-wiki/blob/main/docs/pro-features.md).
|
|
328
|
-
|
|
329
|
-
### Connection & Discovery
|
|
330
|
-
|
|
331
|
-
#### `photoshop_ping`
|
|
332
|
-
|
|
333
|
-
Test connection to Photoshop and report session-start discovery signals. Returns `connected`, plus on success: `version` (folds the former `photoshop_get_version`), `custom_action_sets` (count of user-loaded Action Sets — non-zero means `photoshop_list_actions` / `photoshop_play_action` are worth exploring), `user_templates` (count of saved Editmamei templates), and `open_documents` (names of docs already open in Photoshop). On open-ended editing tasks, follow up with `photoshop_overview` to get the workflow brief.
|
|
334
|
-
|
|
335
|
-
```javascript
|
|
336
|
-
photoshop_ping();
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
#### `photoshop_overview`
|
|
340
|
-
|
|
341
|
-
Orientation brief for the entire MCP — workflow contract, capabilities map by category, verification primitives, escape-hatch policy, known gaps. Returns ~6 KB of markdown in `content[0].text`. **READ THIS FIRST when the user gives you an open-ended editing task** — the per-tool descriptions tell you what one tool does, but the overview tells you HOW to combine them (e.g. the place → preview → bounds_diff → adjust verification loop). Read-only, idempotent, no Photoshop call. Skip it for trivial single-tool requests where you already know which tool fits. Bundle R (2026-06-02).
|
|
342
|
-
|
|
343
|
-
```javascript
|
|
344
|
-
photoshop_overview();
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
### Document Management
|
|
348
|
-
|
|
349
|
-
#### `photoshop_create_document`
|
|
350
|
-
|
|
351
|
-
Create a new Photoshop document.
|
|
352
|
-
|
|
353
|
-
**Parameters:**
|
|
354
|
-
|
|
355
|
-
- `width` (number, required): Document width in pixels
|
|
356
|
-
- `height` (number, required): Document height in pixels
|
|
357
|
-
- `resolution` (number, optional): DPI resolution (default: 72)
|
|
358
|
-
- `color_mode` (string, optional): Color mode - RGB, CMYK, or Grayscale (default: RGB)
|
|
359
|
-
|
|
360
|
-
```javascript
|
|
361
|
-
photoshop_create_document({
|
|
362
|
-
width: 1920,
|
|
363
|
-
height: 1080,
|
|
364
|
-
resolution: 72,
|
|
365
|
-
color_mode: 'RGB',
|
|
366
|
-
});
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
#### `photoshop_get_metadata`
|
|
370
|
-
|
|
371
|
-
Read metadata for the active document. Returns six sections by default: `document` (size, resolution, bit depth, color profile, layer count, saved state), `iptc` (title, author, copyright, dateCreated, keywords, location), `camera` (make/model/lens/EXIF: datetime_original, exposure_time, f_number, iso, focal_length, white_balance, flash, orientation), `gps` (lat/lon/altitude if geotagged), `acr` (Camera Raw develop settings: temperature, tint, exposure, contrast, highlights, shadows, vibrance, saturation, clarity, dehaze, sharpness), and `context` (active doc + active layer + selection state). `camera`/`gps`/`acr` read the source file directly via `exifr` and require it to still be on disk at its original path — if the document was never saved or the source has moved, those sections report unavailable with a reason.
|
|
372
|
-
|
|
373
|
-
Pass `sections=["context"]` for a cheap orientation call that skips the IPTC traversal and the source-file read. This is the recommended call when you just need to know "what's active right now." Read-only.
|
|
374
|
-
|
|
375
|
-
```javascript
|
|
376
|
-
photoshop_get_metadata(); // everything
|
|
377
|
-
photoshop_get_metadata({ sections: ['context'] }); // cheap orientation
|
|
378
|
-
photoshop_get_metadata({ sections: ['camera', 'acr'] });
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
#### `photoshop_close_document`
|
|
382
|
-
|
|
383
|
-
Close the active document.
|
|
384
|
-
|
|
385
|
-
**Parameters:**
|
|
386
|
-
|
|
387
|
-
- `save` (boolean, optional): Save before closing (default: false)
|
|
388
|
-
|
|
389
|
-
#### `photoshop_open_document`
|
|
390
|
-
|
|
391
|
-
Open a file from disk with all PS dialogs suppressed. Raw/HEIC formats fall back to last-used Camera Raw settings. Pipeline-oriented: returns dimensions, color mode, bit depth, and whether the source was a raw format.
|
|
392
|
-
|
|
393
|
-
**Parameters:**
|
|
394
|
-
|
|
395
|
-
- `file_path` (string, required): Absolute path to the file to open
|
|
396
|
-
- `suppress_dialogs` (boolean, optional): Suppress all PS dialogs during open (default: true)
|
|
397
|
-
|
|
398
|
-
```javascript
|
|
399
|
-
photoshop_open_document({
|
|
400
|
-
file_path: 'E:\\Photos\\Inbox\\shell_01.heic',
|
|
401
|
-
});
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
#### `photoshop_save_psd`
|
|
405
|
-
|
|
406
|
-
Save the active document as a layered PSD copy. The working document's filename and dirty state are unchanged (useful in the pipeline so subsequent export calls still target the same in-memory doc).
|
|
407
|
-
|
|
408
|
-
**Parameters:**
|
|
409
|
-
|
|
410
|
-
- `output_path` (string, required): Absolute output path including filename
|
|
411
|
-
- `maximize_compatibility` (boolean, optional): Include flattened composite for compatibility (default: true)
|
|
412
|
-
|
|
413
|
-
```javascript
|
|
414
|
-
photoshop_save_psd({
|
|
415
|
-
output_path: 'E:\\Photos\\Edit\\shell_01.psd',
|
|
416
|
-
});
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
#### `photoshop_export_jpeg`
|
|
420
|
-
|
|
421
|
-
Export the active document as a flattened JPEG. Optionally converts to sRGB and downscales so the long edge equals a target pixel count. Operates on a duplicate — working document is unchanged.
|
|
422
|
-
|
|
423
|
-
**Parameters:**
|
|
424
|
-
|
|
425
|
-
- `output_path` (string, required): Absolute output path including filename
|
|
426
|
-
- `quality` (integer, optional): JPEG quality 0-12 (default: 11)
|
|
427
|
-
- `long_edge_px` (integer, optional): Resize so longest edge equals this value (downscale only)
|
|
428
|
-
- `embed_color_profile` (boolean, optional): Embed color profile (default: true)
|
|
429
|
-
- `convert_to_srgb` (boolean, optional): Convert to sRGB before export (default: true)
|
|
430
|
-
|
|
431
|
-
```javascript
|
|
432
|
-
photoshop_export_jpeg({
|
|
433
|
-
output_path: 'E:\\Photos\\Processed\\shell_01.jpg',
|
|
434
|
-
quality: 11,
|
|
435
|
-
long_edge_px: 2400,
|
|
436
|
-
});
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
#### `photoshop_export_png`
|
|
440
|
-
|
|
441
|
-
Export the active document as a PNG. Choose transparent background (alpha preserved) or flattened onto white. Optionally resizes. Operates on a duplicate — working document is unchanged.
|
|
442
|
-
|
|
443
|
-
**Parameters:**
|
|
444
|
-
|
|
445
|
-
- `output_path` (string, required): Absolute output path including filename
|
|
446
|
-
- `transparent_background` (boolean, optional): Preserve alpha (default: false → flatten onto white)
|
|
447
|
-
- `long_edge_px` (integer, optional): Resize so longest edge equals this value (downscale only)
|
|
448
|
-
- `compression` (integer, optional): PNG compression 0-9, lower = larger/faster (default: 6)
|
|
449
|
-
|
|
450
|
-
```javascript
|
|
451
|
-
photoshop_export_png({
|
|
452
|
-
output_path: 'E:\\Photos\\Processed\\shell_01_t.png',
|
|
453
|
-
transparent_background: true,
|
|
454
|
-
});
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
### Layer Operations
|
|
458
|
-
|
|
459
|
-
#### `photoshop_create_layer`
|
|
460
|
-
|
|
461
|
-
Create a new layer.
|
|
462
|
-
|
|
463
|
-
**Parameters:**
|
|
464
|
-
|
|
465
|
-
- `name` (string, optional): Layer name
|
|
466
|
-
|
|
467
|
-
#### `photoshop_delete_layer`
|
|
468
|
-
|
|
469
|
-
**DESTRUCTIVE:** Delete a layer. With no arg, deletes the currently active layer (backward-compatible). With `name`, recurses into groups and deletes the first match — useful for cleanup workflows where the dead layer is not currently active. To delete a group and all its contents, use `photoshop_delete_group`.
|
|
470
|
-
|
|
471
|
-
**Parameters:**
|
|
472
|
-
|
|
473
|
-
- `name` (string, optional): Layer name to delete by recursive search (defaults to active layer when omitted)
|
|
474
|
-
|
|
475
|
-
#### `photoshop_create_text_layer`
|
|
476
|
-
|
|
477
|
-
Create a text layer.
|
|
478
|
-
|
|
479
|
-
**Parameters:**
|
|
480
|
-
|
|
481
|
-
- `text` (string, required): Text content
|
|
482
|
-
- `x` (number, optional): X position in pixels (default: 100)
|
|
483
|
-
- `y` (number, optional): Y position in pixels (default: 100)
|
|
484
|
-
- `font_size` (number, optional): Font size in points (default: 24)
|
|
485
|
-
|
|
486
|
-
#### `photoshop_fill_layer`
|
|
487
|
-
|
|
488
|
-
Fill the active layer with a solid color.
|
|
489
|
-
|
|
490
|
-
**Parameters:**
|
|
491
|
-
|
|
492
|
-
- `red` (number, required): Red component (0-255)
|
|
493
|
-
- `green` (number, required): Green component (0-255)
|
|
494
|
-
- `blue` (number, required): Blue component (0-255)
|
|
495
|
-
|
|
496
|
-
#### `photoshop_get_layer_tree`
|
|
497
|
-
|
|
498
|
-
Get the full layer tree as nested JSON. Recursively walks groups and reports name, kind, visibility, opacity, blend mode, clipping membership, and (for art layers) bounds. The right call when you need to know what's inside a group.
|
|
499
|
-
|
|
500
|
-
#### `photoshop_select_layer`
|
|
501
|
-
|
|
502
|
-
Make a layer active by name. Recurses into groups; if a name appears more than once, picks the first match in stack order (top-to-bottom). Foundational for multi-layer workflows — use after `photoshop_duplicate_layer` or `photoshop_add_adjustment_layer` when you need to focus a specific layer before applying further operations.
|
|
503
|
-
|
|
504
|
-
**Parameters:**
|
|
505
|
-
|
|
506
|
-
- `name` (string, required): Layer name to make active
|
|
507
|
-
|
|
508
|
-
#### `photoshop_set_layer_opacity`
|
|
509
|
-
|
|
510
|
-
Set the opacity of the active layer.
|
|
511
|
-
|
|
512
|
-
**Parameters:**
|
|
513
|
-
|
|
514
|
-
- `opacity` (number, required): Opacity value (0-100)
|
|
515
|
-
|
|
516
|
-
#### `photoshop_set_layer_blend_mode`
|
|
517
|
-
|
|
518
|
-
Set the blend mode of the active layer.
|
|
519
|
-
|
|
520
|
-
**Parameters:**
|
|
521
|
-
|
|
522
|
-
- `blend_mode` (string, required): NORMAL, MULTIPLY, SCREEN, OVERLAY, etc.
|
|
523
|
-
|
|
524
|
-
Available blend modes: NORMAL, DISSOLVE, DARKEN, MULTIPLY, COLORBURN, LINEARBURN, DARKERCOLOR, LIGHTEN, SCREEN, COLORDODGE, LINEARDODGE, LIGHTERCOLOR, OVERLAY, SOFTLIGHT, HARDLIGHT, VIVIDLIGHT, LINEARLIGHT, PINLIGHT, HARDMIX, DIFFERENCE, EXCLUSION, SUBTRACT, DIVIDE, HUE, SATURATION, COLOR, LUMINOSITY
|
|
525
|
-
|
|
526
|
-
#### `photoshop_set_layer_visibility`
|
|
527
|
-
|
|
528
|
-
Show or hide the active layer.
|
|
529
|
-
|
|
530
|
-
#### `photoshop_set_layer_locked`
|
|
531
|
-
|
|
532
|
-
Lock or unlock the active layer.
|
|
533
|
-
|
|
534
|
-
#### `photoshop_rename_layer`
|
|
535
|
-
|
|
536
|
-
Rename the active layer.
|
|
537
|
-
|
|
538
|
-
#### `photoshop_duplicate_layer`
|
|
539
|
-
|
|
540
|
-
Duplicate the active layer.
|
|
541
|
-
|
|
542
|
-
#### `photoshop_merge_visible_layers`
|
|
543
|
-
|
|
544
|
-
Merge all visible layers into one.
|
|
545
|
-
|
|
546
|
-
#### `photoshop_flatten_image`
|
|
547
|
-
|
|
548
|
-
Flatten all layers into a single background layer.
|
|
549
|
-
|
|
550
|
-
#### `photoshop_convert_to_smart_object`
|
|
551
|
-
|
|
552
|
-
Convert the active layer to a Smart Object so every subsequent filter becomes an editable, non-destructive Smart Filter. Prerequisite for re-editable filter workflows; works on pixel, text, shape, and adjustment layers and auto-promotes the background layer. Inverse of `photoshop_rasterize_layer`.
|
|
553
|
-
|
|
554
|
-
#### `photoshop_rasterize_layer`
|
|
555
|
-
|
|
556
|
-
Rasterize the active layer (convert text/smart object to normal layer). Destructive — the text/smart-object source is lost.
|
|
557
|
-
|
|
558
|
-
#### `photoshop_add_layer_style`
|
|
559
|
-
|
|
560
|
-
Apply a non-destructive layer style (drop shadow, stroke, or outer glow) to the active layer. Editable and removable. Drop shadow uses Multiply blend; outer glow uses Screen; stroke uses Normal.
|
|
561
|
-
|
|
562
|
-
**Parameters:**
|
|
563
|
-
|
|
564
|
-
- `style` (string, required): One of `drop_shadow`, `stroke`, `outer_glow`
|
|
565
|
-
- `color` (object, optional): RGB color `{r, g, b}` (0-255). Defaults: black for shadow/stroke, white for glow
|
|
566
|
-
- `opacity` (number, optional): Effect opacity 0-100 (default: 50)
|
|
567
|
-
- `angle` (number, optional): Drop shadow only — light angle in degrees, 90 = top-down (default: 90)
|
|
568
|
-
- `distance` (number, optional): Drop shadow only — shadow offset in pixels (default: 8)
|
|
569
|
-
- `size` (number, optional): Drop shadow only — blur size in pixels (default: 12)
|
|
570
|
-
- `spread` (number, optional): Drop shadow only — spread 0-100% (default: 0)
|
|
571
|
-
- `stroke_size` (number, optional): Stroke only — width in pixels (default: 3)
|
|
572
|
-
- `stroke_position` (string, optional): Stroke only — `outside` / `inside` / `center` (default: outside)
|
|
573
|
-
- `glow_size` (number, optional): Outer glow only — blur size in pixels (default: 12)
|
|
574
|
-
- `glow_spread` (number, optional): Outer glow only — spread 0-100% (default: 0)
|
|
575
|
-
|
|
576
|
-
```javascript
|
|
577
|
-
photoshop_add_layer_style({
|
|
578
|
-
style: 'drop_shadow',
|
|
579
|
-
color: { r: 0, g: 0, b: 0 },
|
|
580
|
-
opacity: 50,
|
|
581
|
-
distance: 12,
|
|
582
|
-
});
|
|
21
|
+
editmamei install # registers with Claude Desktop, Cursor, Claude Code
|
|
22
|
+
editmamei status # confirms install state + Photoshop detection
|
|
583
23
|
```
|
|
584
24
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
#### `photoshop_move_layer_to_position`
|
|
588
|
-
|
|
589
|
-
Move the active layer relative to another layer.
|
|
590
|
-
|
|
591
|
-
**Parameters:**
|
|
592
|
-
|
|
593
|
-
- `target_layer_name` (string, required): Name of the reference layer
|
|
594
|
-
- `position` (string, required): ABOVE, BELOW, TOP, or BOTTOM
|
|
595
|
-
|
|
596
|
-
> **Removed 2026-05-31:** `photoshop_move_layer_to_top` / `_to_bottom` / `_up` / `_down` were strict subsets of `photoshop_move_layer_to_position` (TOP / BOTTOM / ABOVE+target / BELOW+target) and saw zero LLM usage in six months of session logs. See [docs/20260531-tool-removals.md](docs/20260531-tool-removals.md).
|
|
597
|
-
|
|
598
|
-
### Group Operations
|
|
599
|
-
|
|
600
|
-
Layer groups (LayerSets) are foundational for structured non-destructive editing — drop a stack of adjustments into a single group and you can A/B toggle the whole look via the group's visibility, or apply one mask to the composite by switching the group's blend mode to NORMAL.
|
|
601
|
-
|
|
602
|
-
#### `photoshop_create_group`
|
|
603
|
-
|
|
604
|
-
Create a new layer group (LayerSet) above the active layer with the given name. Optionally moves existing layers into it in one step.
|
|
605
|
-
|
|
606
|
-
**Parameters:**
|
|
607
|
-
|
|
608
|
-
- `name` (string, required): Name for the new group
|
|
609
|
-
- `layers` (string[], optional): Existing layer names to move into the new group. The first listed name ends up on top of the group stack. Layers not found are returned in `not_found`.
|
|
610
|
-
|
|
611
|
-
#### `photoshop_move_layer_to_group`
|
|
612
|
-
|
|
613
|
-
Move a named layer into a named group. The layer is placed at the top of the group stack. Both names are looked up recursively.
|
|
614
|
-
|
|
615
|
-
**Parameters:**
|
|
616
|
-
|
|
617
|
-
- `layer_name` (string, required): Name of the layer to move
|
|
618
|
-
- `group_name` (string, required): Name of the destination group
|
|
619
|
-
|
|
620
|
-
#### `photoshop_set_group_blend_mode`
|
|
621
|
-
|
|
622
|
-
Set a group's blend mode. Default for new groups is `PASSTHROUGH` (adjustments inside affect layers below the group). Change to `NORMAL` when treating the group as a single composite — required for masking a stack of adjustments with one mask.
|
|
623
|
-
|
|
624
|
-
**Parameters:**
|
|
625
|
-
|
|
626
|
-
- `name` (string, required): Group name (recursive search)
|
|
627
|
-
- `blend_mode` (string, required): One of `PASSTHROUGH`, `NORMAL`, `MULTIPLY`, `SCREEN`, `OVERLAY`, `SOFTLIGHT`, `HARDLIGHT`, `COLORDODGE`, `COLORBURN`, `DARKEN`, `LIGHTEN`, `DIFFERENCE`, `EXCLUSION`, `HUE`, `SATURATION`, `COLORBLEND`, `LUMINOSITY`
|
|
628
|
-
|
|
629
|
-
#### `photoshop_ungroup` ⚠️ DESTRUCTIVE
|
|
630
|
-
|
|
631
|
-
Dissolve a group, leaving its contents at the parent level in their existing stack order. The group itself is removed. Requires `confirm: true`. Recoverable only via Edit > Undo.
|
|
632
|
-
|
|
633
|
-
**Parameters:**
|
|
634
|
-
|
|
635
|
-
- `name` (string, required): Group name to dissolve
|
|
636
|
-
- `confirm` (boolean, required): Must be true
|
|
637
|
-
|
|
638
|
-
#### `photoshop_delete_group` ⚠️ DESTRUCTIVE
|
|
639
|
-
|
|
640
|
-
Delete a group AND ALL its contents (including nested groups and their layers). Requires `confirm: true` because the destructive scope is much larger than a single-layer delete. To dissolve a group while keeping its contents, use `photoshop_ungroup` instead.
|
|
641
|
-
|
|
642
|
-
**Parameters:**
|
|
643
|
-
|
|
644
|
-
- `name` (string, required): Group name to delete
|
|
645
|
-
- `confirm` (boolean, required): Must be true
|
|
646
|
-
|
|
647
|
-
#### `photoshop_create_clipping_mask`
|
|
648
|
-
|
|
649
|
-
Clip the active layer to the layer directly below it, using that layer's pixels as the alpha source (the upper layer shows only where the lower one has content). Non-destructive. Equivalent to Layer > Create Clipping Mask. The standalone primitive — `photoshop_add_adjustment_layer` already accepts `clip_to_below` for the adjustment-layer case.
|
|
650
|
-
|
|
651
|
-
### Layer Transformations
|
|
652
|
-
|
|
653
|
-
#### `photoshop_fit_layer_to_document`
|
|
654
|
-
|
|
655
|
-
Scale the active layer to fit or fill the document canvas while maintaining aspect ratio, and center it. Idempotent.
|
|
656
|
-
|
|
657
|
-
**Parameters:**
|
|
658
|
-
|
|
659
|
-
- `mode` (string, optional): `fit` (default) letterboxes the layer inside the canvas; `fill` covers the canvas, cropping the long edge. Both preserve aspect ratio.
|
|
660
|
-
|
|
661
|
-
> **Bundle R (2026-06-02) — background auto-promote.** The three transform tools below (`scale_layer`, `move_layer`, `rotate_layer`) now auto-promote the background layer instead of throwing. They return `background_promoted: true` in the result so the caller sees the side-effect. No more "duplicate first" dance.
|
|
662
|
-
|
|
663
|
-
#### `photoshop_scale_layer`
|
|
664
|
-
|
|
665
|
-
Scale the active layer by a percentage. Auto-promotes the background layer if needed.
|
|
666
|
-
|
|
667
|
-
**Parameters:**
|
|
668
|
-
|
|
669
|
-
- `scale_percent` (number, required): Scale percentage (e.g., 50 for 50%, 200 for 200%)
|
|
670
|
-
- `center_anchor` (boolean, optional): Scale from center (true) or top-left (false). Default: true
|
|
671
|
-
|
|
672
|
-
#### `photoshop_move_layer`
|
|
673
|
-
|
|
674
|
-
Translate the active layer. Three positioning modes — pass exactly one pair:
|
|
675
|
-
|
|
676
|
-
- **Relative**: `delta_x` + `delta_y` (original behavior — offset from current position).
|
|
677
|
-
- **Absolute**: `absolute_x` + `absolute_y` to land the bounds top-left at a specific document-pixel point.
|
|
678
|
-
- **Center**: `center_on_x` + `center_on_y` to land the bounds CENTER at a specific point — use for "place inside the frame opening" workflows.
|
|
679
|
-
|
|
680
|
-
Mixing modes returns a validation error. Auto-promotes the background layer if needed.
|
|
681
|
-
|
|
682
|
-
**Parameters (delta mode):**
|
|
683
|
-
|
|
684
|
-
- `delta_x` (number): Horizontal offset in pixels
|
|
685
|
-
- `delta_y` (number): Vertical offset in pixels
|
|
686
|
-
|
|
687
|
-
**Parameters (absolute mode):**
|
|
688
|
-
|
|
689
|
-
- `absolute_x` (number): Target X for the layer's bounds top-left, in document pixels
|
|
690
|
-
- `absolute_y` (number): Target Y for the layer's bounds top-left, in document pixels
|
|
25
|
+
Then restart your AI client and ask it: _"Is Photoshop connected?"_
|
|
691
26
|
|
|
692
|
-
|
|
27
|
+
Prefer not to use a terminal? Claude Desktop users can install the one-click `.mcpb` extension from [the latest release](https://github.com/editmamei/editmamei-wiki/releases/latest). Full walkthrough in the [install guide](https://github.com/editmamei/editmamei-wiki/blob/main/docs/installation.md).
|
|
693
28
|
|
|
694
|
-
|
|
695
|
-
- `center_on_y` (number): Target Y for the layer's bounds CENTER, in document pixels
|
|
29
|
+
**Requirements:** Adobe Photoshop 2026 (v27.x), Windows 10/11 or macOS 12+, Node.js 20+ (for the npm path), and an MCP-compatible AI client.
|
|
696
30
|
|
|
697
|
-
|
|
31
|
+
## What it does
|
|
698
32
|
|
|
699
|
-
|
|
33
|
+
Editmamei gives your AI assistant a working photographer's toolkit inside Photoshop: open and save documents, build layer stacks, make selections, add non-destructive adjustments, run filters, mask, retouch, and check the result with inline previews and histograms. Your AI calls these as building blocks, so you can say _"make the sky more dramatic but keep the foreground natural"_ instead of clicking through menus.
|
|
700
34
|
|
|
701
|
-
|
|
35
|
+
The full capability surface is at [editmamei.com](https://editmamei.com). The Community and Pro split is in [pro-features.md](https://github.com/editmamei/editmamei-wiki/blob/main/docs/pro-features.md): Community is free and covers the everyday editing surface; Pro adds the reproducible-template system, Sensei-backed Select Subject and Select Sky, and Photoshop Actions plus scripting.
|
|
702
36
|
|
|
703
|
-
|
|
37
|
+
## Privacy
|
|
704
38
|
|
|
705
|
-
|
|
39
|
+
Editmamei runs on your computer and edits in your own Photoshop. No image content, document data, or file paths are sent to Editmamei's servers. It reports anonymous, content-free usage telemetry (on by default; turn it off with `editmamei config set telemetry.usage false`). When your AI assistant needs to see a result, Editmamei sends it a downscaled preview, the same as dropping a photo into a chat with that assistant. Every field is documented in [privacy.md](https://github.com/editmamei/editmamei-wiki/blob/main/docs/privacy.md).
|
|
706
40
|
|
|
707
|
-
|
|
41
|
+
## Docs and support
|
|
708
42
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
**Parameters:**
|
|
714
|
-
|
|
715
|
-
- `radius` (number, required): Blur radius in pixels (0.1-250)
|
|
716
|
-
- `apply_to_active_layer` (boolean, optional): Bake into the active layer instead of a copy. Default `false`.
|
|
717
|
-
|
|
718
|
-
#### `photoshop_apply_sharpen`
|
|
719
|
-
|
|
720
|
-
Apply Unsharp Mask (sharpen) filter to a duplicate of the active layer (default).
|
|
721
|
-
|
|
722
|
-
**Parameters:**
|
|
723
|
-
|
|
724
|
-
- `amount` (number, required): Sharpening amount in percent (1-500)
|
|
725
|
-
- `radius` (number, required): Radius in pixels (0.1-250)
|
|
726
|
-
- `threshold` (number, optional): Threshold levels (0-255, default: 0)
|
|
727
|
-
- `apply_to_active_layer` (boolean, optional): Bake into the active layer instead of a copy. Default `false`.
|
|
728
|
-
|
|
729
|
-
#### `photoshop_apply_noise`
|
|
730
|
-
|
|
731
|
-
Apply Add Noise filter to a duplicate of the active layer (default).
|
|
732
|
-
|
|
733
|
-
**Parameters:**
|
|
734
|
-
|
|
735
|
-
- `amount` (number, required): Noise amount in percent (0.1-400)
|
|
736
|
-
- `distribution` (string, optional): UNIFORM or GAUSSIAN (default: UNIFORM)
|
|
737
|
-
- `monochromatic` (boolean, optional): Monochromatic noise (default: false)
|
|
738
|
-
- `apply_to_active_layer` (boolean, optional): Bake into the active layer instead of a copy. Default `false`.
|
|
739
|
-
|
|
740
|
-
#### `photoshop_apply_motion_blur`
|
|
741
|
-
|
|
742
|
-
Apply Motion Blur filter to a duplicate of the active layer (default).
|
|
743
|
-
|
|
744
|
-
**Parameters:**
|
|
745
|
-
|
|
746
|
-
- `angle` (number, required): Blur angle in degrees (-360 to 360)
|
|
747
|
-
- `radius` (number, required): Blur distance in pixels (1-999)
|
|
748
|
-
- `apply_to_active_layer` (boolean, optional): Bake into the active layer instead of a copy. Default `false`.
|
|
749
|
-
|
|
750
|
-
#### `photoshop_apply_lens_blur`
|
|
751
|
-
|
|
752
|
-
Apply Lens Blur (photographically authentic depth-of-field) to a duplicate of the active layer (default). Use instead of Gaussian Blur when the goal is real DOF — portrait backgrounds, tilt-shift/miniature looks — with control over the iris shape, specular-highlight bokeh, and noise restoration. Auto-rasterizes text/smart-object layers.
|
|
753
|
-
|
|
754
|
-
**Parameters:**
|
|
755
|
-
|
|
756
|
-
- `radius` (number, optional): Blur radius in pixels 0-100 (default: 15) — the defining parameter
|
|
757
|
-
- `iris_shape` (string, optional): `triangle` / `square` / `pentagon` / `hexagon` (default) / `heptagon` / `octagon`
|
|
758
|
-
- `iris_blade_curvature` (number, optional): 0 = polygonal bokeh, 100 = circular (default: 0)
|
|
759
|
-
- `iris_rotation` (number, optional): Iris rotation in degrees 0-360 (default: 0)
|
|
760
|
-
- `specular_brightness` (number, optional): Highlight boost for bokeh balls 0-255 (default: 0)
|
|
761
|
-
- `specular_threshold` (number, optional): Threshold above which pixels count as speculars 0-255 (default: 255)
|
|
762
|
-
- `noise_amount` (number, optional): Noise restoration into the blurred region 0-100 (default: 0)
|
|
763
|
-
- `apply_to_active_layer` (boolean, optional): Bake into the active layer instead of a copy. Default `false`.
|
|
764
|
-
|
|
765
|
-
### Color Adjustments
|
|
766
|
-
|
|
767
|
-
#### `photoshop_add_adjustment_layer`
|
|
768
|
-
|
|
769
|
-
Create a non-destructive adjustment layer above the active layer. Supports the full Photoshop tonal/color surface: Curves, Levels, Hue/Saturation, Brightness/Contrast, **Black & White** (with optional tint), **Color Balance**, **Photo Filter** (preset or custom color), **Vibrance**, **Channel Mixer**, **Selective Color**, **Gradient Map** (preset), **Exposure** (stops + offset + gamma), **Color Lookup** (3DLUT presets or custom file path), and **Invert**. Optionally clips the adjustment to only affect the layer directly below it. If a selection is active at call time, the new layer is automatically masked by it (toggleable via `mask_from_selection` / `mask_inverted`). This is the canonical entry point for ALL tonal/color adjustments; the destructive bake tools (`photoshop_auto_levels` / `photoshop_auto_contrast` / `photoshop_desaturate` / `photoshop_invert`) were removed on 2026-05-31 — if you genuinely need a pixel bake, follow this call with `photoshop_merge_visible_layers`.
|
|
770
|
-
|
|
771
|
-
**Parameters:**
|
|
772
|
-
|
|
773
|
-
- `type` (string, required): One of `curves`, `levels`, `hue_saturation`, `brightness_contrast`, `black_and_white`, `color_balance`, `photo_filter`, `vibrance`, `channel_mixer`, `selective_color`, `gradient_map`, `exposure`, `color_lookup`, `invert`, `posterize`, `threshold`
|
|
774
|
-
- `clip_to_below` (boolean, optional): Restrict effect to the layer directly below (default: false)
|
|
775
|
-
- `name` (string, optional): Layer name
|
|
776
|
-
- **Curves:** `curves_preset` — `linear` / `sCurveLight` / `sCurveMedium` / `sCurveStrong`
|
|
777
|
-
- **Levels:** `black_point` / `white_point` / `gamma`
|
|
778
|
-
- **Hue/Saturation:** `hue` / `saturation` / `lightness`
|
|
779
|
-
- **Brightness/Contrast:** `brightness` / `contrast`
|
|
780
|
-
- **Black & White:** `bw_reds` / `bw_yellows` / `bw_greens` / `bw_cyans` / `bw_blues` / `bw_magentas` (each −200 to +300); optional `bw_tint` boolean + `bw_tint_hue` + `bw_tint_saturation` for split-toned B&W
|
|
781
|
-
- **Color Balance:** `cb_shadows_cyan_red` / `cb_shadows_magenta_green` / `cb_shadows_yellow_blue` + matching `cb_midtones_*` and `cb_highlights_*`; `cb_preserve_luminosity`
|
|
782
|
-
- **Photo Filter:** either `pf_preset` (e.g. `warming_85`, `cooling_80`, `sepia`, 17 more) or `pf_color_hex`; `pf_density` (1-100, default 25); `pf_preserve_luminosity`
|
|
783
|
-
- **Vibrance:** `vib_vibrance` / `vib_saturation`
|
|
784
|
-
- **Channel Mixer:** `cm_monochrome` flag; in mono mode `cm_gray_from_r/g/b` + `cm_gray_constant`; in RGB mode `cm_r_from_{r,g,b}` + `cm_r_constant` for each output channel
|
|
785
|
-
- **Selective Color:** `sc_method` (`relative` / `absolute`); `sc_colors` is a nested object — `{reds: {cyan, magenta, yellow, black}, blues: {...}, ...}` for any of the 9 color families
|
|
786
|
-
- **Gradient Map:** `gm_preset` (`black_to_white` / `sepia` / `tint`); when preset=tint, `gm_tint_color_hex`; `gm_reverse`; `gm_dither`. Custom gradient stops are not supported in v1 — record a Photoshop Action for arbitrary gradients
|
|
787
|
-
- **Exposure:** `exp_exposure` (stops, −20 to +20), `exp_offset` (−0.5 to +0.5), `exp_gamma` (0.01 to 9.99)
|
|
788
|
-
- **Color Lookup:** `cl_lut_name` (validated against `Presets/3DLUTs/` or absolute path); `cl_lut_type` (`3dlut` only). **Note:** the LUT is NOT loaded — PS scripting has no entry point for the .cube/.3DL/.look parser. The layer is created empty; the artist hand-picks the LUT in PS's Properties panel, or records a Photoshop Action that applies the desired LUT preset and invokes that via the actions surface. See [docs/20260603-color-lookup-limitation.md](docs/20260603-color-lookup-limitation.md) for the full investigation.
|
|
789
|
-
- **Invert:** no params — creating the layer IS the operation
|
|
790
|
-
- **Posterize:** `pos_levels` (2-255, default 4)
|
|
791
|
-
- **Threshold:** `thr_level` (1-255, default 128)
|
|
792
|
-
- `mask_from_selection` (boolean, optional, default `true`): If true and there is an active selection, the new layer gets a mask from it. If false, any existing selection is dropped first and the layer is unmasked (full canvas).
|
|
793
|
-
- `mask_inverted` (boolean, optional, default `false`): Only meaningful with `mask_from_selection: true` and an active selection. Inverts the resulting mask — useful for "I selected the sky but want to adjust everything else."
|
|
794
|
-
|
|
795
|
-
```javascript
|
|
796
|
-
photoshop_add_adjustment_layer({
|
|
797
|
-
type: 'curves',
|
|
798
|
-
curves_preset: 'sCurveMedium',
|
|
799
|
-
clip_to_below: true,
|
|
800
|
-
name: 'Contrast',
|
|
801
|
-
});
|
|
802
|
-
```
|
|
803
|
-
|
|
804
|
-
> **Removed 2026-05-31:** `photoshop_auto_levels` / `photoshop_auto_contrast` / `photoshop_desaturate` / `photoshop_invert` were redundancies with `photoshop_add_adjustment_layer` (non-destructive + editable + maskable) and saw zero LLM usage in six months of session logs. To bake, use `photoshop_add_adjustment_layer` followed by `photoshop_merge_visible_layers`. See [docs/20260531-tool-removals.md](docs/20260531-tool-removals.md).
|
|
805
|
-
|
|
806
|
-
#### `photoshop_apply_color_lookup`
|
|
807
|
-
|
|
808
|
-
Apply a 3DLUT preset as a destructive color grade, baked onto a duplicate of the active layer (the original is preserved). This is the **only** working LUT path — the non-destructive `add_adjustment_layer type=color_lookup` form can't load a LUT via scripting (see [docs/20260603-color-lookup-limitation.md](docs/20260603-color-lookup-limitation.md)). For an editable grade, compose `selective_color` + `color_balance` + `curves`.
|
|
809
|
-
|
|
810
|
-
**Parameters:**
|
|
811
|
-
|
|
812
|
-
- `cl_lut_name` (string, required): Leaf name of a LUT in PS's `Presets/3DLUTs/` folder (e.g. `FallColors.look`, `Kodak 5205 Fuji 3510 (by Adobe).cube`, `TealOrangePlusContrast.3DL`) or an absolute path to a `.cube` / `.3dl` / `.look` file. Extension-agnostic leaf matching.
|
|
813
|
-
- `apply_to_active_layer` (boolean, optional): Bake into the active layer instead of a copy. Default `false`.
|
|
814
|
-
|
|
815
|
-
### Text Formatting
|
|
816
|
-
|
|
817
|
-
#### `photoshop_set_text_font`
|
|
818
|
-
|
|
819
|
-
Set font family and size for active text layer.
|
|
820
|
-
|
|
821
|
-
**Parameters:**
|
|
822
|
-
|
|
823
|
-
- `font_name` (string, required): Font family name
|
|
824
|
-
- `font_size` (number, optional): Font size in points
|
|
825
|
-
|
|
826
|
-
#### `photoshop_set_text_color`
|
|
827
|
-
|
|
828
|
-
Set color for active text layer.
|
|
829
|
-
|
|
830
|
-
**Parameters:**
|
|
831
|
-
|
|
832
|
-
- `red`, `green`, `blue` (number, required): RGB components (0-255)
|
|
833
|
-
|
|
834
|
-
#### `photoshop_set_text_alignment`
|
|
835
|
-
|
|
836
|
-
Set text alignment.
|
|
837
|
-
|
|
838
|
-
**Parameters:**
|
|
839
|
-
|
|
840
|
-
- `alignment` (string, required): LEFT, CENTER, RIGHT, LEFTJUSTIFIED, CENTERJUSTIFIED, RIGHTJUSTIFIED, FULLYJUSTIFIED
|
|
841
|
-
|
|
842
|
-
#### `photoshop_update_text_content`
|
|
843
|
-
|
|
844
|
-
Update text content of active text layer.
|
|
845
|
-
|
|
846
|
-
**Parameters:**
|
|
847
|
-
|
|
848
|
-
- `text` (string, required): New text content
|
|
849
|
-
|
|
850
|
-
### Selections & Masks
|
|
851
|
-
|
|
852
|
-
**Common `selection_type` arg** on every selection-creating tool: `replace` (default) overwrites the current selection; `add` unions with it; `subtract` removes this region from it; `intersect` keeps the overlap.
|
|
853
|
-
|
|
854
|
-
**Common `selection_info` return** on every selection tool: a rich post-op stats bundle the agent uses to verify what got selected — bounds, coverage-weighted `pixel_count`, `area_percent`, `bounds_fill_ratio` (low = patchy selection), `edge_complexity` (high = soft/feathered edge), plus `fully_selected_pixels` / `partial_pixels` breakouts. Computed in ~150-300ms by routing the selection through a temp alpha channel histogram. Use these numbers before committing a mask; if they look off, call `photoshop_get_selection_preview` for a visual.
|
|
855
|
-
|
|
856
|
-
#### `photoshop_select_rectangle`
|
|
857
|
-
|
|
858
|
-
Create a rectangular selection. Optional `feather_px` softens the edge — essential for regional adjustments in smooth areas (open sky bands visibly without it).
|
|
859
|
-
|
|
860
|
-
**Parameters:**
|
|
861
|
-
|
|
862
|
-
- `left`, `top`, `right`, `bottom` (number, required): Selection bounds in pixels
|
|
863
|
-
- `feather_px` (number, optional): Soften the selection edge by this many pixels (default: 0). Typical values 40-180.
|
|
864
|
-
- `selection_type` (string, optional): `replace` (default), `add`, `subtract`, `intersect`.
|
|
865
|
-
|
|
866
|
-
#### `photoshop_select_subject`
|
|
867
|
-
|
|
868
|
-
**Smart selection** via Adobe Sensei's on-device subject-detection model. One-call selection of the main subject — person, animal, product, etc. ~2-5s typical. Killer for portrait masking. Combines via `selection_type`.
|
|
869
|
-
|
|
870
|
-
**Parameters:**
|
|
871
|
-
|
|
872
|
-
- `selection_type` (string, optional): default `replace`.
|
|
873
|
-
|
|
874
|
-
#### `photoshop_select_sky`
|
|
875
|
-
|
|
876
|
-
**Smart selection** via Adobe Sensei's sky detection. One-call sky masking for landscape work. On tricky horizons (foreground objects against sky), `selection_info.edge_complexity` will be high — verify with `photoshop_get_selection_preview` before committing.
|
|
877
|
-
|
|
878
|
-
**Parameters:**
|
|
879
|
-
|
|
880
|
-
- `selection_type` (string, optional): default `replace`.
|
|
881
|
-
|
|
882
|
-
#### `photoshop_magic_wand`
|
|
883
|
-
|
|
884
|
-
Click-point selection by color similarity. Equivalent to the Magic Wand tool — clicks at (x, y) and selects all pixels within `tolerance` of that color. Often needs 2-3 iterations adjusting tolerance; use the returned `selection_info` (and `photoshop_get_selection_preview` if needed) to gauge whether to widen or narrow.
|
|
885
|
-
|
|
886
|
-
**Parameters:**
|
|
887
|
-
|
|
888
|
-
- `x`, `y` (integer, required): Click coords in document pixel space.
|
|
889
|
-
- `tolerance` (integer 0-255, optional, default 32): Color similarity threshold.
|
|
890
|
-
- `contiguous` (boolean, optional, default true): Restrict to connected matching pixels.
|
|
891
|
-
- `anti_alias` (boolean, optional, default true): Soften the edge.
|
|
892
|
-
- `sample_all_layers` (boolean, optional, default false): Sample color across all visible layers.
|
|
893
|
-
- `selection_type` (string, optional): default `replace`.
|
|
894
|
-
|
|
895
|
-
#### `photoshop_select_color_range`
|
|
896
|
-
|
|
897
|
-
Select all pixels matching a target RGB color within a fuzziness threshold. Equivalent to Select > Color Range. Use for "select all the red," "select skin tones," etc. Combine multiple calls with `selection_type: 'add'` to capture related color ranges.
|
|
898
|
-
|
|
899
|
-
**Parameters:**
|
|
900
|
-
|
|
901
|
-
- `red`, `green`, `blue` (integer 0-255, required): Target color.
|
|
902
|
-
- `fuzziness` (integer 0-200, optional, default 40): Tolerance — higher selects a wider color range.
|
|
903
|
-
- `selection_type` (string, optional): default `replace`.
|
|
904
|
-
|
|
905
|
-
#### `photoshop_get_selection_info`
|
|
906
|
-
|
|
907
|
-
Read the current selection state without modifying anything. Returns the same `selection_info` bundle (bounds, coverage-weighted `pixel_count`, `area_percent`, `bounds_fill_ratio`, `edge_complexity`, etc.) that selection-creating tools embed in their return. Use this as a **pre-flight check** when you start a workflow and aren't sure whether a selection is already active — a previous tool may have failed mid-way and left a stale selection that would corrupt a downstream mask. Cheap (~200ms). For a visual instead of stats, use `photoshop_get_selection_preview`.
|
|
908
|
-
|
|
909
|
-
#### `photoshop_get_selection_preview`
|
|
910
|
-
|
|
911
|
-
Render TWO inline JPEGs so the agent can visually verify what's currently selected: (1) an **overlay** of the document with a 50% red wash over the selected area (Quick Mask-style — most intuitive), and (2) a **B/W mask** where black = selected. Heavier than reading `selection_info` (~2-4s) — reach for it when the stats look off or before committing a layer mask. Does NOT modify the source document.
|
|
912
|
-
|
|
913
|
-
**Parameters:**
|
|
914
|
-
|
|
915
|
-
- `max_dimension` (integer 128-4096, optional, default 800): Long-edge pixel cap for both returned images.
|
|
916
|
-
|
|
917
|
-
#### `photoshop_feather_selection`
|
|
918
|
-
|
|
919
|
-
Feather (soften) the current selection by a pixel radius. Use this when a selection was created without a feather (e.g. `select_all`, `invert_selection`, `select_subject`) or when an existing selection needs further softening before applying an adjustment. Throws if no active selection. After feathering, `selection_info.edge_complexity` rises noticeably.
|
|
920
|
-
|
|
921
|
-
**Parameters:**
|
|
922
|
-
|
|
923
|
-
- `radius_px` (number, required): Feather radius in pixels (> 0)
|
|
924
|
-
|
|
925
|
-
#### `photoshop_select_all`
|
|
926
|
-
|
|
927
|
-
Select the entire document canvas. Returns `selection_info` with `area_percent: 100`.
|
|
928
|
-
|
|
929
|
-
#### `photoshop_deselect`
|
|
930
|
-
|
|
931
|
-
Clear the active selection. Returns `selection_info` with `has_selection: false`.
|
|
932
|
-
|
|
933
|
-
#### `photoshop_invert_selection`
|
|
934
|
-
|
|
935
|
-
Invert the current selection. NOT idempotent.
|
|
936
|
-
|
|
937
|
-
#### `photoshop_delete_layer_mask`
|
|
938
|
-
|
|
939
|
-
Delete the layer mask from the active layer. The underlying layer pixels are NOT lost.
|
|
940
|
-
|
|
941
|
-
#### `photoshop_apply_layer_mask`
|
|
942
|
-
|
|
943
|
-
**DESTRUCTIVE (bakes into pixels):** Permanently apply the layer mask to the layer pixels (Apply Mask). Pixels outside the mask are lost and the mask is removed.
|
|
944
|
-
|
|
945
|
-
#### `photoshop_save_selection_to_channel`
|
|
946
|
-
|
|
947
|
-
Save the current active selection to a named alpha channel. If a channel with that name already exists it is overwritten in place (returns `overwritten: true`); otherwise a new channel is created. Use to checkpoint complex or expensive selections so they can be recalled later — particularly useful before a multi-step refinement loop where you want to restore the base selection if the refinement overshoots.
|
|
948
|
-
|
|
949
|
-
**Parameters:**
|
|
950
|
-
|
|
951
|
-
- `channel_name` (string, required): Name for the alpha channel to save into (creates it if it doesn't exist, overwrites if it does)
|
|
952
|
-
|
|
953
|
-
**Returns:** `saved`, `channel_name`, `overwritten`, `channel_count` (total channels in document after save), `selection_info`
|
|
954
|
-
|
|
955
|
-
#### `photoshop_load_selection_from_channel`
|
|
956
|
-
|
|
957
|
-
Load a previously saved alpha channel back as an active selection. Supports all four boolean combination modes (`replace`, `add`, `subtract`, `intersect`) so you can compose multi-channel masks without losing the current selection. Use after `photoshop_save_selection_to_channel` to restore a checkpoint, or combine two saved channels by loading each in turn with `add`/`subtract`.
|
|
958
|
-
|
|
959
|
-
**Parameters:**
|
|
960
|
-
|
|
961
|
-
- `channel_name` (string, required): Name of the alpha channel to load
|
|
962
|
-
- `operation` (string, optional): `replace` (default), `add`, `subtract`, or `intersect` — how the loaded selection combines with any existing active selection
|
|
963
|
-
|
|
964
|
-
**Returns:** `loaded`, `channel_name`, `operation`, `selection_info`
|
|
965
|
-
|
|
966
|
-
### History & Undo/Redo
|
|
967
|
-
|
|
968
|
-
#### `photoshop_undo`
|
|
969
|
-
|
|
970
|
-
Undo the last operation(s) - equivalent to Ctrl/Cmd+Z.
|
|
971
|
-
|
|
972
|
-
**Parameters:**
|
|
973
|
-
|
|
974
|
-
- `steps` (number, optional): Number of steps to undo (default: 1)
|
|
975
|
-
|
|
976
|
-
#### `photoshop_redo`
|
|
977
|
-
|
|
978
|
-
Redo previously undone operation(s) - equivalent to Ctrl/Cmd+Shift+Z.
|
|
979
|
-
|
|
980
|
-
**Parameters:**
|
|
981
|
-
|
|
982
|
-
- `steps` (number, optional): Number of steps to redo (default: 1)
|
|
983
|
-
|
|
984
|
-
#### `photoshop_get_history`
|
|
985
|
-
|
|
986
|
-
Get the history states of the active document.
|
|
987
|
-
|
|
988
|
-
### Actions & Automation
|
|
989
|
-
|
|
990
|
-
#### `photoshop_list_actions`
|
|
991
|
-
|
|
992
|
-
Enumerate the Photoshop Actions palette. Returns every Action Set and the actions inside it. Read-only and cheap. Call this BEFORE `photoshop_play_action` so you know which `action_name` + `action_set_name` combinations actually exist — `play_action` throws on unknown names and has no other way to enumerate them.
|
|
993
|
-
|
|
994
|
-
```javascript
|
|
995
|
-
photoshop_list_actions();
|
|
996
|
-
// → { count: 2, sets: [{ name: "Default Actions", actions: ["Vignette", "Sepia"] }, ...] }
|
|
997
|
-
```
|
|
998
|
-
|
|
999
|
-
#### `photoshop_play_action`
|
|
1000
|
-
|
|
1001
|
-
Play a recorded action from the Actions palette. Call `photoshop_list_actions` first to discover valid names.
|
|
1002
|
-
|
|
1003
|
-
**Parameters:**
|
|
1004
|
-
|
|
1005
|
-
- `action_name` (string, required): Action name
|
|
1006
|
-
- `action_set_name` (string, required): Action set name
|
|
1007
|
-
|
|
1008
|
-
#### `photoshop_execute_script` _(Pro)_
|
|
1009
|
-
|
|
1010
|
-
Execute custom ExtendScript code (advanced). **Pro tier as of 2026-05-31** — see [docs/20260531-tool-removals.md](docs/20260531-tool-removals.md) for the rationale. CE callers fall back to `photoshop_play_action` for any user-recorded workflow that covers the same operation.
|
|
1011
|
-
|
|
1012
|
-
**Parameters:**
|
|
1013
|
-
|
|
1014
|
-
- `code` (string, required): ExtendScript code
|
|
1015
|
-
|
|
1016
|
-
### Image Manipulation
|
|
1017
|
-
|
|
1018
|
-
#### `photoshop_resize_image`
|
|
1019
|
-
|
|
1020
|
-
Resize the active image.
|
|
1021
|
-
|
|
1022
|
-
**Parameters:**
|
|
1023
|
-
|
|
1024
|
-
- `width` (number, required): New width in pixels
|
|
1025
|
-
- `height` (number, required): New height in pixels
|
|
1026
|
-
|
|
1027
|
-
#### `photoshop_crop_document`
|
|
1028
|
-
|
|
1029
|
-
Crop the document to specified bounds.
|
|
1030
|
-
|
|
1031
|
-
**Parameters:**
|
|
1032
|
-
|
|
1033
|
-
- `left`, `top`, `right`, `bottom` (number, required): Crop bounds in pixels
|
|
1034
|
-
|
|
1035
|
-
#### `photoshop_place_image`
|
|
1036
|
-
|
|
1037
|
-
Place an image file as a layer in the active document.
|
|
1038
|
-
|
|
1039
|
-
**Parameters:**
|
|
1040
|
-
|
|
1041
|
-
- `file_path` (string, required): Full path to the image file
|
|
1042
|
-
- `x` (number, optional): X position offset in pixels (default: 0)
|
|
1043
|
-
- `y` (number, optional): Y position offset in pixels (default: 0)
|
|
1044
|
-
|
|
1045
|
-
### Preview & Verification
|
|
1046
|
-
|
|
1047
|
-
#### `photoshop_get_preview`
|
|
1048
|
-
|
|
1049
|
-
Render the active Photoshop document as a flattened, downscaled image and return it inline so the AI can see the current visual state. Read-only with respect to the working document (renders a duplicate that's closed immediately). The optional `annotations` array draws document-space overlays in two families: **spatial verification** (rectangles, guides, points, current-selection markers — Bundle Q, 2026-06-02) and **coordinate / compositional overlays** (regular grids, rule-of-thirds, golden-ratio guides, golden spiral, diagonals, triangles — 2026-06-09). Use spatial overlays to verify placement ("did the layer land inside the frame?"); use grids when you need to translate a visual judgment ("subject is in the lower-left third") into pixel coordinates for a downstream tool call; use composition overlays to evaluate balance, leading lines, and focal-point placement against canonical photographic frameworks.
|
|
1050
|
-
|
|
1051
|
-
**Parameters:**
|
|
1052
|
-
|
|
1053
|
-
- `max_dimension` (integer, optional): Cap on the long edge in pixels, 64-8192 (default: 1024)
|
|
1054
|
-
- `format` (string, optional): `jpeg` (smaller) or `png` (preserves transparency, lossless). Default: `jpeg`
|
|
1055
|
-
- `quality` (integer, optional): JPEG quality 1-12. Ignored for PNG. Default: 6
|
|
1056
|
-
- `annotations` (array, optional): List of annotations to draw onto the preview. Each is one of:
|
|
1057
|
-
- `{ type: "rectangle", left, top, right, bottom, color, label, stroke_width }` — wireframe rectangle at explicit bounds
|
|
1058
|
-
- `{ type: "rectangle", layer: "<name>", color, label }` — wireframe around a layer's bounds (tool reads them via the layer tree)
|
|
1059
|
-
- `{ type: "guide", orientation: "horizontal"|"vertical", pixel, canvas_pct, color, label }` — reference line
|
|
1060
|
-
- `{ type: "point", x, y, marker: "cross"|"dot"|"crosshair", color, label }` — point marker
|
|
1061
|
-
- `{ type: "selection", color, label }` — outline the current active selection
|
|
1062
|
-
- `{ type: "grid", style: "every"|"thirds"|"quarters"|"phi", spacing_px, color, label }` — regular grid for coordinate readout. `every` uses `spacing_px` (default 50); `thirds` draws 2 horizontal + 2 vertical lines at the 1/3 / 2/3 marks; `quarters` is a center crosshair; `phi` is the golden-ratio analog of thirds at 0.382 / 0.618.
|
|
1063
|
-
- `{ type: "composition", style: "diagonals"|"triangles"|"fibonacci_grid"|"golden_spiral", orientation_corner: "tl"|"tr"|"bl"|"br", color, label }` — compositional guides. `diagonals` draws a corner-to-corner X; `triangles` is the diagonal plus perpendiculars from the opposite corners (the "golden triangles" composition); `fibonacci_grid` draws nested golden-ratio rectangles from the named corner; `golden_spiral` is `fibonacci_grid` plus the iconic spiral curve through it. Default corner `tl`.
|
|
1064
|
-
- `color` accepts named (`red`, `blue`, `green`, `yellow`, `magenta`, `cyan`, `orange`, `white`, `black`) or hex (`#RRGGBB`). Default `red`. Default stroke width 4 px.
|
|
1065
|
-
|
|
1066
|
-
```javascript
|
|
1067
|
-
photoshop_get_preview({
|
|
1068
|
-
max_dimension: 1500,
|
|
1069
|
-
annotations: [
|
|
1070
|
-
{
|
|
1071
|
-
type: 'rectangle',
|
|
1072
|
-
left: 1060,
|
|
1073
|
-
top: 820,
|
|
1074
|
-
right: 3890,
|
|
1075
|
-
bottom: 2690,
|
|
1076
|
-
color: 'red',
|
|
1077
|
-
label: 'target',
|
|
1078
|
-
},
|
|
1079
|
-
{ type: 'rectangle', layer: 'Sunset', color: 'blue', label: 'actual' },
|
|
1080
|
-
],
|
|
1081
|
-
});
|
|
1082
|
-
```
|
|
1083
|
-
|
|
1084
|
-
#### `photoshop_get_layer_bounds_diff`
|
|
1085
|
-
|
|
1086
|
-
Numeric verification: compute the per-edge pixel deltas between a layer's actual bounds and a target rectangle. Returns deltas (actual − target), scale ratio, centroid offset, and a one-word verdict (`aligned`, `shifted right`, `layer too small`, etc.). Use after `place_image` / `scale_layer` / `move_layer` to confirm intended placement — far more reliable than eyeballing a preview for fine alignment.
|
|
1087
|
-
|
|
1088
|
-
**Parameters:**
|
|
1089
|
-
|
|
1090
|
-
- `layer` (string, required): Layer name (searched recursively through groups)
|
|
1091
|
-
- `target_left`, `target_top`, `target_right`, `target_bottom` (number, required): Target rectangle in document pixels
|
|
1092
|
-
- `tolerance_px` (number, optional, default 10): Tolerance for the "aligned" verdict
|
|
1093
|
-
|
|
1094
|
-
#### `photoshop_compare_regions`
|
|
1095
|
-
|
|
1096
|
-
Quantitative region comparison: capture the histogram of two rectangular regions on the same document and report per-channel mean / stdev / median for each, plus differences between them. Use to verify color or tonal claims about specific areas ("is the sky region noticeably bluer than the foreground?"). Single-pixel sampling supported (1×1 rect).
|
|
1097
|
-
|
|
1098
|
-
**Parameters:**
|
|
1099
|
-
|
|
1100
|
-
- `region_a_left`, `region_a_top`, `region_a_right`, `region_a_bottom` (number, required): Region A bounds
|
|
1101
|
-
- `region_b_left`, `region_b_top`, `region_b_right`, `region_b_bottom` (number, required): Region B bounds
|
|
1102
|
-
- `label_a`, `label_b` (string, optional): Labels for the regions in the response
|
|
1103
|
-
|
|
1104
|
-
#### `photoshop_get_histogram`
|
|
1105
|
-
|
|
1106
|
-
Read the histogram of the active document for a given channel. Returns 256 bin counts plus `mean`, `stdev`, and `median`. Cheap (~50ms) and read-only. **Use as a verification primitive**: capture a histogram before and after a destructive op to confirm pixels actually changed. If two histograms are identical, the op was a no-op — don't trust a tool's success message alone. Composite reads the visible flattened image (works in any color mode); per-channel reads work only on documents that have that channel.
|
|
1107
|
-
|
|
1108
|
-
**Parameters:**
|
|
1109
|
-
|
|
1110
|
-
- `channel` (string, optional): `composite` (default), `red`, `green`, `blue`, `luminosity`, or `gray`
|
|
1111
|
-
|
|
1112
|
-
### Templates _(Pro)_
|
|
1113
|
-
|
|
1114
|
-
> **The entire template surface is Pro** (as of 2026-06-16). Authoring (`create_evidence` / `save` / `delete`) and use (`list` / `apply` / `verify` / `recall`) are all Pro-tier — templates are the reproducible-recipe / learning-loop layer and ship as one paid feature.
|
|
1115
|
-
|
|
1116
|
-
The template system lets the photographer freeze a finished edit as a reproducible recipe. After Claude finishes editing a photo to satisfaction, ask it to create a template; the next time you want the same look on a different photo, ask Claude to apply that template by name. Templates live as plain markdown files at `~/.editmamei/templates/<slug>/template.md` alongside before/after thumbnails — you can hand-edit them in any text editor.
|
|
1117
|
-
|
|
1118
|
-
The synthesis is a two-step flow. Step 1 (`photoshop_template_create_evidence`) gathers everything Claude needs: every tool call made in the current session, every Photoshop history state, full image metadata, and rendered before/after thumbnails. Step 2 (`photoshop_template_save`) accepts the markdown Claude authored and writes the bundle to disk.
|
|
1119
|
-
|
|
1120
|
-
#### `photoshop_template_create_evidence`
|
|
1121
|
-
|
|
1122
|
-
Step 1 of 2: gather the three evidence layers needed to author a template — session tool calls (from the Phase 2 telemetry log), Photoshop history states, and full metadata snapshot. Renders before.jpg (history[0]) and after.jpg (current state) inline. Read-only.
|
|
1123
|
-
|
|
1124
|
-
**Parameters:**
|
|
1125
|
-
|
|
1126
|
-
- `name` (string, required): Human-readable template name (sanitized to a filesystem-safe slug for storage)
|
|
1127
|
-
|
|
1128
|
-
```javascript
|
|
1129
|
-
photoshop_template_create_evidence({ name: 'Warm Portrait' });
|
|
1130
|
-
// Then draft the template.md content based on the returned evidence,
|
|
1131
|
-
// then call photoshop_template_save.
|
|
1132
|
-
```
|
|
1133
|
-
|
|
1134
|
-
#### `photoshop_template_save`
|
|
1135
|
-
|
|
1136
|
-
Step 2 of 2: write Claude's authored markdown + freshly re-rendered before/after JPEGs + evidence.json bundle to `~/.editmamei/templates/<slug>/`. Re-renders previews at save time so the saved bundle always matches the current document state.
|
|
1137
|
-
|
|
1138
|
-
**Parameters:**
|
|
1139
|
-
|
|
1140
|
-
- `name` (string, required): Template name (will be slug-sanitized)
|
|
1141
|
-
- `md_content` (string, required): Full template.md body with YAML frontmatter
|
|
1142
|
-
- `overwrite` (boolean, optional): Replace an existing template (default: false; errors on collision)
|
|
1143
|
-
|
|
1144
|
-
#### `photoshop_template_list`
|
|
1145
|
-
|
|
1146
|
-
List all saved templates with parsed frontmatter descriptors (slug, display name, intent, created date, source camera, tags). Read-only. Sorted newest first.
|
|
1147
|
-
|
|
1148
|
-
```javascript
|
|
1149
|
-
photoshop_template_list();
|
|
1150
|
-
```
|
|
1151
|
-
|
|
1152
|
-
#### `photoshop_template_apply`
|
|
1153
|
-
|
|
1154
|
-
Load a template by name and return its markdown + before/after thumbnails as inline content. Does NOT directly edit the active document — Claude reads the template as guidance and drives the existing `photoshop_*` pipeline tools to match the look, using `photoshop_get_preview` to self-judge against the template's exit criteria.
|
|
1155
|
-
|
|
1156
|
-
The response orders **text first** so the markdown instructions reach the agent even if MCP truncates the trailing payload. Thumbnails are inlined when their combined base64 size fits under the MCP 1 MB response cap; oversized bundles degrade gracefully to text-only and flag `images_included:false` in `structuredContent`.
|
|
1157
|
-
|
|
1158
|
-
**Parameters:**
|
|
1159
|
-
|
|
1160
|
-
- `name` (string, required): Template slug (use `photoshop_template_list` to discover)
|
|
1161
|
-
|
|
1162
|
-
```javascript
|
|
1163
|
-
photoshop_template_apply({ name: 'warm-portrait' });
|
|
1164
|
-
```
|
|
1165
|
-
|
|
1166
|
-
#### `photoshop_template_verify`
|
|
1167
|
-
|
|
1168
|
-
Evaluate the active document against a template's **signature** — machine-checkable style assertions (`signature.json`) authored at save time via `photoshop_template_save`'s `signature_content` arg. Returns per-predicate `pass | fail | skipped` with measured-vs-target detail and a one-line corrective steer per failure, turning "matches the look" into a measurement. Predicates are relative/scale-invariant (channel orderings, clipping ceilings, tonal points, subject-vs-background relations) so they transfer across photos.
|
|
1169
|
-
|
|
1170
|
-
Regions resolve relationally (Select Subject / Select Sky + inversion); when those are unavailable the affected predicates report `skipped`, never `failed`. Measurement transiently changes the document's selection state and ends deselected — pixels are never modified. Templates without a signature return an explanatory error.
|
|
1171
|
-
|
|
1172
|
-
**Parameters:**
|
|
1173
|
-
|
|
1174
|
-
- `name` (string, required): Template slug (use `photoshop_template_list` to discover)
|
|
1175
|
-
|
|
1176
|
-
```javascript
|
|
1177
|
-
photoshop_template_verify({ name: 'warm-portrait' });
|
|
1178
|
-
```
|
|
1179
|
-
|
|
1180
|
-
#### `photoshop_template_recall`
|
|
1181
|
-
|
|
1182
|
-
Re-surface one section of a template as **text only** — no images, no full recipe. Built for long edit sessions where the template body is tens of thousands of tokens back in context: recall the binding tier cheaply instead of re-running `photoshop_template_apply`. Read-only, filesystem-only.
|
|
1183
|
-
|
|
1184
|
-
**Parameters:**
|
|
1185
|
-
|
|
1186
|
-
- `name` (string, required): Template slug
|
|
1187
|
-
- `section` (string, optional, default `exit_criteria`): One of `exit_criteria`, `tune`, `fixed`, `intent`, `signature`
|
|
1188
|
-
|
|
1189
|
-
```javascript
|
|
1190
|
-
photoshop_template_recall({ name: 'warm-portrait' }); // exit criteria
|
|
1191
|
-
photoshop_template_recall({ name: 'warm-portrait', section: 'tune' });
|
|
1192
|
-
```
|
|
1193
|
-
|
|
1194
|
-
#### `photoshop_template_delete`
|
|
1195
|
-
|
|
1196
|
-
Delete a template by name. Destructive and irreversible. Pass `confirm: true` to acknowledge.
|
|
1197
|
-
|
|
1198
|
-
**Parameters:**
|
|
1199
|
-
|
|
1200
|
-
- `name` (string, required): Template slug
|
|
1201
|
-
- `confirm` (boolean, required): Must be true
|
|
1202
|
-
|
|
1203
|
-
## Context Tracking
|
|
1204
|
-
|
|
1205
|
-
Each tool returns comprehensive context information about the current state of Photoshop, including:
|
|
1206
|
-
|
|
1207
|
-
- **Document Info**: Name, dimensions, resolution, color mode, layer count
|
|
1208
|
-
- **Active Layer Info**: Name, type, opacity, blend mode, visibility, lock state
|
|
1209
|
-
- **Selection State**: Whether a selection is active
|
|
1210
|
-
- **Operation Result**: Specific details about what was changed
|
|
1211
|
-
|
|
1212
|
-
This allows AI assistants to maintain awareness of:
|
|
1213
|
-
|
|
1214
|
-
- Which document is active
|
|
1215
|
-
- Which layer is being worked on
|
|
1216
|
-
- Current layer properties (opacity, blend mode, etc.)
|
|
1217
|
-
- Document dimensions and settings
|
|
1218
|
-
|
|
1219
|
-
**Example Response:**
|
|
1220
|
-
|
|
1221
|
-
```javascript
|
|
1222
|
-
{
|
|
1223
|
-
"applied": true,
|
|
1224
|
-
"filter": "Gaussian Blur",
|
|
1225
|
-
"radius": 10,
|
|
1226
|
-
"wasRasterized": true,
|
|
1227
|
-
"context": {
|
|
1228
|
-
"hasDocument": true,
|
|
1229
|
-
"document": {
|
|
1230
|
-
"name": "design.psd",
|
|
1231
|
-
"width": 1920,
|
|
1232
|
-
"height": 1080,
|
|
1233
|
-
"resolution": 72,
|
|
1234
|
-
"colorMode": "RGBColorMode",
|
|
1235
|
-
"layerCount": 3,
|
|
1236
|
-
"hasSelection": false
|
|
1237
|
-
},
|
|
1238
|
-
"activeLayer": {
|
|
1239
|
-
"name": "Background",
|
|
1240
|
-
"kind": "NORMAL",
|
|
1241
|
-
"opacity": 100,
|
|
1242
|
-
"blendMode": "NORMAL",
|
|
1243
|
-
"visible": true,
|
|
1244
|
-
"locked": false,
|
|
1245
|
-
"isBackground": false
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
```
|
|
1250
|
-
|
|
1251
|
-
## Platform-Specific Notes
|
|
1252
|
-
|
|
1253
|
-
### Windows
|
|
1254
|
-
|
|
1255
|
-
- Uses COM automation to communicate with Photoshop
|
|
1256
|
-
- Registry-based auto-detection for installation paths
|
|
1257
|
-
- Supports both 32-bit and 64-bit versions
|
|
1258
|
-
|
|
1259
|
-
### macOS
|
|
1260
|
-
|
|
1261
|
-
- Uses AppleScript/OSA for Photoshop communication
|
|
1262
|
-
- Spotlight-based auto-detection
|
|
1263
|
-
- Supports multiple Photoshop versions installed simultaneously
|
|
1264
|
-
|
|
1265
|
-
## Supported Photoshop Versions
|
|
1266
|
-
|
|
1267
|
-
- **Tested on Photoshop 2026 (internal version 27.x).** This is the only version Editmamei has been verified against; ScriptListener captures pinning ActionManager descriptor specs come from PS 27.x sessions on both Windows and macOS.
|
|
1268
|
-
- **Earlier versions are unverified.** Editmamei may run on Photoshop 2025 / 2024 / 2023 / 2022 — the DOM-level APIs and many AM events are stable across recent majors — but Adobe rotates event IDs between major versions, and silent-no-op descriptor failures on untested PS versions cannot be ruled out. The auto-detector still probes older install paths so power users can try; failing tools on those versions are a known unsupported-version risk, not a bug.
|
|
1269
|
-
- **PS 27.x bug roster.** Several PS 27.x descriptor regressions are worked around in current builds — see [docs/20260530-ps27-cross-platform-bug-analysis.md](docs/20260530-ps27-cross-platform-bug-analysis.md) for the roster and which are fixed vs deferred.
|
|
1270
|
-
- ExtendScript API via AppleScript (macOS) or COM (Windows). ExtendScript is the only path that works for external automation — UXP cannot be invoked from outside Photoshop (see CLAUDE.md "Why ExtendScript only").
|
|
1271
|
-
|
|
1272
|
-
## Troubleshooting
|
|
1273
|
-
|
|
1274
|
-
### "Photoshop not found"
|
|
1275
|
-
|
|
1276
|
-
1. Make sure Photoshop is installed in the default location
|
|
1277
|
-
2. Or set `PHOTOSHOP_PATH` environment variable to custom installation path
|
|
1278
|
-
|
|
1279
|
-
```json
|
|
1280
|
-
{
|
|
1281
|
-
"env": {
|
|
1282
|
-
"PHOTOSHOP_PATH": "C:\\Custom\\Path\\Adobe Photoshop 2026\\Photoshop.exe"
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
```
|
|
1286
|
-
|
|
1287
|
-
### "Failed to connect to Photoshop"
|
|
1288
|
-
|
|
1289
|
-
1. Ensure Photoshop is running (the server will try to launch it if not)
|
|
1290
|
-
2. Check that scripting is enabled in Photoshop preferences
|
|
1291
|
-
3. On Windows, verify COM automation is not blocked by security settings
|
|
1292
|
-
|
|
1293
|
-
### "Script execution timeout"
|
|
1294
|
-
|
|
1295
|
-
- Some operations may take longer on large documents
|
|
1296
|
-
- The default timeout is 30 seconds
|
|
1297
|
-
- For complex operations, consider breaking them into smaller steps
|
|
1298
|
-
|
|
1299
|
-
### Debug Logging
|
|
1300
|
-
|
|
1301
|
-
Enable detailed logging by setting `LOG_LEVEL=0`:
|
|
1302
|
-
|
|
1303
|
-
```json
|
|
1304
|
-
{
|
|
1305
|
-
"env": {
|
|
1306
|
-
"LOG_LEVEL": "0"
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
```
|
|
1310
|
-
|
|
1311
|
-
## Development
|
|
1312
|
-
|
|
1313
|
-
### Build
|
|
1314
|
-
|
|
1315
|
-
```bash
|
|
1316
|
-
npm run build
|
|
1317
|
-
```
|
|
1318
|
-
|
|
1319
|
-
### Watch Mode
|
|
1320
|
-
|
|
1321
|
-
```bash
|
|
1322
|
-
npm run dev
|
|
1323
|
-
```
|
|
1324
|
-
|
|
1325
|
-
### Lint & Format
|
|
1326
|
-
|
|
1327
|
-
```bash
|
|
1328
|
-
npm run lint
|
|
1329
|
-
npm run format
|
|
1330
|
-
```
|
|
1331
|
-
|
|
1332
|
-
## Architecture
|
|
1333
|
-
|
|
1334
|
-
```
|
|
1335
|
-
Editmamei/
|
|
1336
|
-
├── src/
|
|
1337
|
-
│ ├── core/ # MCP server core
|
|
1338
|
-
│ │ ├── server.ts # Main MCP server (EditmameiServer)
|
|
1339
|
-
│ │ ├── session.ts # Session management
|
|
1340
|
-
│ │ └── tool-registry.ts # Tool registration system
|
|
1341
|
-
│ ├── platform/ # Platform-specific detection & execution
|
|
1342
|
-
│ │ ├── detector.ts # Main detector
|
|
1343
|
-
│ │ ├── connection.ts # Connection manager
|
|
1344
|
-
│ │ ├── script-executor.ts # Cross-platform script execution
|
|
1345
|
-
│ │ ├── windows-detector.ts # Windows registry detection
|
|
1346
|
-
│ │ ├── windows-executor.ts # Windows COM automation
|
|
1347
|
-
│ │ ├── macos-detector.ts # macOS Spotlight detection
|
|
1348
|
-
│ │ └── macos-executor.ts # macOS AppleScript execution
|
|
1349
|
-
│ ├── api/ # Photoshop API abstractions
|
|
1350
|
-
│ │ ├── photoshop-api.ts # API factory
|
|
1351
|
-
│ │ ├── batch-play.ts # UXP batchPlay helpers (legacy)
|
|
1352
|
-
│ │ └── extendscript.ts # ExtendScript snippets library
|
|
1353
|
-
│ ├── tools/ # MCP tool implementations (50+ tools)
|
|
1354
|
-
│ │ ├── document-tools.ts
|
|
1355
|
-
│ │ ├── layer-tools.ts
|
|
1356
|
-
│ │ ├── layer-properties-tools.ts
|
|
1357
|
-
│ │ ├── layer-transform-tools.ts
|
|
1358
|
-
│ │ ├── layer-ordering-tools.ts
|
|
1359
|
-
│ │ ├── image-tools.ts
|
|
1360
|
-
│ │ ├── image-placement-tools.ts
|
|
1361
|
-
│ │ ├── filter-tools.ts
|
|
1362
|
-
│ │ ├── adjustment-tools.ts
|
|
1363
|
-
│ │ ├── text-tools.ts
|
|
1364
|
-
│ │ ├── selection-tools.ts
|
|
1365
|
-
│ │ ├── history-tools.ts
|
|
1366
|
-
│ │ ├── action-tools.ts
|
|
1367
|
-
│ │ └── preview-tools.ts
|
|
1368
|
-
│ ├── utils/ # Utilities
|
|
1369
|
-
│ │ └── logger.ts # Logging system (stderr-based)
|
|
1370
|
-
│ └── index.ts # Entry point
|
|
1371
|
-
├── examples/ # Configuration examples
|
|
1372
|
-
│ ├── cursor-config.json
|
|
1373
|
-
│ └── claude-desktop-config.json
|
|
1374
|
-
├── LICENSE # Proprietary license
|
|
1375
|
-
├── NOTICES.md # Third-party attributions (MIT upstream + deps)
|
|
1376
|
-
└── server.json # MCP registry metadata
|
|
1377
|
-
```
|
|
43
|
+
- **Features and pricing:** [editmamei.com](https://editmamei.com)
|
|
44
|
+
- **Install, getting started, FAQ, Pro features:** [the wiki](https://github.com/editmamei/editmamei-wiki)
|
|
45
|
+
- **Bugs and feature requests:** [the issue tracker](https://github.com/editmamei/editmamei-wiki/issues)
|
|
46
|
+
- **Security:** see [editmamei.com/security](https://editmamei.com/security) (don't file security issues publicly)
|
|
1378
47
|
|
|
1379
48
|
## License
|
|
1380
49
|
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
Editmamei incorporates code originally licensed under the MIT License. Required attributions are provided in [NOTICES.md](./NOTICES.md).
|
|
1384
|
-
|
|
1385
|
-
## Acknowledgments
|
|
1386
|
-
|
|
1387
|
-
Editmamei is a derivative work originally based on [photoshop-mcp](https://github.com/alisaitteke/photoshop-mcp) by Ali Sait Teke, released under the MIT License. Significant portions have been rewritten, extended, or replaced.
|
|
50
|
+
Proprietary, free to install and use. See [the license](https://editmamei.com/license). Third-party dependencies keep their own licenses, listed in the bundled `NOTICES.md`.
|
|
1388
51
|
|
|
1389
|
-
|
|
52
|
+
---
|
|
1390
53
|
|
|
1391
|
-
|
|
54
|
+
_Pairs well with: a layered PSD, a willing AI, and a small bowl of edamame._
|