10efe85f381f5930f0e30dee5a61c8b74583c1b9
There is no native tool for this, and images are shell data like any other, so the surface is a bash function the model pipes into: curl -sL https://example.com/photo.png | see, or see path.png. The name reads as a sentence in the pipe position, keeps working as a plain argument for local files, and is one const in vision.rs if it ever needs to change. Two halves, joined by a staging directory. Provision writes the BASH_ENV init file one non-interactive bash sources; see() execs the rhema binary's hidden __vision mode, which sniffs magic bytes, stages them under a 0700 per-process dir, and says so on stdout. 5 MB per image (the strictest API ceiling), png/jpeg/gif/webp only, and a refusal exits 2 with the reason on stderr so the model reads the limit in-band rather than losing the bytes to a silent drop. Attach runs after every bash command that reaches an exit: ShellTools drains the staging dir into ToolResult.images, a new core field. Bytes never ride stdout, so output caps and truncation cannot eat them, and a staged image attaches even when the command failed. The model staged it, so it belongs in the context. The caps: 5 MB staged, 8 images per result, the rest named in the result's text, because a for loop staging 30 screenshots must not cost a context window. serde keeps the field default, so old checkpoints load unchanged. Anthropic carries native image blocks in the tool_result content array, text first. OpenAI-dialect tool messages (llama.cpp, Copilot, OpenRouter, DeepSeek) and Gemini carry text only, so each withheld image is named in a trailing note the model can act on. The transcript's byte accounting and summaries count the images; the coding-agent config carries the prompt section, and the render adds the section only when wired. Frontends provision only where their bash runs locally: the TUI's session_agent_config, the headless one-shot, the ACP adapter, the claw's daemon, the same gate the MCP wire applies, because a session whose bash runs elsewhere cannot write where the drain reads. The vision wiring lands before the MCP wire so BASH_ENV names the MCP file last and its baked predecessor line reaches the vision init; both functions end up defined. Subagent inner shells inherit the parent's wiring, so a spawned agent keeps the macro in its own commands. SPEC's decision bullet, AGENTS.md's scope line, and the README row land with the feature.
Languages
Rust
74.9%
Kotlin
13.8%
Vue
7.1%
TypeScript
3%
Dockerfile
0.5%
Other
0.6%