Images
APX turns a prompt into a file with apx image. It does not run a model itself: it talks to
a diffusion server you point it at — one on this machine, one on your network, or a cloud API —
and routes between them the same way voice routes between TTS engines.
Quick start
Section titled “Quick start”$ apx image "a green origami fox on a white background" /Users/you/.apx/images/2026-08-28/a1111-6f0c….png a1111 · z_image_turbo · 512x512 · seed 1608784042 · 476 KB · 24.9s
Without --out the file lands in ~/.apx/images/<date>/ and the path is printed. Nothing is
written into a project checkout unless you ask for it:
apx image "portrait of a fox" --size 768x512 --steps 8 --cfg 1.0 --out fox.pngEngines
Section titled “Engines”An engine is a server plus the dialect it speaks. Four are built in:
| id | API | What it covers |
|---|---|---|
a1111 | POST /sdapi/v1/txt2img (synchronous) | The universal dialect: AUTOMATIC1111, Forge, SD.Next, Draw Things on macOS, stable-diffusion.cpp. Carries every sampling knob. |
sdcpp | POST /sdcpp/v1/img_gen + job polling | stable-diffusion.cpp’s native queue. The request returns immediately and the job is polled, so a queued render never looks like a hung connection. |
openai | POST /v1/images/generations | OpenAI itself (gpt-image-1, dall-e-3), or any OpenAI-compatible server when you set a base URL. |
mock | — | An offline test engine. Always last in the chain, and used only when no real engine was tried — never to paper over one that failed. |
You can add any number of your own endpoints; each one declares which of the three dialects it speaks, so a single screen covers a local server, a LAN box and a cloud key.
Configuration
Section titled “Configuration”Everything lives under images.* in ~/.apx/config.json, and has a screen at
Settings → Images in the web panel.
apx config set --global images.a1111.base_url http://127.0.0.1:7860apx config set --global images.a1111.defaults '{"steps":8,"cfg_scale":1}'| Key | What it does |
|---|---|
images.<engine>.base_url | Where the server is. The origin only — no API path. |
images.<engine>.api_key | Optional. Most local and LAN servers need none. |
images.<engine>.model | Checkpoint or model id, where the server can switch. |
images.<engine>.defaults | Size, steps, guidance, sampler, scheduler for this server. |
images.<engine>.timeout_s | How long to wait for one image. |
images.defaults | The shared bottom layer: size, format, negative prompt, count. |
images.order | The chain order. The first engine that draws wins. |
images.mode | chain (router, the default) or single (only images.provider). |
images.custom.<slug> | Your own endpoint. Needs label, kind and base_url. |
Routing
Section titled “Routing”Engines are tried in order until one draws. The chain covers both ways an engine can let a
call down: a configured but unreachable server is skipped, and one that answers a probe but
fails the render hands the prompt to the next engine — a diffusion box whose GPU has fallen
over still answers probes perfectly. --provider overrides the routing for one call, and
apx image providers shows what is reachable right now.
A named engine — --provider, or single mode — fails without a retry, so the settings tester
reports on the engine you pointed it at rather than quietly rendering somewhere else. mock
closes the chain for a machine with nothing configured, but never stands in for a failed
render: a placeholder handed back as success cannot be told apart from a real picture.
When every engine fails, the error names each one it tried, where that server lives and what the server itself said, so a broken box is identifiable from the message alone:
$ apx image "a fox" apx image: image generation failed — all 3 engines tried: · custom:zimage (http://box.example:8189): 500: server_error: vk::Queue::submit: ErrorDeviceLost · custom:sdxl (http://box.example:8192): 500: server_error: vk::Queue::submit: ErrorDeviceLost · custom:flux (http://box.example:8191): 500: server_error: vk::Queue::submit: ErrorDeviceLost
Three servers, one message: that is the GPU they share, not three broken models.
$ apx image providers Routing chain (a1111 → sdcpp → openai → mock) ● a1111 reachable, configured http://127.0.0.1:7860 ○ openai unreachable, not configured ● mock reachable, not configured
Where the knobs belong
Section titled “Where the knobs belong”Options resolve in three layers — images.defaults, then images.<engine>.defaults, then the
call. Steps and guidance belong to the engine, because the right value depends on the
checkpoint that server loaded: a turbo checkpoint wants about 8 steps at guidance 1, a standard
one 20 at guidance 7. Putting them in the engine’s own block means no caller has to remember
which server they are talking to.
Not every engine honors every option
Section titled “Not every engine honors every option”The OpenAI dialect has no steps, guidance, sampler, scheduler, seed or negative prompt. stable-diffusion.cpp hosts one checkpoint and cannot switch models. Rather than accepting an option and quietly ignoring it, APX reports it:
sdcpp ignored: modelapx image capabilities asks a server what it actually offers — models, samplers, schedulers,
output formats — so you are not guessing at names.
Options
Section titled “Options”| Flag | Meaning |
|---|---|
--out <file> | Copy the result here. A directory works too. |
--provider <id> | a1111 | sdcpp | openai | mock | custom:<slug> |
--size <WxH> | e.g. 768x512. Or --width / --height. |
--steps N | Sampling steps. |
--cfg N | Guidance scale. |
--seed N | Fix the seed for a reproducible image. -1 is random. |
--negative "…" | What to keep out of the picture. |
--count N | How many images in one run. |
--model <id> | Checkpoint, where the server can switch. |
--format <ext> | png | jpeg | webp, where supported. |
--sampler / --scheduler | Names from apx image capabilities. |
--json | Engine, resolved request, ignored options and file paths. |
--open | Open the result in the OS viewer. |