Editor guide
Chat
The agent panel in the Editor: parallel chat sessions, the model and effort picker, and what the agent knows about your design system.
The Chat tab in the right rail is a conversation with an agent that can read your repo, look at the page you are on, and edit your source. It is not a separate mode: it edits the same working tree the inspector does, and its changes land as ordinary uncommitted file changes exactly like every other Editor edit. See branch mode for what that means for saving.
Asking for something#
Type in the box at the bottom and press Enter. Shift+Enter inserts a newline instead of sending. The box never locks: you can type and press Enter at any point, including while the agent is still working on something you asked earlier. Your message goes to the agent right away. The agent decides what to do with it: answer it now, finish what it was doing first, or fold it into the current plan. You never have to stop the agent to talk to it.
While a turn is running, a Stop button appears next to Send rather than replacing it, so you can send a new message without stopping the agent first.
If a turn ends before the server can confirm your message actually reached the agent (you pressed Stop, the connection dropped, or the request never got an answer), Editor resends it for you automatically. A row above the input reads:
Resending “your message”. The previous turn ended before this could be confirmed.
while that happens, and clears itself once the resend lands.
If you have an element selected in the prototype, it shows as a badge next to the input: the component name, or "N selected" when several elements are pinned. The agent can read that selection, so "make this wider" works without describing which thing you mean. Click the × on the badge to detach the selection from the conversation.
You can attach images. Use the + button, paste, or drag an image anywhere over the input. Pending images show as thumbnails above the text.
While the agent works, the panel shows what it is doing right now (for example, "Reading App.vue…", "Editing Button.vue…", "Searching…") rather than an anonymous spinner.
Chats are conversations, not workspaces#
This is the single most important thing to understand about the panel, and it is the opposite of what "session" implies in some other tools.
A chat is a conversation thread, persisted per repo at .desde/chat-sessions/<id>.json. That is all it is. Every chat edits the same files. There is no per-chat branch, no per-chat copy of your code, no isolation of any kind. Two chats open at once are two conversations with two separate memories, pointed at one working tree.
So if you ask chat A to restyle Button.vue and then ask chat B to restructure the same file, B is writing over what A did, and B does not know A exists.
The overwrite warning#
The Editor detects the common version of this. Before the agent writes a file it has read, it compares the file on disk against what it saw when it read it. If the bytes changed in between, the write still goes through, and a banner appears above the input:
Heads up: this edit to
src/components/Button.vuewrote over changes made by another chat session. Both edits are in the file now, so check it reads the way you want.
When the Editor can work out which other chat touched the file, the banner names it by
that chat's opening message instead, replacing "another chat session" above with something
like made by "make the header sticky". That lookup is decorative; when it fails the
banner falls back to the generic wording above.
The warning is informational. It tells you a merge already happened silently and you should look, not that anything was blocked.
Warning The overwrite check is per-file and only covers files the agent read during a turn. It is not a general concurrency guarantee. If you are doing two unrelated pieces of work, prefer doing them one after another over running two chats in parallel on the same area of the code.
Switching and starting chats#
A thin bar above the messages holds two controls:
- A history button with a count of your chats. Click it for a list of recent conversations, labelled by their first message with a relative timestamp. Click one to switch to it.
- + New starts a fresh conversation.
Status shows up in two places. Each row in the list gets a pulsing dot while that conversation's turn is still running, a red Failed badge if its last turn errored, and a red count badge for unresolved file conflicts. The history button itself carries an aggregate dot: red if any chat has failed or has conflicts, otherwise a pulsing dot if any chat is mid-turn.
Switching mid-turn is safe. Each conversation's messages are kept in its own bucket and streamed events are written into the bucket of the turn that produced them, never into whatever is on screen. A background turn keeps running and keeps writing to its own conversation; you see it as the dot in the list.
Half-typed messages survive switching: each conversation keeps its own draft.
Switching to a conversation that was pinned to a particular page also sends the prototype back to that page, so you land where that conversation was working.
Three turns can run at once per project. A fourth waits in line and shows "Waiting for an open chat slot…" until a slot frees up.
Parallel chats are on by default. To turn the feature off and keep a single conversation, set chat.detachedSessions to false in .desde/config.json, not in desde.config.json, whose loader never looks for a chat block. There is no environment variable for it, and the flag is read at startup, so changing it needs a CLI restart.
Choosing a model and effort#
The small chip in the action row shows which model this conversation will use. Click it to change the model, and (for models that support it) the reasoning effort. The choice is per conversation and is remembered, so a scratch chat on a fast model and a long refactor on a capable one can coexist.
| Model | Effort levels |
|---|---|
| Opus 5 | low, medium, high, xhigh, max |
| Opus 4.8 (default) | low, medium, high, xhigh, max |
| Sonnet 5 | low, medium, high, xhigh, max |
| Sonnet 4.6 | low, medium, high, max |
| Haiku 4.5 | none |
Higher effort means the model spends longer reasoning before answering. Leaving effort on Default lets the runtime decide.
Two behaviours are worth knowing:
- The chip never shows a model different from the one your next message will actually run on. If a saved choice is no longer in the catalogue, it silently drops back to the default rather than showing you something stale.
- If the model list cannot be fetched, the chip disappears entirely and chat keeps working on defaults. A missing chip is not a broken chat.
The picker governs chat only. The short AI pass that handles edits the deterministic lane refuses (see deterministic editing) always runs on the runtime default.
What the agent is grounded in#
The agent is not editing your prototype from general knowledge of Vue or React. It is given read-only tools over your own design system and told to query them before guessing:
- List the components that actually exist in your catalogue, so it reaches for a real one instead of writing raw markup.
- Read one component's manifest (its props, defaults, the allowed values for each variant prop, its slots, events, and import path) before setting a prop or picking a variant.
- Search components by name or description.
- Read your design tokens, so a colour or a spacing value comes out as
var(--your-token)rather than a hardcoded hex or pixel value.
These come from the packages actually installed in your prototype, not from a hand-written list. See design-system grounding for where manifests come from and how to attach a library.
It can also see what you see. It has tools to read your current selection, ask what page and route the prototype is on, drive the prototype to another route, and take a screenshot of the running app so it can visually check its own work.
For the repo itself it uses ordinary file reading, searching and editing, scoped to your prototype's directory. Absolute paths pointing outside it are rejected.
When you ask "what did you change?", it can answer from git: the branch, the merge-base with the default branch, and the accumulated diff of the branch so far.
When it cannot find something#
The system prompt instructs the agent to stop rather than guess when a file, repo or reference it was asked about is not reachable: to say what is missing and what would make it reachable, instead of inventing a plausible path or a plausible prop.
Writes, and where they land#
Every file the agent writes is an ordinary uncommitted change in your working tree. Nothing is auto-committed. You commit when you are ready, from the top bar. Each write is backed by the per-edit backup journal, so the Activity panel can put an individual file back to your last commit. See the git workflow.
The agent may edit any existing file in your prototype. Creating a new file is restricted by extension: components and modules, docs and plain text, data and config, stylesheets, HTML and SVG. It cannot create binaries, .env files, or shell scripts.
It has a few structural tools beyond plain file writing: inserting a design-system component (with its import added for you), inserting plain HTML, scaffolding a new page and registering its route, renaming or deleting a file, and adding or removing an npm dependency through the package manager. Each of these refuses with a reason rather than guessing when it cannot do the job cleanly. See what refuses and why.
Rate limits and retries#
Two banners appear above the input when the API is under pressure, both self-clearing:
- Usage limit, as a plain sentence rather than a labelled badge. While you are approaching it: "The usage limit for this Claude account is nearly reached (72% used). Limits reset in 38 mins. This turn is still running." Once a request is actually turned away: "The model request has been denied. The usage limit for this Claude account has been reached. Try again in 38 mins when the limit resets." The turn keeps running on the first; on the second it waits for the limit to clear.
- API retry: "Rate limit hit, waiting before retry (2/5). Resuming in ~3s." on a 429, or "Transient API error, retrying (2/5). Resuming in ~3s." for anything else. The numbers are the attempt out of the maximum, and roughly how long the wait is.
Every banner, including the self-clearing ones, can be dismissed.
Next#
- The git workflow: committing what chat wrote
- What refuses and why: the refusals you will meet
- Design-system grounding: where the agent's component knowledge comes from