pixforge
A fast, single-binary CLI for generating images from text prompts. Speaks multiple providers natively — switch between OpenAI, Azure OpenAI, Azure MAI, Google Gemini, and LocalAI by changing one config value, no code or env-var juggling required.
# → ./pixforge-20260503-100201-688df5.png (and opens it in your default viewer)
# → uses your Gemini profile instead
Built in Rust on a synchronous HTTP stack (ureq + rustls) for fast cold
starts and a small binary.
Demo
(If your viewer doesn't render embedded video, watch it directly: docs/demo.mp4)
Install
Shell installer (any Unix — recommended for v0.2)
|
This downloads the right binary for your platform (macOS arm64/x86_64, Linux
arm64/x86_64) and installs it into $CARGO_HOME/bin (defaults to
~/.cargo/bin).
From crates.io (Rust users)
Homebrew
Coming in a follow-up release. Currently the binary ships via the shell installer above and via crates.io.
Shell completions and man page
After installing, set up completions and the man page from the binary itself:
# bash
|
# zsh (adjust the path to a directory in your $fpath)
# fish
# man page
|
Build from source
# binary: ./target/release/pixforge
First-time setup
The fastest path is the interactive wizard:
It asks which provider you want, walks you field-by-field with inline
validation, optionally tests the connection, optionally appends the
export line to your shell config, and writes the profile. Most users
finish in under a minute.
Prefer to write TOML by hand?
config.toml example with two providers:
= "azure-mai"
[]
= "azure-mai"
= "https://your-resource.services.ai.azure.com"
= "MAI-Image-2"
= "AZURE_API_KEY"
= "preview"
[]
= "openai-compat"
= "https://api.openai.com/v1"
= "gpt-image-1"
= "OPENAI_API_KEY"
Then in your shell:
The config file lives at $XDG_CONFIG_HOME/pixforge/config.toml, defaulting
to ~/.config/pixforge/config.toml on every OS. Run pixforge config-path
to see the resolved location.
Security note: literal
api_key = "..."is rejected inconfig.tomlto keep committed configs safe. Onlyapi_key_env = "VAR"is allowed; the actual secret is read from the environment at request time.
Supported providers
| Provider | provider = value |
Auth header | Notes |
|---|---|---|---|
| Azure MAI | azure-mai |
api-key |
Microsoft AI image models on Azure AI Foundry. Uses width/height. |
| OpenAI | openai-compat |
Authorization: Bearer |
DALL·E, gpt-image-*. Also covers Gemini's OpenAI-compat layer for chat (NOT image gen — use provider = "gemini" for Imagen). |
| Azure OpenAI | azure-openai |
api-key |
DALL·E etc. via Azure deployments. Requires api_version. |
| Google Gemini | gemini |
x-goog-api-key |
Native API for gemini-*-image and Imagen models. Image size is decided by Gemini — passing -W/-H is rejected. |
| LocalAI | openai-compat |
none | Run image gen locally via Docker. See LocalAI setup. |
LocalAI setup
LocalAI is the easiest way to run a real OpenAI-compatible image-gen server on your own machine. CPU-only example (no GPU required):
# In another shell, install a small image model:
Then add this to your config.toml:
[]
= "openai-compat"
= "http://localhost:8080/v1"
= "stable-diffusion-1.5"
= "none"
Environment variables
These override any config file values, in this order of precedence: CLI flags > env vars > config file > built-in defaults.
| Variable | Effect |
|---|---|
PIXFORGE_PROFILE |
Picks the profile when no --profile flag is given |
XDG_CONFIG_HOME |
Locates the config file |
(the env var named in api_key_env) |
Provides the credential at request time |
Usage
pixforge [OPTIONS] -p <PROMPT>
Options:
-p, --prompt <PROMPT> Prompt text. Use `-` to read from stdin.
-o, --output <PATH> Output PNG path (default: ./pixforge-{ts}-{hash}.png)
--profile <NAME> Pick a profile from your config
-m, --model <NAME> Override model / deployment for this call
-W, --width <N> Width in px (validated per-provider)
-H, --height <N> Height in px (validated per-provider)
--endpoint <URL> Override provider endpoint
--api-version <STR> Override API version (where applicable)
--quality <STR> Quality hint (low|medium|high) for providers that support it
--timeout <SECS> HTTP timeout (default: 300)
--max-attempts <N> Retries on 429/5xx/transport (default: 5)
--no-open Don't open the image after generation
-q, --quiet Suppress progress on stderr
Subcommands:
init Write a starter config file
config-path Print the resolved config path
profiles List profiles in your config
profile show <name> Show a profile's resolved settings (api_key masked)
Examples
Pipe a long prompt from a file:
|
Switch providers per call:
Scriptable usage (only the path is on stdout):
img=
Inspect a profile (the api_key is never printed; you only see the env var name and its status):
)
Output
For every successful generation, two files are written:
<output>.png— the image<output>.png.prompt.json— sidecar with full provenance:
Both are written atomically (*.tmp then rename).
Behavior notes
- Retries on HTTP 429/5xx and transport errors (DNS/TLS/timeout) with
exponential backoff (1, 2, 4, 8, 16s + jitter, capped at 60s). Honors
Retry-After,retry-after-ms, andx-ms-retry-after-ms. - Per-provider validation runs before the HTTP call where possible:
azure-mairequireswidth >= 768 && height >= 768 && width*height <= 1,048,576geminirejects-W/-H(the model picks the size)openai-compat/azure-openaisend the requested size verbatim; if it's not allowed for the model, the API returns a 400 with details.
- Exit codes:
0success,1runtime error,2config / usage error. - stdout vs stderr: progress and warnings go to stderr; the final image
path is the only thing on stdout, so
$(pixforge -p …)is safe in scripts.
Adding a new provider
- Create
src/providers/your_provider.rsimplementingImageProvider(seesrc/providers/azure_mai.rsas a small reference). - Add a variant to
ProviderKindinsrc/config.rsand wire its validator (required fields, default endpoint, defaultauth_style). - Construct the adapter in
build_providerinsrc/main.rs. - Add a
tests/your_provider_mock.rscovering URL/headers/body, success parsing, retry behavior, and error cases. Use the existing test files as templates.
PRs welcome.
License
MIT — see LICENSE.