# Undo/Redo Baseline
Catalog of the current undo/redo behaviour across Insomnia's text-input surfaces, established
before attempting any improvement. Findings below are split into **confirmed by code**,
**confirmed at runtime** (Playwright probe against the dev build), and **open questions**.
## TL;DR
- There are **three input technologies**, each with different undo semantics.
- CodeMirror editors have built-in undo history; plain inputs rely on native browser/OS undo.
- The dominant defect is that **undo history is destroyed on component remount**, and the
single-line editor (`OneLineEditor`) has no mechanism to restore it (the multi-line
`CodeEditor` does, via a module-level cache — but only when its cache key is stable).
- A native Electron Edit menu binds `Cmd/Ctrl+Z` to the OS-level undo, which competes with
CodeMirror's internal history.
## The three input technologies
### A. Multi-line CodeMirror — `CodeEditor`
[`code-editor.tsx`](../packages/insomnia/src/ui/components/.client/codemirror/code-editor.tsx)
| Aspect | Behaviour | Ref |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Undo engine | CodeMirror built-in history | — |
| Init | `initEditor` runs once via `useMount`; `defaultValue` applied on mount only → **uncontrolled** | [:560](../packages/insomnia/src/ui/components/.client/codemirror/code-editor.tsx#L560) |
| Seed guard | `clearHistory()` after first `setValue` so the seed isn't undoable | [:488](../packages/insomnia/src/ui/components/.client/codemirror/code-editor.tsx#L488) |
| External writes | `maybePrettifyAndSetValue` no-ops when value is unchanged | [:296](../packages/insomnia/src/ui/components/.client/codemirror/code-editor.tsx#L296) |
| **Remount survival** | History is persisted to module-global `editorStates[uniquenessKey]` (`getHistory()`) and restored (`setHistory()`) on re-init — **but only if `uniquenessKey` is unchanged across the remount** | [:324](../packages/insomnia/src/ui/components/.client/codemirror/code-editor.tsx#L324), [:503](../packages/insomnia/src/ui/components/.client/codemirror/code-editor.tsx#L503) |
| Persist to model | debounced `onChange`, `DEBOUNCE_MILLIS = 100` | [:598](../packages/insomnia/src/ui/components/.client/codemirror/code-editor.tsx#L598) |
Consumers (~21): raw body, GraphQL query/variables, environment JSON editor, request
headers/params editors, request-script, markdown, mock response, code-prompt modal, etc.
### B. Single-line CodeMirror — `OneLineEditor`
[`one-line-editor.tsx`](../packages/insomnia/src/ui/components/.client/codemirror/one-line-editor.tsx)
| Aspect | Behaviour | Ref |
| -------------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Undo engine | CodeMirror built-in history | — |
| Init | `initEditor` once via `useMount`, `defaultValue` on mount only → **uncontrolled** | [:255](../packages/insomnia/src/ui/components/.client/codemirror/one-line-editor.tsx#L255) |
| Seed guard | `clearHistory()` after first set | [:221](../packages/insomnia/src/ui/components/.client/codemirror/one-line-editor.tsx#L221) |
| **Remount survival** | **None.** No `editorStates` equivalent — history is destroyed on every remount | — |
| `setValue` handle | Preserves cursor but `cm.setValue()` **clears CM undo history** | [:366](../packages/insomnia/src/ui/components/.client/codemirror/one-line-editor.tsx#L366) |
| Persist to model | debounced `onChange` (100ms) **+ flush on blur** | [:295](../packages/insomnia/src/ui/components/.client/codemirror/one-line-editor.tsx#L295), [:304](../packages/insomnia/src/ui/components/.client/codemirror/one-line-editor.tsx#L304) |
Consumers (~14): URL bar, all key-value rows (name/value/description for headers, query,
form-data, env), auth-input rows, cookies modal, WebSocket/gRPC/Socket.IO URL + panes, MCP url bar.
The "uncontrolled + manual `setValue`" design is deliberate — see the comment at
[`request-pane.tsx:71-75`](../packages/insomnia/src/ui/components/panes/request-pane.tsx#L71):
controlling the editor would make typed input lag behind the model round-trip.
### C. Plain inputs — React Aria `Input`/`TextField`, raw ``/`