diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts index 1b896e89fcb..2e66ff3506a 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts @@ -260,6 +260,17 @@ export function useTerminalLifecycle({ const { xterm, fitAddon, searchAddon } = cached; + // Called after createOrAttach resolves: re-fit against the now-settled + // container and push dims to the backend. Guards against stale sizes + // from attachToContainer's fit running before flex layout resolved + // (e.g. preset tabs, new workspace bulk creation). Mirrors v2's + // terminal-ws-transport sendResize-on-open. + const syncBackendDimensions = () => { + if (container.clientWidth === 0 || container.clientHeight === 0) return; + fitAddon.fit(); + resizeRef.current({ paneId, cols: xterm.cols, rows: xterm.rows }); + }; + // Attach the wrapper div to the live container. // The cache creates a ResizeObserver that calls fitAddon.fit() and // forwards resize events to the backend — no separate resize handler needed. @@ -383,6 +394,7 @@ export function useTerminalLifecycle({ return; } setConnectionError(null); + syncBackendDimensions(); pendingInitialStateRef.current = result; maybeApplyInitialState(); if (!command) { @@ -595,6 +607,7 @@ export function useTerminalLifecycle({ v1TerminalCache.startStream(paneId); v1TerminalCache.setStreamReady(paneId); markTerminalSessionReady(paneId); + syncBackendDimensions(); const storedColdRestore = coldRestoreState.get(paneId); if (storedColdRestore?.isRestored) {