diff --git a/src/renderer/src/components/sidebar/AddRepoDialog.tsx b/src/renderer/src/components/sidebar/AddRepoDialog.tsx
index ade12730dee..0608a41fff7 100644
--- a/src/renderer/src/components/sidebar/AddRepoDialog.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoDialog.tsx
@@ -283,6 +283,7 @@ export default React.memo(function AddRepoDialog({
isOpen={isOpen}
step={step}
isAdding={isAdding}
+ isCloning={isCloning}
onBack={handleBack}
onCloseAutoFocus={hosted?.onCloseAutoFocus}
onOpenChange={handleOpenChange}
diff --git a/src/renderer/src/components/sidebar/AddRepoDialogChrome.test.tsx b/src/renderer/src/components/sidebar/AddRepoDialogChrome.test.tsx
new file mode 100644
index 00000000000..81ad68756ae
--- /dev/null
+++ b/src/renderer/src/components/sidebar/AddRepoDialogChrome.test.tsx
@@ -0,0 +1,98 @@
+// @vitest-environment happy-dom
+
+import { cleanup, render, screen } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import { useState } from 'react'
+import { afterEach, describe, expect, it, vi } from 'vitest'
+import { DialogDescription, DialogTitle } from '@/components/ui/dialog'
+import { AddRepoDialogChrome } from './AddRepoDialogChrome'
+
+afterEach(cleanup)
+
+function CloneDialog({
+ isCloning,
+ onOpenChange
+}: {
+ isCloning: boolean
+ onOpenChange: (open: boolean) => void
+}) {
+ const [isOpen, setIsOpen] = useState(true)
+ return (
+ {}}
+ onOpenChange={(open) => {
+ onOpenChange(open)
+ setIsOpen(open)
+ }}
+ >
+ Clone from URL
+ Clone progress
+
+ )
+}
+
+function backdrop(): Element {
+ const overlay = document.querySelector('[data-slot="dialog-overlay"]')
+ if (!overlay) {
+ throw new Error('Missing dialog backdrop')
+ }
+ return overlay
+}
+
+describe('AddRepoDialogChrome dismissal', () => {
+ it('keeps an in-flight clone open after a backdrop click', async () => {
+ const user = userEvent.setup()
+ const onOpenChange = vi.fn()
+ render()
+
+ await user.click(backdrop())
+
+ expect(onOpenChange).not.toHaveBeenCalled()
+ expect(screen.queryByRole('dialog', { name: 'Clone from URL' })).not.toBeNull()
+ })
+
+ it('allows backdrop dismissal when no clone is running', async () => {
+ const user = userEvent.setup()
+ const onOpenChange = vi.fn()
+ render()
+
+ await user.click(backdrop())
+
+ expect(onOpenChange).toHaveBeenCalledWith(false)
+ expect(screen.queryByRole('dialog', { name: 'Clone from URL' })).toBeNull()
+ })
+
+ it('allows backdrop dismissal after the clone settles', async () => {
+ const user = userEvent.setup()
+ const onOpenChange = vi.fn()
+ const view = render()
+ await user.click(backdrop())
+ expect(onOpenChange).not.toHaveBeenCalled()
+
+ view.rerender()
+ await user.click(backdrop())
+
+ expect(onOpenChange).toHaveBeenCalledWith(false)
+ expect(screen.queryByRole('dialog', { name: 'Clone from URL' })).toBeNull()
+ })
+
+ it.each(['Escape', 'Close'])(
+ 'keeps explicit %s dismissal available during a clone',
+ async (action) => {
+ const user = userEvent.setup()
+ const onOpenChange = vi.fn()
+ render()
+
+ await (action === 'Escape'
+ ? user.keyboard('{Escape}')
+ : user.click(screen.getByRole('button', { name: 'Close' })))
+
+ expect(onOpenChange).toHaveBeenCalledWith(false)
+ expect(screen.queryByRole('dialog', { name: 'Clone from URL' })).toBeNull()
+ }
+ )
+})
diff --git a/src/renderer/src/components/sidebar/AddRepoDialogChrome.tsx b/src/renderer/src/components/sidebar/AddRepoDialogChrome.tsx
index 8a4a1893b4d..4876cd7a981 100644
--- a/src/renderer/src/components/sidebar/AddRepoDialogChrome.tsx
+++ b/src/renderer/src/components/sidebar/AddRepoDialogChrome.tsx
@@ -1,11 +1,13 @@
import type { ReactNode } from 'react'
import { Dialog, DialogContent } from '@/components/ui/dialog'
+import { preventOutsideDismissWhenDirty } from '@/lib/outside-dismiss-guard'
import type { AddRepoDialogStep } from './add-repo-dialog-types'
import { AddRepoStepIndicator } from './AddRepoStepIndicator'
export function AddRepoDialogChrome({
children,
isAdding,
+ isCloning,
isOpen,
onBack,
onCloseAutoFocus,
@@ -14,6 +16,7 @@ export function AddRepoDialogChrome({
}: {
children: ReactNode
isAdding: boolean
+ isCloning: boolean
isOpen: boolean
onBack: () => void
onCloseAutoFocus?: (event: Event) => void
@@ -24,6 +27,8 @@ export function AddRepoDialogChrome({