Skip to content

Documents and images

Parent: Tools and workspace.

Rho reads more than plain text. read_file and fetch_content share one bounded document extractor for PDFs and Office files. read_file also builds a safe image thumbnail for the interactive feed. The goal is the same in every path: give the model useful content without loading unbounded bytes or graphics into the session.

User paste and path drop use the same extractors. See attachments.

Supported inputs

KindFormatsTools
Text and sourceUTF-8 filesread_file, paste as document attachment
DocumentsPDF, DOCX, XLSX, XLS, ODSread_file, fetch_content, paste as document attachment
ImagesPNG, JPEG, GIF, WebPread_file (thumbnail), paste as multimodal image

offset and limit on read_file apply only to UTF-8 text and source files. They do not page through a PDF or spreadsheet.

How read_file chooses a path

  1. Open the file and read a short header.
  2. If the magic bytes match PNG, JPEG, GIF, or WebP, build an image preview.
  3. Else if the path or bytes look like a supported rich document, run the shared extractor and return rendered text.
  4. Else treat the body as UTF-8 text and return a hashline view for default edit chaining.

Rich documents are not editable source files. Use their extracted text to reason about them; write results back with write or the selected edit tool on real source files.

Document extraction

read_file and fetch_content call the same facade. Local paths and remote PDFs both use the pure-Rust path. There is no separate remote placeholder.

What comes back:

  • PDF - structured Markdown through pdf-inspector. Headings, lists, tables, links, and reading order are kept when the file has a text layer.
  • DOCX - extracted body text.
  • XLSX, XLS, ODS - bounded Markdown tables per worksheet.

Extraction warnings and truncation notices appear in the tool text as [document warning: ...] lines and in tool metadata. Truncation also appends a short extraction notice.

Limits

LimitValue
Source size25 MiB
Extracted text200,000 Unicode characters
Warnings kept per document20
Spreadsheet rows per sheet200
Spreadsheet columns per sheet40
PDF Flate stream expansion budget64 MiB total

PDF load preflights Flate stream expansion, including object and cross-reference streams, against that 64 MiB budget. Chained or unbounded stream filters are rejected. Image XObjects are not expanded on the text path.

Not included

  • OCR for scanned PDFs with no text layer (those files return a clear warning)
  • PPTX
  • Archive recursion or unpacking arbitrary zip trees as documents
  • Native provider document parts as a substitute for local extraction

Office and PDF parsers sit behind optional rho_tools features (document-pdf, document-docx, document-spreadsheets). The shipped Rho binary enables them.

Images

read_file detects images from magic bytes, not only from the file extension. It decodes on a blocking worker under strict limits, then shrinks the result to a bounded PNG thumbnail. That thumbnail is attached to the completed tool result, so a later change on disk cannot alter the preview the feed already showed.

LimitValue
Source image size for preview32 MiB
Decode width and height4,096 px each
Decode allocation80 MiB
Thumbnail box1,024 × 768

The model-facing tool text is a short summary such as image/png image (12345 bytes). The thumbnail is presentation for the TUI, not a second multimodal upload from the tool path. User-pasted images still use the provider multimodal path; see attachments.

Where thumbnails paint

EnvironmentBehavior
Kitty, GhosttyGraphics protocol preview in the feed
Herdr with paintable Kitty clientKitty placements through the host
Herdr without host cell metricsHalfblock preview so reserved rows are not blank
Persistent tmuxText fallback (no graphics probe; env can describe a stale client)
Other terminalsText tool result only; no graphics escape sequences

Capability detection stays conservative and does not probe terminal input. Image previews are presentation-only. Resuming a saved transcript does not restore them.

If preview fails (oversized file, decode error, worker failure), read_file still returns the text summary and records why the preview is missing. A file that looked like an image but decodes as UTF-8 text falls back to the hashline text view.