JetBrains / JetBrains/thinkrail
Opening an image file shows a Monaco buffer of its bytes instead of the picture
- Dominant language
- TypeScript
- Stars
- 478
- Forks
- 37
- Avg merge
- 1d 52m
- Merged PRs (30d)
- 143
Description
## Description
Double-clicking a PNG (or JPEG, GIF, WebP, SVG, BMP, ICO, AVIF) in the Files tree opens a read-only Monaco editor filled with the file's binary decoded as UTF-8: a wall of replacement characters and stray glyphs. There is no way to actually look at the image from inside ThinkRail, even though the host already streams a worktree file's raw bytes over `GET /files//` for relative images in the markdown viewer.
Every extension goes through `fs.readFile` in `openFileInTab` / `FilePane`, which reads the file as text and ships it to the tab as `tab.content`. For an image that content is useless, and the round trip is wasted on every open and every `fsChanged` refresh.
My personal use case: I wanted to generate a Mermaid diagram to share and wanted to look at the result.
## Steps to reproduce
1. Open a project whose worktree contains an image, e.g. `logo.png`.
2. Switch to the Files tab and double-click the image.
## Expected behavior
The tab renders the picture: an `` pointed at the `/files/…` route, natural dimensions shown somewhere, and zoom controls. When an agent or an external tool rewrites the file (including delete-and-rename, as exporters do), the tab reloads the new pixels in place without reopening.
## Actual behavior
A Monaco editor opens with the decoded bytes as text. The tab is read-only, has no image, and the markdown chrome is absent, so nothing on screen says the file is a picture.
## Environment
- OS: macOS 26.6.2
- Bun version (`bun --version`): 1.4.0
- Node version (`node --version`): v26.8.1
- ThinkRail version / commit: reproducible on `main` at 127a8cef
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Contributor guide
Research direction
Trace image handling from openFileInTab and FilePane, then inspect the existing GET /files// route used by the markdown viewer. Check how fsChanged refreshes an open tab, including delete-and-rename updates. Done means supported image extensions render pixels with dimensions and zoom controls, refresh in place, and no longer load binary data into Monaco.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100