Read file contents with line numbers, limited to the personal workspace. This workspace-only variant rejects any path outside the workspace: dependency-source caches, temp spill files, `/tmp`, and other system paths are not accessible. Relative paths resolve from the workspace. Hard credential denials still apply: protected credential locations and private-key files (`id_rsa`/`id_dsa`/`id_ecdsa`/`id_ed25519`, `*.ppk`) are rejected even inside the workspace, while credential-bearing config files are readable but scrubbed for credentials. Files larger than 10 MB are rejected, except document containers, which are accepted up to 50 MB.
When the path is a directory, the tool lists its contents instead of returning an error. The directory listing groups subdirectories and files with sizes and an extension summary. Note that `mode`, `offset`, and `limit` parameters only apply to file reads — they are silently ignored when a directory is passed.
Modes:
- `content` (default): Outputs a file or a range (using `offset`+`limit`) with line numbers. Large outputs are truncated to a small budget (~5 KB) — for big files, read in slices with `offset`/`limit`, or navigate via `symbols`/`zoom`. Handles any file type; binary files are read with lossy UTF-8 conversion, except the document containers converted below and a background shell session's own output file (read as a program's output). When the path is a directory, lists the directory contents.
- `symbols`: Lists all AST-level symbols (functions, structs, impl blocks, etc.) with line ranges — the quickest way to map a large file's structure without reading it whole. Works for supported code formats only (Rust, JS/TS, Python, Go, C, Ruby, SQL, Markdown, JSON, TOML, CSS, HTML, shell), not arbitrary formats.
- `zoom`: Extract a single symbol's full source by name (requires `symbol` parameter). Same supported-formats limit as `symbols`. Use with the output of `symbols` mode to drill into specific definitions.
When a content-mode path is a raster image (PNG, JPEG, or WebP), the tool reads and attaches it to the conversation as a native image the model can inspect, instead of returning lossy text. Other binary formats that cannot be decoded (e.g. GIF, BMP, HEIC) are reported as unsupported.
When a content-mode path is a document container — a PDF, or a Word `.docx`/`.docm` (an encrypted one is reported as password-protected instead) — the tool converts it the same way an inbound chat attachment is converted, instead of returning its raw bytes. The extracted text is returned; when it is too long to inline, the tool writes it out to a file and reports that path. Pages without a usable text layer, pages whose text could not be read — the answer names those pages, so an unreadable page is never mistaken for one with nothing to read — and images embedded in a page, are attached to the conversation as images when there are at most 5 of them. With more, all of them are saved in a folder and listed by path, so you can read them individually; when even that listing would not fit the answer, the folder alone is named — list it to find them. `offset`/`limit` do not apply to a converted document. A document that yields neither text nor images, or whose conversion cannot run at all, is answered with a plain note saying so — never its raw bytes.