Scriptable CLI tool for generating and editing images with OpenAI, Gemini, and FLUX.
npm install -g etch-image
etch "a polished app icon for a CLI image generation tool called etch"
You'll need an API key for the provider you want to use in ~/.config/etch/.env See Setup
| Provider | Models |
|---|---|
| OpenAI | |
| Gemini | |
| FLUX (Black Forest Labs) |
npm install -g etch-image
Etch is bring-your-own-token. You provide API keys for the providers you want to use. Put them in ~/.config/etch/.env:
OPENAI_API_KEY=your_key_here
GEMINI_API_KEY=your_key_here
BFL_API_KEY=your_key_here
You only need keys for the providers you plan to use. Keys are read from the shell environment first, then ~/.config/etch/.env.
etch [input_file ...] "prompt" [options]
The last positional argument is always the prompt. Anything before it is treated as an input image:
- No input files β generate a new image from the prompt.
- One or more input files β edit those images using the prompt.
The result is saved as a PNG. Pass -o <path> to choose the file, or leave it out and Etch generates a name and outputs it in the current directory (or in output_dir from your config).
| Flag | Description |
|---|---|
-o, --output <path> |
Where to save the image (default: an auto-named PNG in the current directory). Never overwrites an existing file unless --force is given |
-n, --count <n> |
Number of images to generate, 1 to 10 (default: 1). With -o , files get a-1 ,-2 , ... suffix |
--model <model> |
Model to use (default: gpt-image-2.5-sunburst ) |
--size <size> |
Output size; depends on the provider, see Sizes and quality |
--quality <quality> |
Quality level (OpenAI) or resolution tier (FLUX 3), see Sizes and quality |
--background <background> |
Background style (OpenAI only) |
--open |
Open the image after it is saved (default when run from a terminal) |
--dont-open |
Don't open the image after it is saved |
--json |
Print the result as a JSON object instead of text |
--force |
Overwrite the output file if it already exists |
--models |
List available models and exit |
--sizes |
List available sizes by provider and exit |
--config |
Show the config file path and effective defaults, then exit |
What --size and --quality accept depends on the model. Run etch --sizes for the list.
OpenAI
- Size:
auto,1024x1024,1536x1024,1024x1536.gpt-image-2and later also accept anyWIDTHxHEIGHT(multiples of 16, aspect ratio 1:3 to 3:1, up to3840x2160). - Quality:
auto,low,medium,high.gpt-image-2.5models also acceptxhighandmax.
Gemini
- Size:
1K,2K,4K.gemini-3.1-flash-imagealso accepts512px,gemini-3.1-flash-lite-imageonly1K, andgemini-2.5-flash-imagetakes no size. - Quality: not supported.
FLUX
- Size: an aspect ratio like
16:9, from 21:9 to 9:21.flux-3models take a fixed list of ratios (see--sizes). FLUX 2, 1.1 and dev also acceptWIDTHxHEIGHT; a ratio is converted to about 1 megapixel for these models. - Quality:
flux-3models only, as a resolution tier:768sq,1k,1.5k,2k,4k.
Any option's default can be changed in ~/.config/etch/config.json (or $XDG_CONFIG_HOME/etch/config.json if that variable is set). A flag on the command line always wins over the config file.
{
"open": false,
"model": "gpt-image-2.5-flare",
"quality": "high",
"output_dir": "~/Pictures/etch"
}
Supported settings: model, size, quality, background, count, open, output_dir. The output_dir setting only applies when -o is not given. Run etch --config to see the effective defaults.
Only the saved paths are written to stdout, one per line. Progress and the model details go to stderr, and when stdout is not a terminal the spinner and auto-open are skipped. So the output can be captured or piped directly:
file=$(etch "a red cube")
etch "a red cube" | xargs open
Pass --open to open the image anyway.
With --json, stdout is a single JSON object and errors on stderr are JSON too. path is the first image and paths lists all of them:
etch --json "a red cube" | jq -r .path
{"path":"/Users/you/etch-20261021-143210-k8v1.png","paths":["/Users/you/etch-20261021-143210-k8v1.png"],"mode":"generate","provider":"openai","model":"gpt-image-2.5-sunburst","size":null,"quality":null,"background":null,"inputs":[],"elapsed_ms":11840,"cost_usd":0.0412,"cost_estimated":true}
Exit codes:
| Code | Meaning |
|---|---|
0 |
Image saved |
1 |
Usage or config error (bad flag, invalid size, missing input file) |
2 |
Provider error (bad API key, network, server error) |
3 |
Request refused by the provider's content moderation |
Generate an image from a prompt:
etch "a dramatic sunset over the ocean"
Save to a specific file:
etch "a dramatic sunset over the ocean" -o output/sunset.png
Generate four variations at once:
etch "a dramatic sunset over the ocean" -n 4
Edit an image:
etch source.png "make the sky purple"
Use a specific model:
etch source.png "make the sky purple" --model gemini-nano-banana-2.1
Specify size and quality:
etch source.png "add a sunset" --size 1536x1024 --quality high
Generate a 4K widescreen image with the top quality setting (gpt-image-2.5 models only):
etch "a city skyline at dusk" --size 3840x2160 --quality max -o output/skyline.png
Use a FLUX model:
etch "cyberpunk cityscape at night" --model flux-2-pro --size 16:9
Generate a 4K image with FLUX 3:
etch "cyberpunk cityscape at night" --model flux-3-image --size 21:9 --quality 4k
Use multiple input images:
etch room.jpg reference.jpg "restyle the first room to match the second" -o output/restyled.png
Save without opening the result:
etch "a minimal app icon" --dont-open
The repo ships a plugin that teaches Claude Code and Codex how to use Etch: ask for an image in a session and the agent runs etch for you, names the file sensibly, and reports the cost. It needs etch installed and an API key configured as described in Setup.
Claude Code:
/plugin install etch --marketplace michaeldmueller/etch-image
Codex:
codex plugin marketplace add michaeldmueller/etch-image
codex plugin add etch@etch-image
Both read the same skill, in plugins/etch/skills/etch/SKILL.md. To use it as a standalone skill instead, copy that folder to ~/.claude/skills/etch or ~/.agents/skills/etch.