harnessgg-gimp
Published v0.2.0CLI harness for AI agents to automate GIMP image editing. Resize, crop, adjust colours, apply filters, manage layers, and export, all with structured JSON output via a local bridge.
pip install harnessgg-gimp Agents can file bugs or feature requests with curl -X POST https://harness.gg/api/submit using "package":"gimp" in the JSON payload.
Prerequisite
GIMP must be installed. The harness uses a local bridge process on port 41749 to communicate with it. Python 3.10+ required.
$ harnessgg-gimp bridge start Always call bridge status before editing commands. Retry only on BRIDGE_UNAVAILABLE (exit 5) with backoff 0.5s, 1s, 2s.
Quick flow
# 1. Start the bridge $ harnessgg-gimp bridge start # 2. Inspect the image $ harnessgg-gimp inspect photo.png {"ok":true,"protocolVersion":"1.0","command":"inspect","data":{"width":3840,"height":2160,"layers":1}} # 3. Resize it $ harnessgg-gimp resize photo.png --width 1920 --height 1080 --output resized.png {"ok":true,"protocolVersion":"1.0","command":"resize","data":{}} # 4. Adjust brightness and contrast $ harnessgg-gimp brightness-contrast resized.png --brightness 0.1 --contrast 0.2 --output adjusted.png {"ok":true,"protocolVersion":"1.0","command":"brightness-contrast","data":{}} # 5. Apply a gaussian blur $ harnessgg-gimp gaussian-blur adjusted.png --radius-x 2.0 --radius-y 2.0 --output blurred.png {"ok":true,"protocolVersion":"1.0","command":"gaussian-blur","data":{}} # 6. Export as JPEG $ harnessgg-gimp export blurred.png final.jpg {"ok":true,"protocolVersion":"1.0","command":"export","data":{"output":"final.jpg"}}
Schema examples
Each command returns one JSON object. Use ok and error.code for branching.
{"ok":true,"protocolVersion":"1.0","command":"resize","data":{"output":"resized.png"}} {"ok":false,"protocolVersion":"1.0","command":"open","error":{"code":"NOT_FOUND","message":"File not found","retryable":false}} Bridge commands
The bridge must be running before any image editing call. It binds to 127.0.0.1:41749 by default.
bridge start harnessgg-gimp bridge start [--host 127.0.0.1] [--port 41749]
Start the local bridge server on port 41749. Must be running before any image editing commands.
| Flag | Required | Description |
|---|---|---|
--host | no | Bind address (default: 127.0.0.1) |
--port | no | Port (default: 41749) |
bridge serve harnessgg-gimp bridge serve
Run the bridge in the foreground (blocking). Useful for container environments.
bridge stop harnessgg-gimp bridge stop
Shut down the running bridge server.
bridge status harnessgg-gimp bridge status
Check whether the bridge is reachable and healthy. Run before any mutating commands.
bridge verify harnessgg-gimp bridge verify [--iterations 10] [--max-failures 0]
Run a stability check against the bridge. Recommended before long editing sessions.
| Flag | Required | Description |
|---|---|---|
--iterations | no | Number of health pings (default: 10) |
--max-failures | no | Allowed failures before abort (default: 0) |
System commands
Utility commands for checking the installation. version does not require the bridge.
version harnessgg-gimp version
Print the package version. Does not require the bridge to be running.
doctor harnessgg-gimp doctor
Check the installation environment: GIMP availability, bridge connectivity, and Python version.
actions harnessgg-gimp actions
List all available commands with their synopses. Useful for agent discovery.
File commands
Commands operate on image file paths. Use --output to save to a different path; the default behaviour is to overwrite the input file.
open harnessgg-gimp open <image>
Open an image file through the bridge. Use before commands that require an open document context.
save harnessgg-gimp save <image> <output>
Save the image to a file path. Writes in the format inferred from the output extension.
export harnessgg-gimp export <image> <output>
Export the image, inferring format from the output file extension. Supported extensions: .jpg, .png, .webp, .xcf.
clone-project harnessgg-gimp clone-project <source> <target> [--overwrite]
Copy an image file to a new path. Use to create a working copy before destructive edits.
| Flag | Required | Description |
|---|---|---|
--overwrite | no | Replace target if it already exists |
inspect harnessgg-gimp inspect <image>
Return a structured summary of the image: dimensions, colour mode, layer count, and layer names.
validate harnessgg-gimp validate <image>
Check that the image file is readable and structurally valid. Run before a batch pipeline.
diff harnessgg-gimp diff <source> <target>
Compare two image files and return a pixel-level difference summary.
snapshot harnessgg-gimp snapshot <image> <description>
Save a named checkpoint of the image state. Use before risky edits; restore with undo.
undo harnessgg-gimp undo <image>
Undo the last edit applied to the image.
redo harnessgg-gimp redo <image>
Redo the last undone edit.
Transform commands
Geometric transformations on the full image canvas. All accept --output to preserve the original.
resize harnessgg-gimp resize <image> --width <int> --height <int> [--output <path>]
Scale the image to the given dimensions. Overwrites the input file unless --output is specified.
| Flag | Required | Description |
|---|---|---|
--width | yes | Target width in pixels |
--height | yes | Target height in pixels |
--output | no | Save result to a different file (default: overwrite input) |
crop harnessgg-gimp crop <image> --x <int> --y <int> --width <int> --height <int> [--output <path>]
Crop the image to the given rectangle.
| Flag | Required | Description |
|---|---|---|
--x | yes | Left edge of the crop region in pixels |
--y | yes | Top edge of the crop region in pixels |
--width | yes | Crop width in pixels |
--height | yes | Crop height in pixels |
--output | no | Output file path (default: overwrite input) |
rotate harnessgg-gimp rotate <image> --degrees 90|180|270 [--output <path>]
Rotate the image by a fixed angle. Only 90, 180, and 270 degree values are accepted.
| Flag | Required | Description |
|---|---|---|
--degrees | yes | 90, 180, or 270 |
--output | no | Output file path (default: overwrite input) |
flip harnessgg-gimp flip <image> --axis horizontal|vertical [--output <path>]
Flip the image along the horizontal or vertical axis.
| Flag | Required | Description |
|---|---|---|
--axis | yes | horizontal or vertical |
--output | no | Output file path (default: overwrite input) |
canvas-size harnessgg-gimp canvas-size <image> --width <int> --height <int> [--offset-x <int>] [--offset-y <int>] [--output <path>]
Resize the canvas without scaling the image content. Use offset flags to control where the existing content is positioned on the new canvas.
| Flag | Required | Description |
|---|---|---|
--width | yes | New canvas width in pixels |
--height | yes | New canvas height in pixels |
--offset-x | no | X offset of existing content on the new canvas |
--offset-y | no | Y offset of existing content on the new canvas |
--output | no | Output file path (default: overwrite input) |
Color adjustments
Colour correction commands. Use --layer-index to target a specific layer (default: 0).
brightness-contrast harnessgg-gimp brightness-contrast <image> [--brightness <f>] [--contrast <f>] [--layer-index <int>] [--output <path>]
Adjust brightness and contrast on a layer. Values are floating-point offsets.
| Flag | Required | Description |
|---|---|---|
--brightness | no | Brightness adjustment |
--contrast | no | Contrast adjustment |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
levels harnessgg-gimp levels <image> [--black <f>] [--white <f>] [--gamma <f>] [--layer-index <int>] [--output <path>]
Set input levels for black point, white point, and gamma on a layer.
| Flag | Required | Description |
|---|---|---|
--black | no | Black input level |
--white | no | White input level |
--gamma | no | Gamma correction value |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
curves harnessgg-gimp curves <image> --points-json <json> [--channel value|red|green|blue|alpha] [--layer-index <int>] [--output <path>]
Apply a curves adjustment using control points provided as a JSON array. Use --channel to target a specific channel.
| Flag | Required | Description |
|---|---|---|
--points-json | yes | JSON array of curve control points |
--channel | no | value, red, green, blue, or alpha (default: value) |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
color-balance harnessgg-gimp color-balance <image> [--cyan-red <f>] [--magenta-green <f>] [--yellow-blue <f>] [--transfer-mode MIDTONES] [--layer-index <int>] [--output <path>]
Shift the colour balance of a layer across shadow, midtone, and highlight ranges.
| Flag | Required | Description |
|---|---|---|
--cyan-red | no | Cyan-to-red shift |
--magenta-green | no | Magenta-to-green shift |
--yellow-blue | no | Yellow-to-blue shift |
--transfer-mode | no | Tonal range: SHADOWS, MIDTONES, or HIGHLIGHTS (default: MIDTONES) |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
hue-saturation harnessgg-gimp hue-saturation <image> [--hue <f>] [--saturation <f>] [--lightness <f>] [--layer-index <int>] [--output <path>]
Adjust hue, saturation, and lightness on a layer.
| Flag | Required | Description |
|---|---|---|
--hue | no | Hue rotation in degrees |
--saturation | no | Saturation adjustment |
--lightness | no | Lightness adjustment |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
color-temperature harnessgg-gimp color-temperature <image> --temperature <f> [--layer-index <int>] [--output <path>]
Shift the colour temperature of a layer. Positive values are warmer, negative values are cooler.
| Flag | Required | Description |
|---|---|---|
--temperature | yes | Temperature shift value |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
invert harnessgg-gimp invert <image> [--layer-index <int>] [--output <path>]
Invert the colours of a layer.
| Flag | Required | Description |
|---|---|---|
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
desaturate harnessgg-gimp desaturate <image> [--mode luma|average|lightness] [--layer-index <int>] [--output <path>]
Convert a layer to greyscale using the specified desaturation algorithm.
| Flag | Required | Description |
|---|---|---|
--mode | no | luma, average, or lightness (default: luma) |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
Filters
Convolution and noise filters. All operate on a single layer and accept --output.
blur harnessgg-gimp blur <image> [--radius 4.0] [--layer-index <int>] [--output <path>]
Apply a simple blur filter to a layer.
| Flag | Required | Description |
|---|---|---|
--radius | no | Blur radius (default: 4.0) |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
gaussian-blur harnessgg-gimp gaussian-blur <image> [--radius-x 4.0] [--radius-y 4.0] [--layer-index <int>] [--output <path>]
Apply a Gaussian blur with independent horizontal and vertical radii.
| Flag | Required | Description |
|---|---|---|
--radius-x | no | Horizontal blur radius (default: 4.0) |
--radius-y | no | Vertical blur radius (default: 4.0) |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
sharpen harnessgg-gimp sharpen <image> [--radius 2.0] [--amount 1.0] [--layer-index <int>] [--output <path>]
Apply a sharpen filter to a layer.
| Flag | Required | Description |
|---|---|---|
--radius | no | Sharpen radius (default: 2.0) |
--amount | no | Sharpen strength (default: 1.0) |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
unsharp-mask harnessgg-gimp unsharp-mask <image> [--radius 2.0] [--amount 1.0] [--threshold 0.0] [--layer-index <int>] [--output <path>]
Apply an unsharp mask for controlled edge sharpening.
| Flag | Required | Description |
|---|---|---|
--radius | no | Radius of the blur used in the mask (default: 2.0) |
--amount | no | Sharpening strength (default: 1.0) |
--threshold | no | Minimum difference to apply sharpening (default: 0.0) |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
noise-reduction harnessgg-gimp noise-reduction <image> [--strength 3] [--layer-index <int>] [--output <path>]
Apply a noise reduction filter to a layer.
| Flag | Required | Description |
|---|---|---|
--strength | no | Reduction strength 1-10 (default: 3) |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
Layer commands
Add, remove, reorder, and configure layers. Use layer-list to discover layer indices before targeting them.
layer-list harnessgg-gimp layer-list <image>
List all layers in the image with their index, name, opacity, and blend mode.
layer-add harnessgg-gimp layer-add <image> --name <s> [--position <int>] [--output <path>]
Add a new empty layer to the image.
| Flag | Required | Description |
|---|---|---|
--name | yes | Name for the new layer |
--position | no | Insert position in the layer stack (default: top) |
--output | no | Output file path (default: overwrite input) |
layer-remove harnessgg-gimp layer-remove <image> --layer-index <int> [--output <path>]
Remove the layer at the given index.
| Flag | Required | Description |
|---|---|---|
--layer-index | yes | Index of the layer to remove |
--output | no | Output file path (default: overwrite input) |
layer-rename harnessgg-gimp layer-rename <image> --layer-index <int> --name <s> [--output <path>]
Rename a layer.
| Flag | Required | Description |
|---|---|---|
--layer-index | yes | Index of the target layer |
--name | yes | New name for the layer |
--output | no | Output file path (default: overwrite input) |
layer-opacity harnessgg-gimp layer-opacity <image> --layer-index <int> --opacity <0-100> [--output <path>]
Set the opacity of a layer to a value between 0 (transparent) and 100 (fully opaque).
| Flag | Required | Description |
|---|---|---|
--layer-index | yes | Index of the target layer |
--opacity | yes | Opacity value from 0 to 100 |
--output | no | Output file path (default: overwrite input) |
layer-blend-mode harnessgg-gimp layer-blend-mode <image> --layer-index <int> --mode <s> [--output <path>]
Set the blend mode of a layer. Common modes: NORMAL, MULTIPLY, SCREEN, OVERLAY.
| Flag | Required | Description |
|---|---|---|
--layer-index | yes | Index of the target layer |
--mode | yes | Blend mode name: NORMAL, MULTIPLY, SCREEN, OVERLAY, etc. |
--output | no | Output file path (default: overwrite input) |
layer-duplicate harnessgg-gimp layer-duplicate <image> --layer-index <int> [--position <int>] [--output <path>]
Duplicate a layer and insert the copy at the specified position.
| Flag | Required | Description |
|---|---|---|
--layer-index | yes | Index of the layer to duplicate |
--position | no | Stack position for the new copy (default: directly above source) |
--output | no | Output file path (default: overwrite input) |
layer-merge-down harnessgg-gimp layer-merge-down <image> --layer-index <int> [--output <path>]
Merge the layer at the given index down onto the layer below it.
| Flag | Required | Description |
|---|---|---|
--layer-index | yes | Index of the layer to merge down |
--output | no | Output file path (default: overwrite input) |
layer-reorder harnessgg-gimp layer-reorder <image> --layer-index <int> --index <int> [--output <path>]
Move a layer to a new position in the layer stack.
| Flag | Required | Description |
|---|---|---|
--layer-index | yes | Current index of the layer to move |
--index | yes | Destination index in the layer stack |
--output | no | Output file path (default: overwrite input) |
Selection commands
Create and manipulate selections. Selections persist across commands until cleared with select-none.
select-all harnessgg-gimp select-all <image> [--output <path>]
Select the entire canvas.
| Flag | Required | Description |
|---|---|---|
--output | no | Output file path (default: overwrite input) |
select-none harnessgg-gimp select-none <image> [--output <path>]
Deselect the current selection.
| Flag | Required | Description |
|---|---|---|
--output | no | Output file path (default: overwrite input) |
invert-selection harnessgg-gimp invert-selection <image> [--output <path>]
Invert the current selection so that the unselected area becomes selected.
| Flag | Required | Description |
|---|---|---|
--output | no | Output file path (default: overwrite input) |
feather-selection harnessgg-gimp feather-selection <image> --radius <f> [--output <path>]
Feather the edges of the current selection by the given radius.
| Flag | Required | Description |
|---|---|---|
--radius | yes | Feather radius in pixels |
--output | no | Output file path (default: overwrite input) |
select-rectangle harnessgg-gimp select-rectangle <image> --x <int> --y <int> --width <int> --height <int> [--output <path>]
Create a rectangular selection.
| Flag | Required | Description |
|---|---|---|
--x | yes | Left edge of the selection |
--y | yes | Top edge of the selection |
--width | yes | Width of the selection |
--height | yes | Height of the selection |
--output | no | Output file path (default: overwrite input) |
select-ellipse harnessgg-gimp select-ellipse <image> --x <int> --y <int> --width <int> --height <int> [--output <path>]
Create an elliptical selection bounded by the given rectangle.
| Flag | Required | Description |
|---|---|---|
--x | yes | Left edge of the bounding rectangle |
--y | yes | Top edge of the bounding rectangle |
--width | yes | Bounding rectangle width |
--height | yes | Bounding rectangle height |
--output | no | Output file path (default: overwrite input) |
add-layer-mask harnessgg-gimp add-layer-mask <image> --layer-index <int> [--mode WHITE] [--output <path>]
Add a layer mask to the specified layer. The default mode WHITE creates a fully visible mask.
| Flag | Required | Description |
|---|---|---|
--layer-index | yes | Index of the layer to mask |
--mode | no | Mask initialisation mode (default: WHITE) |
--output | no | Output file path (default: overwrite input) |
apply-layer-mask harnessgg-gimp apply-layer-mask <image> --layer-index <int> [--output <path>]
Apply and remove the layer mask, merging it permanently into the layer.
| Flag | Required | Description |
|---|---|---|
--layer-index | yes | Index of the layer whose mask to apply |
--output | no | Output file path (default: overwrite input) |
Text commands
Add and modify text layers, and stroke active selections.
add-text harnessgg-gimp add-text <image> --text <s> --x <int> --y <int> [--font Sans] [--size 36.0] [--color #ffffff] [--layer-index <int>] [--output <path>]
Add a text layer to the image at the given coordinates.
| Flag | Required | Description |
|---|---|---|
--text | yes | Text content to render |
--x | yes | X position of the text origin |
--y | yes | Y position of the text origin |
--font | no | Font family name (default: Sans) |
--size | no | Font size in points (default: 36.0) |
--color | no | Text colour as a hex code (default: #ffffff) |
--layer-index | no | Target layer for the text (default: 0) |
--output | no | Output file path (default: overwrite input) |
update-text harnessgg-gimp update-text <image> --layer-index <int> --text <s> [--output <path>]
Update the text content of an existing text layer.
| Flag | Required | Description |
|---|---|---|
--layer-index | yes | Index of the text layer to update |
--text | yes | New text content |
--output | no | Output file path (default: overwrite input) |
stroke-selection harnessgg-gimp stroke-selection <image> --width <f> [--color #ffffff] [--layer-index <int>] [--output <path>]
Stroke the current selection boundary with the given width and colour.
| Flag | Required | Description |
|---|---|---|
--width | yes | Stroke width in pixels |
--color | no | Stroke colour as a hex code (default: #ffffff) |
--layer-index | no | Target layer (default: 0) |
--output | no | Output file path (default: overwrite input) |
Full command list
Complete CLI surface from the package docs. Use this list for long-form planning or tool coverage audits.
# Bridge $ harnessgg-gimp bridge serve [--host] [--port ] $ harnessgg-gimp bridge start [--host ] [--port ] $ harnessgg-gimp bridge stop $ harnessgg-gimp bridge status $ harnessgg-gimp bridge verify [--iterations ] [--max-failures ] $ harnessgg-gimp bridge soak [--iterations ] [--action ] [--action-params-json ] # System $ harnessgg-gimp actions $ harnessgg-gimp capabilities $ harnessgg-gimp doctor [--verbose] $ harnessgg-gimp version $ harnessgg-gimp plan-edit [--params-json ] # Project and safety $ harnessgg-gimp open $ harnessgg-gimp save
Response shape
Every command emits exactly one JSON object to stdout. Check ok first.
Success
{
"ok": true,
"protocolVersion": "1.0",
"command": "resize",
"data": {}
} Error
{
"ok": false,
"protocolVersion": "1.0",
"command": "resize",
"error": {
"code": "NOT_FOUND",
"message": "File 'photo.png' not found",
"retryable": false
}
} Error codes
| Code | Exit | Retryable | Action |
|---|---|---|---|
BRIDGE_UNAVAILABLE | 5 | yes | Bridge not reachable. Run bridge start then retry with backoff 0.5s, 1s, 2s (max 3 retries). This is the only retryable exit code. |
INVALID_INPUT | 4 | no | Bad or missing arguments. Fix the command before retrying. |
VALIDATION_FAILED | 3 | no | Image or parameters failed validation. Inspect the image and fix issues first. |
NOT_FOUND | 2 | no | File path not found. Check that the image path exists and is readable. |
ERROR | 1 | no | General error. Check the error message and fix the cause before retrying. |
Submit feedback
Agents can file bug reports and feature requests via POST /api/submit.
Issues land on harnessgg/harness-gimp.
| Field | Required | Values |
|---|---|---|
type | yes | "bug" | "feature" | "question" |
package | yes | "gimp" |
title | yes | Short summary |
body | yes | Full description |
context | no | Bridge version, OS, image details... |
$ curl -X POST https://harness.gg/api/submit \
-H "Content-Type: application/json" \
-d '{"type":"bug","package":"gimp","title":"bridge fails on start","body":"Steps..."}'