Skip to main content
Type @path anywhere in a message to hand Ziro a file or folder. Ziro reads it for the model before its first step, so you do not have to wait for a tool call. Example: explain @src/app.py and @docs/shot.png.

Syntax

  • @path or @"path with spaces".
  • The @ must be at the start of the input or after whitespace, so an email address or user@host stays plain text.
  • A path that does not exist stays literal text. Nothing is attached and nothing is reported. The exception is a quoted path with no closing quote (the picker leaves @"my dir/ open while you drill down): it stays text with a notice.
  • Several references per message are fine, up to max_refs_per_turn (default 20). Extra references stay as text and a notice says so.
  • deny_paths entries (secrets, policy files, .git) and gitignored paths are refused with a notice.
  • A path outside the project (absolute, ~/... or ../...) works for media files: @~/Pictures/shot.png, @C:\Users\me\Desktop\shot.png. Text files and folders outside the project are refused with a notice, because the agent can only read inside the project. A project file that is a symlink to somewhere outside is refused too. Network paths (\\server\share\...) are always refused, without contacting the server. This works where you type the message yourself: the TUI, the plain REPL, and -p "<message>". Piped -p input, queued jobs and the Python SDK stay limited to the project, because their text may come from someone else.

Picker

Typing @ in the TUI opens a fuzzy picker over the project’s files and folders. It reads git ls-files (falling back to a directory walk) and never lists gitignored or denied entries. While the picker is open, Enter selects instead of sending. The plain REPL and -p parse @ references but have no picker. Dropping a file onto the terminal window inserts it as an @ reference (project-relative inside the project, the full path outside it). Pasted text that is not a list of existing file paths is inserted as is. Paths that VS Code formats for PowerShell (& 'C:\...'), Git Bash (/c/...) or WSL (/mnt/c/...) are recognized too. To paste a screenshot straight from the clipboard, press Ctrl+V (or Alt+V, if your terminal keeps Ctrl+V for itself). The image is saved as a PNG in a private ziro-paste folder (your temp directory on Windows, ~/.cache on Linux and macOS) and inserted as an @ reference; files copied in Explorer or Finder are inserted as their paths. Saved images older than a day are removed on the next paste. On Linux this needs wl-paste (Wayland) or xclip (X11).

What the model gets

If the agent has no filesystem tools, the content is inlined into the message instead. If a deny permission covers read_file, the reference is refused with a notice. The model receives media only if it accepts that kind. Otherwise it gets a text stub naming the file, and for PDF and Office files the skill to use. Switching models mid-thread re-filters history, so images come back when you move to a vision model. The agent’s own read_file on a media file returns the media too. On Office and other binary files it returns a stub naming the skill to use. Media bytes are stored per thread under the data directory (media/<thread>/) and deleted with the thread.

Provider support

When the capability is unknown, Ziro sends the media anyway. If the provider rejects it (HTTP 400 or 422 that is not a context overflow), the turn is retried with the media as text, with the notice model rejected media; sent as text. That model and kind is remembered for the rest of the thread.
Not yet verified on providers that strictly validate tool-call history, such as Gemini 3 models that require a thought signature on every tool call. The synthetic read_file round for a text or folder reference carries no signature, so such a provider may reject the whole request with HTTP 400. If that happens, reference media only, or paste the text into the message.
To declare what a custom provider accepts, set input_modalities in ~/.ziro/custom_providers.json ($ZIRO_HOME/custom_providers.json when ZIRO_HOME is set):

Files outside the project

Reference outside media directly with @, as above, at any point in the conversation. You can also drag a file onto the terminal window: the TUI turns the dropped path into an @ reference. --attach <path> does the same from the command line, in an interactive session or with -p. It is repeatable and applies to the first message.
Outside the project only media files are accepted. Inside the project the gitignore and deny rules apply as for @. The old /img command is gone; typing it prints a notice that points you to @path.

Notices

Anything Ziro skips, refuses, or downgrades produces a notice:

Configuration

attachment_policy.yaml (the attachments section): The legacy max_image_bytes field is still read at runtime and sets the image cap; ziro config doctor flags it and asks you to move it to max_bytes.image. The other pre-@ fields (allowed_image_types and the *_notice texts) are ignored. allowed_image_types no longer narrows anything: every image type Ziro recognises can be attached. Any other unknown key is ignored with a warning.