Claude Code has GUIs now. Here's what one should actually do.
Claude Code is no longer terminal-only. There is a desktop app for Mac and Windows, claude.ai/code in the browser, VS Code and JetBrains extensions, and a growing pile of community GUIs. Nearly all of them do the same thing: render the conversation. That is the easy problem.
The hard problem is supervising work you cannot see, and a chat window does nothing for it.
Search claude code gui and the community projects converge on one shape: a web app, a sidebar of sessions, a message list, a text box. It is a reasonable instinct. Chat is the interface you experience, so a chat window feels like the missing surface.
That instinct is wrong, and the reason is worth spelling out.
the terminal is already good at the thing a chat skin improves
Reading one agent’s output is the part that already works. Claude Code renders markdown, diffs, tool calls, and progress in the terminal, and it renders them well. Putting that same stream in a browser gets you selectable text, a nicer font, and maybe an image in the transcript. Those are worth something, and not very much.
Meanwhile the browser version usually costs you the thing the terminal is uniquely good at: being a shell. Your agent is running git, npm test, a migration, a deploy. When something goes sideways you want to be in that directory, running the command yourself, checking the branch. A chat window is a chat window. It has one input, and the only thing it talks to is the model.
So the trade a chat-shaped Claude Code GUI offers is: slightly nicer rendering, in exchange for the shell. That is a bad trade, and it is why so many people try one of these and go back to the terminal within a week. The IDE extensions dodge part of it, since an editor at least has a terminal pane and your files. They inherit the other half of the problem, though, because an editor window is built around one project and one buffer of attention.
what you are actually doing when you “watch” an agent
Sit with the real behavior for a second. When you have an agent running, you are not reading. You are checking.
You glance at the window. Is it still going? Has it stopped? Did it stop because it finished, or because it is sitting on a permission prompt waiting for a keystroke you did not know it wanted? Then you switch to the second window and do it again. Then the third.
That loop is supervision, not conversation. And it has a specific failure mode: an agent blocked on approval looks exactly like an agent thinking. Same still screen, same absence of output. The only difference is that one of them is burning your wall-clock time doing nothing. With one agent you notice within a minute. With four you find one that has been parked for twenty.
Add a second failure mode: the agent tells you it is done and gives you a summary. The summary is a claim. What it actually did is a sequence of tool calls, and those are the evidence. If your surface shows you the paragraph but makes the tool calls hard to inspect, it has optimized for the thing you should trust least.
And a third: cost. Sessions are not free, and by the time it shows up on a bill you have no idea which agent, on which task, on which day, spent the money.
None of those three are rendering problems. You cannot fix any of them by moving the transcript into a browser.
a GUI worth having is an operations view
The useful frame is not “chat app”. It is closer to htop, or a CI dashboard, or the panel a build system gives you when twelve jobs are running: a view over a set of processes, where the conversation is one thing you can drill into rather than the whole interface.
Concretely, four things.
State across the set. Not “is this window busy” but which sessions exist, which are mid-turn, which finished ten minutes ago and are idle, and which one you forgot about. This has to be visible without focusing any individual session, because the entire point is to stop cycling through tabs.
Blocking, surfaced. The moment an agent needs an approval, that should reach you as a distinct signal, attributed to the project and session that asked. Not a screen you have to be looking at to see. This is the single highest-value thing a supervisory surface can do, and it is the one a chat skin structurally cannot do, because it only knows about the session you currently have open.
Evidence, not summary. Every tool call the agent made, with its input and its result, browsable after the fact. When you review agent work you are checking claims against actions, so the actions need to be a first-class view and not something buried in a collapsed block three thousand lines up. Same for history: transcripts should be searchable by the thing you actually remember, which is a filename or an error string, not a session ID.
Cost, attributed. Tokens per turn, per session, per model, visible while the session is alive and still there after it closes. Otherwise “which of my agents is expensive” is unanswerable.
Notice that all four are about the set, and about time. They are questions a chat window is not shaped to answer, because it is shaped around one conversation happening right now.
the test
Here is a quick way to judge any Claude Code GUI, including the one you are thinking of building:
What does it show you when no session is on screen?
If the answer is “nothing, it’s a chat window”, it is a rendering layer. It will be pleasant with one agent and useless with four. If the answer is a list of sessions with their state, what is blocked, what changed, and what it cost, it is an operations view, and it gets more useful as you add agents rather than less.
The second test: can you still run a command? An agent’s work lands in a repo. If the surface cannot run git diff, it has put a window between you and the thing you are supposedly supervising.
why this is where crystl landed
I build crystl, so treat this as a disclosed bias. But the design followed from the argument above, not the other way round.
crystl is a macOS terminal, so the shell never goes away. Every session is a real Claude Code session running the real CLI, with git, tests, and builds available in the same place. What it adds is the operations layer:
- Approvals arrive as floating panels, color-coded by project, so a blocked agent interrupts you instead of waiting silently. A session parked on an in-terminal prompt is flagged
⏸ awaiting inputincrystl statusand streams overcrystl events, which is the difference between “quiet” and “done”. - An agent activity panel shows live activity and token usage across every open project at once, which is the “what is running” view.
- A history navigator splits each session into Conversation and Tools tabs, so the tool calls are a view rather than an archaeology exercise.
Cmd+Shift+Fsearches every agent turn and every shell command across all projects, open and closed sessions, from a local index. - Per-turn token usage, model, and duration on every turn, with a session summary on top.
- Projects and sessions have names, so a fan-out of four agents reads
parser,tests,api,docsrather than four identical tabs.
The pieces that matter most are agent-neutral, because the problem is not Claude-specific. Codex and Antigravity CLI sessions run in the same window, land in the same timeline search index, and come back from the same undo-close list. The history navigator is the Claude Code specific piece, because it parses Claude Code’s transcript format.
the shorter version
Anthropic’s own surfaces, the desktop app and the web app and the IDE extensions, are all built around one conversation at a time, which is a fair reading of what most people need. The gap they leave is not rendering. It opens the moment you run a second agent, and it is made of state, blocking, evidence, and cost.
If you are evaluating what to install, start with what a UI for Claude Code should show you, or the desktop app versus terminal question if that is the fork you are at. If your actual problem is that you cannot find the session you had yesterday, that is a session manager problem, and it has a different answer.
Build the operations view. The chat window is already fine.