Repository navigation
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Problem
When Claude sends files with the SendUserFile tool, herdr-web-ui shows only the raw tool call and its text output. The files can't be seen or opened from the web UI. This happens in both modes:
Terminal mode: the caption and plain-text local paths:
⏺ <caption text>
› [image] /private/tmp/claude-<uid>/<project-slug>/<session-id>/scratchpad/image-a.png (258.6KB)
› [image] /private/tmp/claude-<uid>/<project-slug>/<session-id>/scratchpad/image-b.png (491.8KB)
Chat mode: a collapsible JSON block plus a text output:
{
"files": [
"/private/tmp/claude-<uid>/<project-slug>/<session-id>/scratchpad/image-a.png",
"/private/tmp/claude-<uid>/<project-slug>/<session-id>/scratchpad/image-b.png"
],
"caption": "<caption text>",
"status": "normal",
"display": "render"
}2 files delivered to user.
/private/tmp/.../scratchpad/image-a.png → file_uuid: <uuid-a>
/private/tmp/.../scratchpad/image-b.png → file_uuid: <uuid-b>
SendUserFile exists to put a result (screenshot, rendered preview, report) in front of the user, often when they follow the session from another device. In the web UI the user only gets a local path, which they can't open from a phone or a remote browser.
Proposal
Render SendUserFile calls as a proper message instead of raw JSON:
- Caption shown as normal message text.
- Images (
png,jpg,gif,webp,svg) shown as inline previews when"display": "render"is set. Clicking one opens the full-size image. - Other files (PDF, HTML, text, archives…) shown as a clickable chip with the file name and size, which opens or downloads the file.
- Raw tool input/output kept in a collapsed "details" section.
- Terminal mode: turn the
› [image] <path>lines into links (or show a preview on hover/tap).
Implementation notes:
- The tool input already has everything needed:
files[],caption,display. The output maps each path to afile_uuid, which could serve as a stable ID for a route such as/files/<file_uuid>. - herdr-web-ui already stores and shows pasted images (
.herdr-web-ui/paste-*.png), so that serving path could probably be reused. - Security: only serve paths that actually appeared in a
SendUserFilecall of the current session. No general "serve any local path" endpoint. Resolve symlinks and reject..before checking. - Scratchpad files under
/private/tmp/...may disappear after the session ends or after a reboot. Show a "file no longer available" placeholder instead of a broken image.
Where
Chat and prompt cards
Workarounds and alternatives
Current workarounds
- Copy the path from the tool output and open it locally (
open <path>on macOS). This only works on the machine running the agent, not from another device. - Ask Claude to publish the content in another form (e.g. a hosted artifact/page) and share the link. This works, but it's an extra step and it's no longer the file itself.
- Have Claude copy the file into a folder synced to the other device. This is manual, slow, and clutters the project.
Alternatives considered
- Links only, no inline preview: simpler and still fixes the core problem. Inline image previews could come later.
- Copy files into
.herdr-web-ui/when the tool is called: keeps them available after the scratchpad is cleaned up, but uses disk space and needs a cleanup policy. - Generic local file browser in the web UI: much more powerful, but a far bigger security surface. Limiting access to the files Claude explicitly sent is the safer choice.
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity