diff --git a/desktop/frontend/src/App.tsx b/desktop/frontend/src/App.tsx
index 35e193000..9c4a45d0a 100644
--- a/desktop/frontend/src/App.tsx
+++ b/desktop/frontend/src/App.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useMemo, useRef, useState } from "react";
+import { useCallback, useDeferredValue, useEffect, useMemo, useRef, useState } from "react";
import type { CSSProperties, KeyboardEvent, PointerEvent as ReactPointerEvent } from "react";
import {
SquarePen,
@@ -257,6 +257,12 @@ export default function App() {
todos.length > 0 &&
todos.some((t) => t.status !== "completed");
+ // useDeferredValue lets React prioritise Composer input (high-priority) over
+ // Transcript re-renders (low-priority) during streaming. When a keystroke
+ // and a transcript update collide, the keystroke is processed immediately
+ // and the transcript re-render is deferred to idle time.
+ const deferredItems = useDeferredValue(state.items);
+
useEffect(() => {
if (!pendingPlanRevision || state.running) return;
const text = pendingPlanRevision;
@@ -927,7 +933,7 @@ export default function App() {
{t("common.loading")}
) : (
-
+
)}