# 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 ``/`