---
title: "Edits and multi-turn"
description: "Let a model change a UI that is already on screen by writing only what changed, with edit mode, patches, appends and merge."
---

> Documentation Index
> Fetch the complete documentation index at: https://gistui.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Edits and multi-turn

In a conversation, the second request is often a small change: "make it a bar chart", "add Q4". Writing the whole screen again costs tokens and time. In **edit mode** the model writes only what changes.

## The four edits

| Edit | Written as | Meaning |
|---|---|---|
| Replace | `k3 = Stat("MRR", "$415k")` | A statement with an existing id replaces it |
| Patch | `k3.value = "$415k"` | Set one prop, by its schema name |
| Append | `kpis += k5` | Add a child, or a table row |
| Delete | `k2 = null` | Remove a statement |

A patch is the cheapest: changing one value costs about 9 tokens instead of re-emitting the statement.

```gistui
trend.type = bar
rev += |Oct|468000
note = Callout("October is a projection.", tone:info)
root += note
```

## How to run an edit turn

1. **Give the model the current program**

   `toEditSource` prints the program in a canonical form in which every part has an id, so everything can be addressed.

   ```ts
   import { library, prompt } from "@gistui/catalog";
   import { toEditSource } from "@gistui/core";

   const current = toEditSource(shownProgram, library);
   const system = prompt({ mode: "edit" }).text;
   const messages = [
     { role: "user", content: `Current UI:\n${current}\n\nRequest: make the chart a bar chart` },
   ];
   ```
2. **Render the edit as it streams**

   `createEditStream` is a stream seeded with the current program, so the change shows live.

   ```ts
   import { createEditStream } from "@gistui/core";

   const stream = createEditStream(shownProgram, library);
   for await (const chunk of modelText) stream.push(chunk);
   stream.end();
   ```
3. **Keep the merged program**

   `merge` applies an edit and returns the new program, canonical and with unused statements removed. Store it as the new current program.

   ```ts
   import { merge } from "@gistui/core";

   const { source, errors } = merge(shownProgram, editText, library);
   ```

## Rules worth knowing

- The last definition of an id wins.
- A patch addresses a prop by name, even one that was written positionally.
- A patch or append whose target does not exist is ignored and reported as `patch-target-missing`.
- Re-declaring a `$state` variable in an edit keeps its current value on screen.
- Statements that nothing uses after an edit are dropped from the merged program.

## The same mechanism powers repair

When `repairStream` fixes a finished answer on the server, it appends the repairs as edits to the end of the stream. The renderer applies them like any other edit, so only what changed re-renders. See [Autofix and repair](/docs/guides/autofix/).

Source: https://gistui.com/docs/language/edits/index.mdx
