> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Image Input (Vision)

> The model SEES images you attach — in chat, coder, agent and the gateway channels. Native multimodal on vision providers, with an automatic describe-fallback for the rest.

Beyond **generating** images, ChatCLI lets the model **see and understand** images you attach — and answer based on them. It works in **chat, `/coder`, `/agent`, one-shot (`-p`)** and across the **gateway channels** (Telegram, WhatsApp, Slack, Discord, webhook).

***

## How to attach

Point `@file` at an image — it detects the type and attaches it as vision input (not inlined as text):

```text theme={"system"}
@file diagram.png what does this flow do?
@file ~/Downloads/error.jpg why does this stacktrace happen?
@file screenshot.png       # image only, no text, also works
```

Supported formats: **PNG, JPEG, GIF, WebP**. Local path or an image inside a directory. Images with the wrong extension are still detected by content (MIME sniff).

<Info>
  **Chat is tool-less by design** — attaching an image in chat works (it's an attachment, not a tool). To **generate/edit** an image, use `/coder` or `/agent` with the [`@image`](/features/image-generation) tool.
</Info>

***

## Hybrid strategy (B + A)

ChatCLI decides automatically, looking at the **active model's** `vision` capability in the catalog:

* **Vision model** (GPT-4o/4.1/5.x, **Claude** 3+/4.x, Gemini, Kimi, GLM, Bedrock Claude…) → the image goes **natively**, the model truly sees the pixels. *(Path B.)*
* **Non-vision model** → **describe-fallback**: a vision model describes the image and the text is folded into the prompt, so a text-only model can still reason about the content. *(Path A.)*
* **No vision model available** → a clear warning and the answer continues text-only (never breaks).

No variable is required — `@file image` just works. `CHATCLI_VISION_PROVIDER`/`CHATCLI_VISION_MODEL` only override the fallback captioner (e.g. `gpt-4o-mini` as a cheap captioner).

### Off-catalog vision models

Models fetched from a provider's `/models` API may have no catalog entry. The decision is **layered** (`CHATCLI_VISION_INPUT`):

1. **Override** `CHATCLI_VISION_INPUT=native|describe|off` — explicit control.
2. **Catalog** (`vision` capability) — authoritative for known models.
3. **Conservative heuristic** — if the **id** carries an unambiguous vision marker (`-vl`, `vl-`, `vision`, `pixtral`, `llava`, `internvl`, `qwen-vl`, `omni`, `multimodal`), treat it as **native**. Those names exist only on multimodal models → near-zero false positives.
4. Otherwise → describe-fallback.

The heuristic matches explicit markers only, **never family prefixes** (which have text-only exceptions like `claude-3-5-haiku`/`o3-mini`), so it never sends an image block to a model that would hard-error. Know your off-catalog model sees? `CHATCLI_VISION_INPUT=native`.

***

## Per-provider coverage (native vision)

Image serialization is done by a shared helper, across **6 dialects** covering the vision-capable providers:

| Dialect                 | Providers                                                                                |
| ----------------------- | ---------------------------------------------------------------------------------------- |
| OpenAI `image_url`      | OpenAI, xAI, Z.AI, OpenRouter, Copilot, GitHub Models, Moonshot, MiniMax, Bedrock-OpenAI |
| Anthropic blocks        | Anthropic (API-key + OAuth), Bedrock-Claude, MiniMax-Anthropic                           |
| Gemini `inline_data`    | Google Gemini                                                                            |
| Bedrock SDK             | Bedrock Converse                                                                         |
| Ollama `images[]`       | Ollama                                                                                   |
| Responses `input_image` | OpenAI Responses                                                                         |

The gate is generic: `catalog.HasCapability(provider, model, "vision")`. Text-only API providers (e.g. StackSpot) automatically fall back to describe.

***

## In the gateway (messaging channels)

**Receive an image** — send a photo on Telegram/WhatsApp/etc. and the gateway downloads it, then the configured model sees it (native or describe-fallback, same logic above). **Image-only** messages (no text) get a default analysis request.

**Send an image** — if the agent **generated/edited** an image during the reply (via [`@image`](/features/image-generation)), it is attached automatically to the reply on photo-capable adapters.

| Variable                          | Purpose                                                        | Default |
| --------------------------------- | -------------------------------------------------------------- | ------- |
| `CHATCLI_GATEWAY_IMAGE_REPLY`     | Attach a generated/edited image to the reply: `auto` / `never` | `auto`  |
| `CHATCLI_GATEWAY_MAX_IMAGE_BYTES` | Inbound image download cap (bytes)                             | 20 MB   |

***

## Configuration

```text theme={"system"}
/config integrations          # shows CHATCLI_VISION_*, CHATCLI_GATEWAY_IMAGE_REPLY etc.
```

| Variable                      | Purpose                                     | Default |
| ----------------------------- | ------------------------------------------- | ------- |
| `CHATCLI_VISION_INPUT`        | Mode: `auto`/`native`/`describe`/`off`      | `auto`  |
| `CHATCLI_VISION_PROVIDER`     | describe-fallback provider                  | (auto)  |
| `CHATCLI_VISION_MODEL`        | describe-fallback model                     | (auto)  |
| `CHATCLI_VISION_COMPRESS`     | Compress images before sending (`on`/`off`) | `on`    |
| `CHATCLI_VISION_MAX_EDGE`     | Longest-edge cap in px                      | `1568`  |
| `CHATCLI_VISION_JPEG_QUALITY` | JPEG re-encode quality (1–100)              | `82`    |

***

## Image compression (before sending)

When native vision is active, ChatCLI **shrinks the image** before sending it to the model — keyless and pure-Go (no new dependency, no cgo). It is part of [Context Compression](/features/context-compression):

* **Downscale** the longest edge to `CHATCLI_VISION_MAX_EDGE` (1568px). Providers already reduce larger images server-side to this size for token accounting, so this is **token-equivalent** — it just avoids uploading pixels that would be thrown away — and for images above the cap it **lowers the billed vision tokens**.
* **JPEG re-encode** of photos (quality `CHATCLI_VISION_JPEG_QUALITY`), far smaller than PNG, preserving transparency (alpha images stay PNG).
* **Safe by construction**: never inflates the payload and leaves formats it cannot round-trip (animated GIF, WebP) untouched. URL-only images pass through unchanged.

Disable with `CHATCLI_VISION_COMPRESS=off`.

***

## Notes

* Images cost **prompt tokens** (a large image can be worth hundreds/thousands of tokens). Confirm before attaching large batches on paid models.
* The image stays in history and is re-sent on subsequent turns (standard multimodal behavior).
* To force a specific fallback captioner: `CHATCLI_VISION_PROVIDER=openai CHATCLI_VISION_MODEL=gpt-4o-mini`.

***

## Related

* [Image Generation & Editing (@image)](/features/image-generation) — the model **creates/edits** images
* [Chat Gateway](/features/chat-gateway)
* [Voice Replies](/features/voice-replies)
