{"id":51294269,"url":"https://github.com/schappim/goimage","last_synced_at":"2026-06-30T13:01:27.213Z","repository":{"id":360671658,"uuid":"1251190862","full_name":"schappim/goimage","owner":"schappim","description":"CLI for image generation using OpenAI GPT Image, Google Gemini 2.5 Flash Image (nano banana), or xAI Grok - single Go binary","archived":false,"fork":false,"pushed_at":"2026-05-27T10:58:35.000Z","size":48,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-27T12:17:19.654Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/schappim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-27T10:31:56.000Z","updated_at":"2026-05-27T10:58:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/schappim/goimage","commit_stats":null,"previous_names":["schappim/goimage"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/schappim/goimage","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schappim%2Fgoimage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schappim%2Fgoimage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schappim%2Fgoimage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schappim%2Fgoimage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/schappim","download_url":"https://codeload.github.com/schappim/goimage/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schappim%2Fgoimage/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34967627,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-30T13:01:25.398Z","updated_at":"2026-06-30T13:01:27.174Z","avatar_url":"https://github.com/schappim.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# goimage\n\nA self-contained command-line tool for image generation using OpenAI (GPT Image), Google Gemini 2.5 Flash Image (nano banana), or xAI Grok image APIs. Written in Go — just a single binary, no external dependencies.\n\n## Features\n\n- **Multiple image providers**: OpenAI, Google nano banana, xAI Grok\n- **Single binary** - written in pure Go, no Python, no node, no ffmpeg\n- **Reference input images** (`-i`) for image-to-image / edits on OpenAI and Google\n- **Mask support** (`--mask`) for OpenAI inpainting\n- **Automatic retries** - transient network/upstream blips retried up to 3 times with exponential backoff (a client-side timeout is reported immediately, not retried)\n- **Configurable timeout** - `--timeout` sets a single deadline (default 5m) applied as a context deadline, so slow renders aren't cut off mid-flight\n- **Actionable errors** - a timeout or connectivity failure is explained in plain language with what to try next, instead of a raw Go transport string\n- **Streaming progress** - OpenAI partial-image events surface on stderr as the model renders (`--stream`, default on)\n- Provider-native model defaults and overrides\n- Prompt from arguments or stdin (great for piping)\n- Save to PNG, JPEG, or WebP (where the provider supports it)\n- Auto-named output files when `-o` is omitted\n- `--open` to view the result in your default image viewer\n- Cross-platform (macOS, Linux, Windows)\n\n## Requirements\n\n- macOS, Linux, or Windows\n- API key for your chosen provider (OpenAI, Google AI Studio, or xAI)\n\n## Installation\n\n### Homebrew (Recommended)\n\n```bash\nbrew tap schappim/goimage\nbrew install goimage\n```\n\nSee the [homebrew-goimage](https://github.com/schappim/homebrew-goimage) tap for more details.\n\n### Download Binary\n\nDownload the latest release from the [releases page](https://github.com/schappim/goimage/releases).\n\n### Build from Source\n\n```bash\ngit clone https://github.com/schappim/goimage.git\ncd goimage\ngo build -o goimage .\n\n# Optional: install to PATH\nsudo cp goimage /usr/local/bin/\n```\n\n### Configuration\n\nSet your API key(s) as environment variables:\n\n```bash\n# OpenAI (default provider)\nexport OPENAI_API_KEY=\"your-openai-api-key\"\n\n# Google Gemini (nano banana)\nexport GEMINI_API_KEY=\"your-google-ai-studio-key\"   # or GOOGLE_API_KEY\n\n# xAI Grok\nexport XAI_API_KEY=\"your-xai-key\"                   # or GROK_API_KEY\n```\n\nOr pass the key directly with the `--token` flag.\n\n## Usage\n\n### Basic Usage (OpenAI)\n\n```bash\n# Generate from a prompt (uses OpenAI by default)\ngoimage \"a watercolor of a fox curled up in autumn leaves\"\n\n# Pipe a prompt\necho \"a hand-drawn map of a fantasy island\" | goimage\n\n# Save to a specific path\ngoimage -o fox.png \"a watercolor of a fox in autumn leaves\"\n\n# Open the result in your default viewer after saving\ngoimage --open \"a logo for a coffee shop called Pixel Brew\"\n```\n\n### Using Google Gemini (nano banana)\n\n```bash\n# Switch provider\ngoimage -p google \"a cyberpunk teacup on a marble counter\"\n\n# Set aspect ratio\ngoimage -p google --aspect 16:9 \"a wide cinematic shot of a misty pine forest\"\ngoimage -p google --aspect 9:16 \"an iPhone-shaped portrait of a desert sunset\"\n```\n\n**Supported aspect ratios:** `1:1` (default), `16:9`, `9:16`, `4:3`, `3:4`\n\n### Using Grok (xAI)\n\n```bash\n# Switch provider\ngoimage -p grok \"a Saturday-morning cartoon hedgehog as a barista\"\n\n# Multiple variations from one prompt\ngoimage -p grok -n 4 -o variants.png \"logo for a Go CLI called goimage\"\n# → variants-1.png, variants-2.png, variants-3.png, variants-4.png\n```\n\n### Choose a Model\n\n**OpenAI models:** `gpt-image-2` (default), `gpt-image-1.5`, `gpt-image-1`, `gpt-image-1-mini`\n\n\u003e `gpt-image-2` requires API Organization Verification. If your key isn't verified, use `-m gpt-image-1` (or `gpt-image-1-mini` / `gpt-image-1.5`) to fall back to an earlier model.\n\n```bash\ngoimage \"a photorealistic kitchen interior at golden hour\"     # gpt-image-2 by default\ngoimage -m gpt-image-1 \"fallback when your key isn't verified\"\ngoimage -m gpt-image-1-mini \"quick thumbnail of a smiling robot\"\n```\n\n**Google models:** `gemini-2.5-flash-image` (default)\n\n**Grok models:** `grok-2-image` (default)\n\n### Size and Quality (OpenAI)\n\n```bash\n# Square (default) / landscape / portrait\ngoimage -s 1024x1024 \"a square poster of a vinyl record\"\ngoimage -s 1536x1024 \"a landscape banner of mountains at dawn\"\ngoimage -s 1024x1536 \"a portrait of an astronaut on Mars\"\n\n# Quality\ngoimage -q low \"rough draft - book cover concept\"\ngoimage -q high \"final book cover with detailed typography\"\n```\n\n### Output Format (OpenAI)\n\n```bash\ngoimage --format png  \"default PNG output\"\ngoimage --format jpeg \"smaller JPEG\"\ngoimage --format webp \"modern WebP\"\n```\n\n### Multiple Images at Once\n\n```bash\ngoimage -n 3 \"a cute pet rock with googly eyes\"\n# → goimage-openai-\u003ctimestamp\u003e-1.png\n# → goimage-openai-\u003ctimestamp\u003e-2.png\n# → goimage-openai-\u003ctimestamp\u003e-3.png\n\ngoimage -n 3 -o cat.png \"a cat in a hat\"\n# → cat-1.png cat-2.png cat-3.png\n```\n\n\u003e Google generates one image per request, so `-n` makes N separate API calls.\n\n### Reference Images (image-to-image / edits)\n\nPass `-i` one or more times to use existing images as reference. OpenAI swaps to its `/v1/images/edits` endpoint; Google attaches each image as an `inlineData` part alongside the prompt. Grok does not support reference images and will error.\n\n```bash\n# Re-render an image with a new style\ngoimage -i original.png \"make it watercolor\"\n\n# Multi-image composition (OpenAI gift basket pattern)\ngoimage -i lotion.png -i bath-bomb.png -i incense.png \\\n        \"a photorealistic gift basket containing all of these items\"\n\n# Inpainting with a mask (OpenAI only — mask alpha channel defines edit area)\ngoimage -i lounge.png --mask pool-mask.png \"put a flamingo in the pool\"\n\n# Google nano banana conversational edit\ngoimage -p google -i fox.png \"make the season autumn, add falling leaves\"\n```\n\n**Mask requirements (OpenAI):** PNG with an alpha channel, same dimensions as the first input image.\n\n### Open in Default Viewer\n\n```bash\ngoimage --open \"a desk setup with mechanical keyboard and ferns\"\n```\n\n`--open` shells out to `open` on macOS, `xdg-open` on Linux, and `start` on Windows.\n\n## Options\n\n| Option        | Short | Description                                       | Default     |\n|---------------|-------|---------------------------------------------------|-------------|\n| `--provider`  | `-p`  | Provider (`openai`, `google`, `grok`)             | `openai`    |\n| `--model`     | `-m`  | Model to use                                      | Provider-specific |\n| `--output`    | `-o`  | Save to this path                                 | Auto-named  |\n| `--size`      | `-s`  | Image size (OpenAI)                               | `1024x1024` |\n| `--quality`   | `-q`  | `low` / `medium` / `high` / `auto` (OpenAI)       | `auto`      |\n| `--format`    |       | `png` / `jpeg` / `webp` (OpenAI)                  | `png`       |\n| `--aspect`    |       | Aspect ratio (Google)                             | `1:1`       |\n| `--count`     | `-n`  | Number of images                                  | `1`         |\n| `--input`     | `-i`  | Reference image path (repeatable)                 | -           |\n| `--mask`      |       | Mask image (alpha) for OpenAI inpainting          | -           |\n| `--stream`    |       | Stream OpenAI partial-image events to stderr      | `true`      |\n| `--timeout`   |       | Max wait for the provider, e.g. `300s`, `10m`     | `5m`        |\n| `--open`      |       | Open the saved image                              | `false`     |\n| `--token`     |       | API key                                           | From env    |\n| `--help`      | `-h`  | Show help                                         | -           |\n\n## Provider Comparison\n\n| Feature           | OpenAI                 | Google (nano banana)             | Grok                |\n|-------------------|------------------------|----------------------------------|---------------------|\n| Env var           | `OPENAI_API_KEY`       | `GEMINI_API_KEY` / `GOOGLE_API_KEY` | `XAI_API_KEY` / `GROK_API_KEY` |\n| Default model     | `gpt-image-2`          | `gemini-2.5-flash-image`         | `grok-2-image`      |\n| Size control      | Yes (size flag)        | Aspect ratio only                | Provider-fixed      |\n| Quality control   | Yes (`low/medium/high`)| No                               | No                  |\n| Output formats    | PNG, JPEG, WebP        | PNG                              | PNG                 |\n| Multi-image (`n`) | Native (single request)| Looped (one per request)         | Native              |\n| Reference (`-i`)  | Yes (`/v1/images/edits`)| Yes (inlineData parts)          | Not supported       |\n| Mask (`--mask`)   | Yes (alpha channel)    | No                               | No                  |\n\n## Scripting Examples\n\n### Generate from a file of prompts\n\n```bash\nwhile IFS= read -r line; do\n  goimage -o \"prompt-$RANDOM.png\" \"$line\"\ndone \u003c prompts.txt\n```\n\n### Pipe from an LLM\n\n```bash\nllm \"describe a cover for a sci-fi novel about whales in space\" \\\n  | goimage -p google --aspect 9:16 --open\n```\n\n### Compare providers side-by-side\n\n```bash\nprompt=\"a single matte black coffee cup on white\"\ngoimage -p openai -o openai.png \"$prompt\"\ngoimage -p google -o google.png \"$prompt\"\ngoimage -p grok   -o grok.png   \"$prompt\"\n```\n\n### Build a contact sheet of variants\n\n```bash\ngoimage -n 9 -o variant.png \"isometric pixel art of a fountain\"\n# variant-1.png .. variant-9.png\n```\n\n## Streaming Progress (OpenAI)\n\nWhen the OpenAI provider is in use and `-n 1`, `goimage` opens an SSE\nconnection (`stream=true`, `partial_images=2`) and surfaces progress on\nstderr as the model renders:\n\n```\n$ goimage \"a watercolor of a fox in autumn leaves\"\nopenai: partial 1 received (3.2s)\nopenai: partial 2 received (8.4s)\nopenai: final image received (11.9s)\ngoimage-openai-20260528-104812.png\n```\n\nstdout still only carries the final file path, so pipelines keep working\nunchanged. Pass `--stream=false` to fall back to the non-streaming JSON\nendpoint (e.g. when scripting and you don't want progress lines).\nStreaming is automatically disabled for multi-image runs (`-n 2+`)\nbecause the SSE API returns a single final image.\n\nGoogle and Grok don't expose partial-image streaming, so `--stream` is a\nno-op for those providers.\n\n## Reliability\n\nTransient failures — network blips and 5xx upstream errors — are retried up to 3 times with exponential backoff (1s, 2s, 4s), so they don't require a manual rerun.\n\nA **client-side timeout** is treated differently. Every request runs under a single deadline (`--timeout`, default 5m) applied as a context deadline that covers the whole call, including the model's render time. If that deadline fires the model was almost certainly still rendering, and re-issuing the identical request would only fail the same way — so goimage reports it immediately (no wasted retries) with guidance: raise `--timeout`, lower `--quality`, use `--stream` to watch progress, or simplify the prompt. Image models can legitimately take minutes, especially at high quality, so prefer a generous `--timeout` over expecting a fixed ceiling.\n\nFailures are reported on stderr; the final file path is written to stdout so you can pipe it into other tools.\n\n## Error Handling\n\nWhen something goes wrong, an error is written to stderr and the process exits with a non-zero status:\n\n```\nError: OPENAI_API_KEY environment variable not set and --token not provided\nError: GEMINI_API_KEY environment variable not set and --token not provided\nError: XAI_API_KEY environment variable not set and --token not provided\nError: Invalid provider 'midjourney'. Use 'openai', 'google', or 'grok'\nError: --count must be \u003e= 1\nError: invalid OpenAI format \"bmp\" (expected png, jpeg, or webp)\nError: --timeout must be \u003e 0 (e.g. 300s, 10m)\n```\n\nA client-side timeout is reported with guidance rather than a raw transport error:\n\n```\nError generating image: the request timed out after 5m0s before the provider responded.\nThe image model was most likely still rendering — this is a client-side\ndeadline, not an API rejection, and re-running the same command unchanged\nwill hit the same deadline. Try one of:\n  - give it longer:      --timeout 10m\n  - make it cheaper:     --quality low   (or medium)\n  - watch live progress: --stream        (on by default for a single image)\n  - simplify the prompt, or lower --count\n```\n\n## Help\n\n```bash\ngoimage --help\n```\n\n## License\n\nMIT License\n\n## Contributing\n\nContributions welcome. Open an issue or PR on the [GitHub repo](https://github.com/schappim/goimage).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschappim%2Fgoimage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fschappim%2Fgoimage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschappim%2Fgoimage/lists"}