- Documentation
- Explanation
- The drawer
Explanation
On this page
The drawer¶
The right-hand drawer is where anything a chat opens beside itself lives: an app the coder built, a saved artifact, a delivered file, the chat's files, the code review. It used to be three drawers that forgot what they showed when closed; it is one now, with a tab per thing. This page explains the choices behind it.
One tab per thing, per chat¶
A tab is keyed by what it shows — an artifact snapshot, a workspace app, a file, the code review — so opening the same thing again focuses its tab instead of adding one, and a files tab that navigates onto a file another tab shows takes that tab's place. Tabs belong to the chat they were opened in and are remembered in the browser's storage with the chat's id: after a reload they come back closed, the header's drawer button shows their count, and a deleted chat's tabs are forgotten. One file saved in two tabs by an earlier build comes back as one tab; tabs that only look alike, such as files of the same name in two folders, stay.
The drawer reads a file before it shows it, whatever its kind — text, sheet, image, PDF or Office document — so what it says about a file is what that read found. A tab whose file no longer exists says so rather than pretending: it shows the workspace's files with a line naming the missing file, whatever the drawer showed before, and Refresh tries the file again. The same happens when a file that is shown is deleted and the drawer is refreshed. A file that is there but that the drawer cannot display, such as an image the browser cannot decode, stays open with its Open with and Open in folder actions and one line saying so; the reason goes to the error log.
A saved artifact's files open in a files tab of their own, from the artifact's own copy: what the tab shows, and its Open in folder and Download, are the artifact's, never a file of the same name in the chat's folder. Those files are the artifact's snapshot and stay read-only, so the drawer offers no Open with for them: an application opened on one could save into the artifact outside its saves and their verification. Download gives a copy that opens anywhere.
Ten tabs at most; the eleventh closes the least recently viewed one and the status line says so. Closing the last tab closes the drawer; closing the drawer keeps every tab.
One app running at a time¶
An app in a tab is a real running program — a workspace app with its own server-side lease — and several would compete for the machine. So only the shown tab's app runs; a tab that is not shown keeps its container but releases its runtime (the server stops the app after a grace period), and its pill shows a dot. Showing it again relaunches it. Nothing runs while the drawer is closed. This is also why a reopen during the closing animation has to cancel the close's completion step: otherwise the close would stop the app the reopen just launched.
Refresh on reopen; resume when selected¶
Opening a card whose tab already exists — a rebuilt app, say — refreshes that tab from the current files. Switching selects the existing tab rather than creating a new one, but an app whose runtime was released must start again. Do not rely on unsaved in-app state surviving a close or switch.
Files and code changes are panes of the same drawer¶
A delivered file opens as a file tab with the file pill's own icon and name, showing the files pane on that workspace and path; the code review is one changes tab per chat. The drawer's own close, expand and resize controls serve every pane, and its opening motion runs once: a pane paints its light header on the opening frame and its cached body when the motion finishes, so a heavy file tree or diff never fights the animation. Sources stayed a separate drawer on purpose: it belongs to an answer, not to the chat, and is read differently.
Why¶
- Remembering tabs per chat, and refreshing on reopen rather than on switch, were explicit owner decisions: the card in the transcript should be a way back to the same thing, and switching tabs should be free.
- One running app at a time keeps the drawer honest about resources without hiding anything: the dot says an app is stopped, and showing it starts it.
- One drawer with panes removed three sets of open/close/resize/expand rules and three theme framings, and made the header button one thing that means "what this chat has open".
Evidence: docs/drawer-tabs-2026-09-19.md in the source tree, with the live test that drives the real server through every rule above.