Potaco is a Go CLI for image generation and editing via multiple AI image providers. Connect to OpenAI, fal, Replicate, or any OpenAI-compatible API via the custom provider.
Warning
This project is still in beta. Therefore, critical breakages or bugs are to be expected. Use at your own risk, and please report any issues you encounter.
- Multi-provider support for OpenAI, fal, Replicate, and custom OpenAI-compatible endpoints
- Encrypted credentials stored locally
- Auth management with
auth add/remove/listcommands - Provider switching with
potaco use <provider> - Model discovery via provider APIs
- Generate images from text prompts with size, quality, seed, and guidance control
- Edit existing images with inpainting (mask-based) and outpainting (canvas extension)
- Status and models commands to inspect current state and available models
- Stats dashboard for local command analytics and estimated spend
- Interactive TUI with hand-crafted prompts for auth, model selection, and provider switching
- Retry with exponential backoff on rate-limit and server errors
- JSON output for scripting and piping
- Dry-run mode to validate requests without calling the API
- Non-interactive mode with
--non-interactiveflag for agents and automated terminal execution
curl -fsSL https://github.com/ncxton/potaco/releases/latest/download/install.sh | shThe installer detects your platform, downloads the matching binary, verifies the checksum, and installs to ~/.local/bin.
curl -fsSL https://github.com/ncxton/potaco/releases/latest/download/install.sh | POTACO_NON_INTERACTIVE=1 shNon-interactive installer mode is plain output for agents and automated terminal execution, not a polished scripting API.
Download the archive for your platform from the releases page, extract, and move the potaco binary to a directory in your PATH.
Supported platforms:
- Linux x86_64 (amd64)
- Linux ARM64 (arm64)
- macOS Intel (darwin/amd64)
- macOS Apple Silicon (darwin/arm64)
# Connect a provider (hand-crafted TUI prompts for key, verification, and model)
potaco auth add openai
# Or non-interactive:
potaco auth add openai --api-key sk-xxx
# Generate an image
potaco gen --prompt "a red fox in a forest"
# Switch to another provider
potaco auth add fal --api-key <fal-key>
potaco use fal
# List or pick available models from the active provider
potaco models # interactive picker (persists the selected model)
potaco models list # discovered model list
potaco models list openai # discovered list for a specific provider
# Check current status
potaco statusGenerate new images from a text prompt.
| Flag | Type | Required | Default | Description |
|---|---|---|---|---|
--prompt, -p |
string | yes | Text description of the desired image(s) | |
--model |
string | no | from config | Model to use (e.g., gpt-image-2) |
--size |
string | no | from model config | Override image dimensions (WxH) |
--quality |
string | no | from model config | Override image quality (low, medium, high, or auto) |
--n |
int | no | from model config | Override number of images to generate |
--seed |
int | no | from model config | Override reproducibility seed |
--guidance-scale |
float | no | from model config | Override guidance scale |
--negative-prompt |
string | no | from model config | Override negative prompt |
--response-format |
string | no | from model config | Override response format (url or b64_json) |
--output, -o |
string | no | auto | Output file path (auto: potaco-YYYYMMDD-HHMMSS.png) |
--output-format |
string | no | png |
Output format (png or jpeg) |
--stdout |
bool | no | false |
Pipe raw image bytes to stdout |
--dry-run |
bool | no | false |
Print request payload without calling API |
--json |
bool | no | false |
Output JSON metadata to stdout |
--provider |
string | no | from config | Override active provider |
--base-url |
string | no | from provider | Override API base URL |
--api-key |
string | no | from credentials | Override API key |
--retries |
int | no | 2 |
Max retry attempts |
--timeout |
string | no | 120 |
Request timeout in seconds |
Examples:
potaco gen --prompt "a red fox in a forest"
potaco config set model.parameters.size 1536x1024
potaco config set model.parameters.quality high
potaco gen --prompt "a cityscape at night"
potaco config set model.parameters.seed 42
potaco gen --prompt "portrait of a woman" --json
potaco gen --prompt "portrait of a woman" --size 1024x1792 --quality medium
potaco gen --prompt "test" --dry-run
potaco gen --prompt "test" --provider fal --api-key <key> --dry-runWhen no provider, API key, or base URL override is supplied, generation can fall back to another configured provider with the same or similar model ID after a transient provider failure such as a rate limit, timeout, or server error. Fallback providers are tried after the active provider in A-Z order.
Edit an existing image with inpainting (mask-based editing) or outpainting (canvas extension).
| Flag | Type | Required | Default | Description |
|---|---|---|---|---|
--prompt, -p |
string | yes | Text description of the edit | |
--image |
string | yes | Path to source image file | |
--mask |
string | no | Path to mask image file (transparent=edit, opaque=keep) | |
--mask-rect |
string | no | Rectangular mask: x,y,w,h in pixels |
|
--mask-circle |
string | no | Circular mask: x,y,r in pixels |
|
--extend |
string | no | Outpaint: top=N,bottom=N,left=N,right=N or all=N |
|
--model |
string | no | from config | Model to use |
--size |
string | no | from model config | Override image dimensions (WxH) |
--n |
int | no | from model config | Override number of images to generate |
--response-format |
string | no | from model config | Override response format (url or b64_json) |
--output, -o |
string | no | auto | Output file path |
--output-format |
string | no | png |
Output format (png or jpeg) |
--stdout |
bool | no | false |
Pipe raw image bytes to stdout |
--dry-run |
bool | no | false |
Print request payload without calling API |
--provider |
string | no | from config | Override active provider |
--base-url |
string | no | from provider | Override API base URL |
--api-key |
string | no | from credentials | Override API key |
--retries |
int | no | 2 |
Max retry attempts |
--timeout |
string | no | 120 |
Request timeout in seconds |
Examples:
potaco edit --prompt "make it look like a painting" --image photo.png
potaco edit --prompt "remove the person" --image photo.png --mask mask.png
potaco edit --prompt "replace with a tree" --image photo.png --mask-rect 100,200,300,300
potaco edit --prompt "extend the landscape" --image photo.png --extend right=256,bottom=256edit only runs when the selected model is configured as edit capable. Interactive model selection asks this after you pick a model. For non-interactive setup, set it yourself after confirming provider support:
potaco config set model.edit true
potaco config set providers.openai.models.gpt-image-2.edit trueEdit requests use the same transient fallback behavior as generation, but only to configured providers whose matching model is marked edit capable.
Connect providers, add API keys, and manage credentials. Credentials are encrypted at rest.
potaco auth add openai # interactive TUI flow
potaco auth add openai --api-key sk-xxx # non-interactive
potaco auth add fal --api-key <key> # connect fal
potaco auth add replicate --api-key <key> # connect Replicate
potaco auth add custom --api-key <key> --base-url <url> # connect any OpenAI-compatible endpoint
potaco auth add openrouter --type openai --api-key <key> --base-url <url> # named OpenAI-style endpoint
potaco auth add staging-openai --type openai --api-key <key> --base-url <url> # named provider using a built-in adapter type
potaco auth remove openai # disconnect a provider
potaco auth list # list connected providers
potaco auth list --json # JSON outputSwitch the active provider and optionally change the model.
potaco use openai # switch to openai
potaco use fal # switch to fal
potaco use openai --model gpt-image-2 # switch and set modelWhen run interactively with no arguments, a TUI picker appears.
Display the active provider, model, config and credential paths, and connected providers.
potaco status # text output
potaco status --json # JSON outputShow a local analytics dashboard for command count, duration, errors, providers, recent runs, and estimated cost. Interactive terminals get a btop-style dashboard; non-interactive shells get a plain text report.
potaco stats # interactive dashboard
potaco stats --non-interactive # plain text fallback
potaco --json stats --non-interactive # JSON summary
potaco stats --clear # clear local stats historyDashboard keys: tab switches focused panel, r refreshes, c clears local stats, and q or ctrl+c closes. Cost is estimated from OpenRouter model pricing when available.
Discover models from the active provider or a specified provider. By default, the command launches an interactive picker that persists the selected model to config and asks whether it can edit images. In non-interactive mode it prints the discovered model list without changing selection.
potaco models # interactive picker with Custom option for the active provider
potaco models openai # interactive picker with Custom option for a specific provider
potaco models --non-interactive # discovered list by display name for the active provider
potaco models list # discovered list by display name for the active provider
potaco models list openai # discovered list by display name for a specific provider
potaco models --json --non-interactive # JSON outputUse potaco models list when you only want to see available models without changing the active model. Interactive pickers include a bottom Custom option for manually entering a model ID and display name. Custom display names are saved with a [Custom] suffix. Model discovery does not configure or display generation/edit capability; generation is assumed available, and edit capability is user-configured.
Manage per-provider settings stored in ~/.potaco/config.yaml. API keys are stored separately in the encrypted credential file.
potaco config set model gpt-image-2 # change active provider model
potaco config set providers.replicate.model black-forest-labs/flux-schnell # set a provider model
potaco config set model.edit true # mark active provider model edit capable
potaco config set providers.openai.models.gpt-image-2.edit true # mark a specific model edit capable
potaco config set model.parameters.size 1536x1024 # set active model image size
potaco config set model.parameters.quality high # set active model quality
potaco config set model.parameters.n 2 # set active model output count
potaco config set model.parameters.response_format url # set active model response format
potaco config set model.parameters.seed 42 # set active model seed
potaco config set model.parameters.guidance_scale 7.5 # set active model guidance
potaco config set model.parameters.negative_prompt blurry # set active model negative prompt
potaco config set base_url https://api.example.com/v1 # set active provider base URL
potaco config set retries 3 # set active provider retries
potaco config set timeout 120 # set active provider timeout in seconds
potaco config set auto_update false # disable automatic update prompts
potaco config show # print raw config.yamlGeneration and edit parameters are stored per model under providers.<name>.models.<model>.parameters. Command flags such as --size, --quality, and --response-format still work and override the model configuration for that run. potaco edit warns when generation-only parameters such as quality, seed, guidance_scale, or negative_prompt are configured but not applied to edit requests.
Print the current binary version and check for updates. Interactive commands check for updates automatically by default; disable that with potaco config set auto_update false.
potaco version
potaco version --json
potaco --versionDownload and run the installer for the latest release.
potaco update # update if newer version available
potaco update --force # force update even if already latestRemove the potaco binary. Interactive uninstall asks whether to remove local configuration.
potaco uninstall # interactive removal
potaco uninstall --yes # skip confirmation promptsDisable interactive TUI flows and automatic update prompts. Useful for agents and automated terminal execution, not a polished scripting API. Can also be set via the POTACO_NON_INTERACTIVE=1 environment variable.
potaco --non-interactive auth add openai --api-key sk-xxx
POTACO_NON_INTERACTIVE=1 potaco modelsPotaco stores configuration in ~/.potaco/config.yaml and encrypted credentials in ~/.potaco/credentials.enc.
Config file format (~/.potaco/config.yaml):
active_provider: openai
active_model: gpt-image-2
auto_update: true
providers:
openai:
model: gpt-image-2
base_url: https://api.openai.com/v1
retries: 3
timeout: 120
fal:
model: fal-ai/flux/dev
base_url: https://fal.run
retries: 3
timeout: 120The base_url field is optional for built-in provider names (openai, fal, replicate) and overrides their preset URL. It is required for any other provider name, including custom and aliases that use a built-in adapter type. Base URLs must be full http:// or https:// URLs; interactive flows warn before continuing with unencrypted http:// endpoints.
API keys are stored separately in ~/.potaco/credentials.enc, encrypted with a machine-derived key.
Update check metadata is stored separately in ~/.potaco/.potaco.json.
Environment variables:
| Variable | Description |
|---|---|
POTACO_PROVIDER |
Active provider name (e.g., openai, fal, replicate, custom) |
POTACO_API_KEY |
API key for the active provider |
POTACO_MODEL |
Default model for the active provider |
POTACO_BASE_URL |
Override the provider's base URL (required for custom and provider aliases) |
POTACO_RETRIES |
Max retry attempts |
POTACO_TIMEOUT |
Request timeout in seconds (e.g., 120) |
POTACO_NON_INTERACTIVE |
Set to 1 to disable TUI flows for agents and automated terminal execution; not a polished scripting API |
Supported providers:
The known provider names below ship with preset base URLs. Any other auth name, including custom and aliases using a built-in adapter type, requires --base-url or base_url in config.
| Provider | Auth Type | Edit Support |
|---|---|---|
openai |
Bearer | Yes |
fal |
Key | Yes |
replicate |
Bearer | No |
Replicate model discovery is not automatic; configure an image model ID manually in owner/model format, for example potaco config set model black-forest-labs/flux-schnell.
See CONTRIBUTING.md for development setup, coding standards, and the pull request process.
Every PR runs: build, go vet, gofmt, staticcheck, gocyclo (complexity threshold 30), go mod tidy, coverage, gitleaks (secret scanning), and tests.
sh scripts/install-hooks.sh # Install gofmt, vet, tidy, and test hooksSee .env.example for a template of all supported environment variables.
MIT - Copyright (c) 2026 ncxton
