Просмотр исходного кода

ux: improve worktree selector and creation UX (#10940)

* Delete modal

* Restructured

* Much more prominent

* UI

* i18n

* Fixes i18n

* Remove mergeresultmodel

* i18n

* tests

* knip

* code review
Bruno Bergher 2 недель назад
Родитель
Сommit
c56f0f43c7
97 измененных файлов с 1189 добавлено и 380 удалено
  1. 5 0
      packages/types/src/global-settings.ts
  2. 5 1
      packages/types/src/vscode-extension-host.ts
  3. 0 1
      packages/types/src/vscode.ts
  4. 0 6
      src/activate/registerCommands.ts
  5. 28 0
      src/core/webview/webviewMessageHandler.ts
  6. 4 0
      src/i18n/locales/ca/worktrees.json
  7. 4 0
      src/i18n/locales/de/worktrees.json
  8. 4 0
      src/i18n/locales/en/worktrees.json
  9. 4 0
      src/i18n/locales/es/worktrees.json
  10. 4 0
      src/i18n/locales/fr/worktrees.json
  11. 4 0
      src/i18n/locales/hi/worktrees.json
  12. 4 0
      src/i18n/locales/id/worktrees.json
  13. 4 0
      src/i18n/locales/it/worktrees.json
  14. 4 0
      src/i18n/locales/ja/worktrees.json
  15. 4 0
      src/i18n/locales/ko/worktrees.json
  16. 4 0
      src/i18n/locales/nl/worktrees.json
  17. 4 0
      src/i18n/locales/pl/worktrees.json
  18. 4 0
      src/i18n/locales/pt-BR/worktrees.json
  19. 4 0
      src/i18n/locales/ru/worktrees.json
  20. 4 0
      src/i18n/locales/tr/worktrees.json
  21. 4 0
      src/i18n/locales/vi/worktrees.json
  22. 4 0
      src/i18n/locales/zh-CN/worktrees.json
  23. 4 0
      src/i18n/locales/zh-TW/worktrees.json
  24. 0 5
      src/package.json
  25. 0 1
      src/package.nls.ca.json
  26. 0 1
      src/package.nls.de.json
  27. 0 1
      src/package.nls.es.json
  28. 0 1
      src/package.nls.fr.json
  29. 0 1
      src/package.nls.hi.json
  30. 0 1
      src/package.nls.id.json
  31. 0 1
      src/package.nls.it.json
  32. 0 1
      src/package.nls.ja.json
  33. 0 1
      src/package.nls.json
  34. 0 1
      src/package.nls.ko.json
  35. 0 1
      src/package.nls.nl.json
  36. 0 1
      src/package.nls.pl.json
  37. 0 1
      src/package.nls.pt-BR.json
  38. 0 1
      src/package.nls.ru.json
  39. 0 1
      src/package.nls.tr.json
  40. 0 1
      src/package.nls.vi.json
  41. 0 1
      src/package.nls.zh-CN.json
  42. 0 1
      src/package.nls.zh-TW.json
  43. 1 4
      webview-ui/src/App.tsx
  44. 4 0
      webview-ui/src/components/chat/ChatView.tsx
  45. 193 0
      webview-ui/src/components/chat/WorktreeSelector.tsx
  46. 299 0
      webview-ui/src/components/chat/__tests__/WorktreeSelector.spec.tsx
  47. 8 1
      webview-ui/src/components/settings/SettingsView.tsx
  48. 5 0
      webview-ui/src/components/settings/__tests__/SettingsView.change-detection.spec.tsx
  49. 5 0
      webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx
  50. 5 0
      webview-ui/src/components/settings/__tests__/SettingsView.unsaved-changes.spec.tsx
  51. 4 4
      webview-ui/src/components/ui/__tests__/toggle-switch.spec.tsx
  52. 1 1
      webview-ui/src/components/ui/button.tsx
  53. 3 3
      webview-ui/src/components/ui/dialog.tsx
  54. 1 1
      webview-ui/src/components/ui/input.tsx
  55. 4 4
      webview-ui/src/components/ui/toggle-switch.tsx
  56. 30 28
      webview-ui/src/components/worktrees/CreateWorktreeModal.tsx
  57. 22 27
      webview-ui/src/components/worktrees/DeleteWorktreeModal.tsx
  58. 138 138
      webview-ui/src/components/worktrees/WorktreesView.tsx
  59. 0 3
      webview-ui/src/components/worktrees/index.ts
  60. 5 0
      webview-ui/src/context/ExtensionStateContext.tsx
  61. 1 0
      webview-ui/src/i18n/locales/ca/settings.json
  62. 18 7
      webview-ui/src/i18n/locales/ca/worktrees.json
  63. 1 0
      webview-ui/src/i18n/locales/de/settings.json
  64. 18 7
      webview-ui/src/i18n/locales/de/worktrees.json
  65. 1 0
      webview-ui/src/i18n/locales/en/settings.json
  66. 26 15
      webview-ui/src/i18n/locales/en/worktrees.json
  67. 1 0
      webview-ui/src/i18n/locales/es/settings.json
  68. 18 7
      webview-ui/src/i18n/locales/es/worktrees.json
  69. 1 0
      webview-ui/src/i18n/locales/fr/settings.json
  70. 18 7
      webview-ui/src/i18n/locales/fr/worktrees.json
  71. 1 0
      webview-ui/src/i18n/locales/hi/settings.json
  72. 18 7
      webview-ui/src/i18n/locales/hi/worktrees.json
  73. 1 0
      webview-ui/src/i18n/locales/id/settings.json
  74. 18 7
      webview-ui/src/i18n/locales/id/worktrees.json
  75. 1 0
      webview-ui/src/i18n/locales/it/settings.json
  76. 18 7
      webview-ui/src/i18n/locales/it/worktrees.json
  77. 1 0
      webview-ui/src/i18n/locales/ja/settings.json
  78. 18 7
      webview-ui/src/i18n/locales/ja/worktrees.json
  79. 1 0
      webview-ui/src/i18n/locales/ko/settings.json
  80. 18 7
      webview-ui/src/i18n/locales/ko/worktrees.json
  81. 1 0
      webview-ui/src/i18n/locales/nl/settings.json
  82. 18 7
      webview-ui/src/i18n/locales/nl/worktrees.json
  83. 1 0
      webview-ui/src/i18n/locales/pl/settings.json
  84. 18 7
      webview-ui/src/i18n/locales/pl/worktrees.json
  85. 1 0
      webview-ui/src/i18n/locales/pt-BR/settings.json
  86. 18 7
      webview-ui/src/i18n/locales/pt-BR/worktrees.json
  87. 1 0
      webview-ui/src/i18n/locales/ru/settings.json
  88. 18 7
      webview-ui/src/i18n/locales/ru/worktrees.json
  89. 1 0
      webview-ui/src/i18n/locales/tr/settings.json
  90. 18 7
      webview-ui/src/i18n/locales/tr/worktrees.json
  91. 1 0
      webview-ui/src/i18n/locales/vi/settings.json
  92. 18 7
      webview-ui/src/i18n/locales/vi/worktrees.json
  93. 1 0
      webview-ui/src/i18n/locales/zh-CN/settings.json
  94. 18 7
      webview-ui/src/i18n/locales/zh-CN/worktrees.json
  95. 1 0
      webview-ui/src/i18n/locales/zh-TW/settings.json
  96. 18 7
      webview-ui/src/i18n/locales/zh-TW/worktrees.json
  97. 1 1
      webview-ui/src/index.css

+ 5 - 0
packages/types/src/global-settings.ts

@@ -203,6 +203,11 @@ export const globalSettingsSchema = z.object({
 	 * Used by the worktree feature to open the Roo Code sidebar in a new window.
 	 */
 	worktreeAutoOpenPath: z.string().optional(),
+	/**
+	 * Whether to show the worktree selector in the home screen.
+	 * @default true
+	 */
+	showWorktreesInHomeScreen: z.boolean().optional(),
 })
 
 export type GlobalSettings = z.infer<typeof globalSettingsSchema>

+ 5 - 1
packages/types/src/vscode-extension-host.ts

@@ -107,6 +107,7 @@ export interface ExtensionMessage {
 		| "worktreeDefaults"
 		| "worktreeIncludeStatus"
 		| "branchWorktreeIncludeResult"
+		| "folderSelected"
 	text?: string
 	payload?: any // eslint-disable-line @typescript-eslint/no-explicit-any
 	checkpointWarning?: {
@@ -119,7 +120,6 @@ export interface ExtensionMessage {
 		| "historyButtonClicked"
 		| "marketplaceButtonClicked"
 		| "cloudButtonClicked"
-		| "worktreesButtonClicked"
 		| "didBecomeVisible"
 		| "focusInput"
 		| "switchTab"
@@ -257,6 +257,8 @@ export interface ExtensionMessage {
 	copyProgressBytesCopied?: number
 	copyProgressTotalBytes?: number
 	copyProgressItemName?: string
+	// folderSelected
+	path?: string
 }
 
 export interface OpenAiCodexRateLimitsMessage {
@@ -332,6 +334,7 @@ export type ExtensionState = Pick<
 	| "includeCurrentCost"
 	| "maxGitStatusFiles"
 	| "requestDelaySeconds"
+	| "showWorktreesInHomeScreen"
 > & {
 	version: string
 	clineMessages: ClineMessage[]
@@ -600,6 +603,7 @@ export interface WebviewMessage {
 		| "checkBranchWorktreeInclude"
 		| "createWorktreeInclude"
 		| "checkoutBranch"
+		| "browseForWorktreePath"
 	text?: string
 	editedMessageContent?: string
 	tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "cloud"

+ 0 - 1
packages/types/src/vscode.ts

@@ -35,7 +35,6 @@ export const commandIds = [
 	"popoutButtonClicked",
 	"cloudButtonClicked",
 	"settingsButtonClicked",
-	"worktreesButtonClicked",
 
 	"openInNewTab",
 

+ 0 - 6
src/activate/registerCommands.ts

@@ -134,12 +134,6 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
 		if (!visibleProvider) return
 		visibleProvider.postMessageToWebview({ type: "action", action: "marketplaceButtonClicked" })
 	},
-	worktreesButtonClicked: () => {
-		const visibleProvider = getVisibleProviderOrLog(outputChannel)
-		if (!visibleProvider) return
-		TelemetryService.instance.captureTitleButtonClicked("worktrees")
-		visibleProvider.postMessageToWebview({ type: "action", action: "worktreesButtonClicked" })
-	},
 	newTask: handleNewTask,
 	setCustomStoragePath: async () => {
 		const { promptForCustomStoragePath } = await import("../utils/storage")

+ 28 - 0
src/core/webview/webviewMessageHandler.ts

@@ -3556,6 +3556,34 @@ export const webviewMessageHandler = async (
 			break
 		}
 
+		case "browseForWorktreePath": {
+			try {
+				const options: vscode.OpenDialogOptions = {
+					canSelectFiles: false,
+					canSelectFolders: true,
+					canSelectMany: false,
+					openLabel: t("worktrees:selectWorktreeLocation"),
+					title: t("worktrees:selectFolderForWorktree"),
+					defaultUri: vscode.workspace.workspaceFolders?.[0]?.uri
+						? vscode.Uri.joinPath(vscode.workspace.workspaceFolders[0].uri, "..")
+						: undefined,
+				}
+
+				const result = await vscode.window.showOpenDialog(options)
+				if (result && result[0]) {
+					await provider.postMessageToWebview({
+						type: "folderSelected",
+						path: result[0].fsPath,
+					})
+				}
+			} catch (error) {
+				const errorMessage = error instanceof Error ? error.message : String(error)
+				provider.log(`Error opening folder picker: ${errorMessage}`)
+			}
+
+			break
+		}
+
 		default: {
 			// console.log(`Unhandled message type: ${message.type}`)
 			//

+ 4 - 0
src/i18n/locales/ca/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/de/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/en/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/es/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/fr/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/hi/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/id/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/it/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/ja/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/ko/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/nl/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/pl/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/pt-BR/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/ru/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/tr/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/vi/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/zh-CN/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 4 - 0
src/i18n/locales/zh-TW/worktrees.json

@@ -0,0 +1,4 @@
+{
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree"
+}

+ 0 - 5
src/package.json

@@ -100,11 +100,6 @@
 				"title": "%command.settings.title%",
 				"icon": "$(settings-gear)"
 			},
-			{
-				"command": "roo-cline.worktreesButtonClicked",
-				"title": "%command.worktrees.title%",
-				"icon": "$(git-branch)"
-			},
 			{
 				"command": "roo-cline.openInNewTab",
 				"title": "%command.openInNewTab.title%",

+ 0 - 1
src/package.nls.ca.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "Obrir a l'Editor",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Configuració",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Documentació",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "Ordres que es poden executar automàticament quan 'Aprova sempre les operacions d'execució' està activat",

+ 0 - 1
src/package.nls.de.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "Im Editor Öffnen",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Einstellungen",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Dokumentation",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "Befehle, die automatisch ausgeführt werden können, wenn 'Ausführungsoperationen immer genehmigen' aktiviert ist",

+ 0 - 1
src/package.nls.es.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "Abrir en Editor",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Configuración",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Documentación",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "Comandos que pueden ejecutarse automáticamente cuando 'Aprobar siempre operaciones de ejecución' está activado",

+ 0 - 1
src/package.nls.fr.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "Ouvrir dans l'Éditeur",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Paramètres",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Documentation",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "Commandes pouvant être exécutées automatiquement lorsque 'Toujours approuver les opérations d'exécution' est activé",

+ 0 - 1
src/package.nls.hi.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "एडिटर में खोलें",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "सेटिंग्स",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "दस्तावेज़ीकरण",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "वे कमांड जो स्वचालित रूप से निष्पादित की जा सकती हैं जब 'हमेशा निष्पादन संचालन को स्वीकृत करें' सक्रिय हो",

+ 0 - 1
src/package.nls.id.json

@@ -11,7 +11,6 @@
 	"command.openInEditor.title": "Buka di Editor",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Pengaturan",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Dokumentasi",
 	"command.openInNewTab.title": "Buka di Tab Baru",
 	"command.explainCode.title": "Jelaskan Kode",

+ 0 - 1
src/package.nls.it.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "Apri nell'Editor",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Impostazioni",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Documentazione",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "Comandi che possono essere eseguiti automaticamente quando 'Approva sempre le operazioni di esecuzione' è attivato",

+ 0 - 1
src/package.nls.ja.json

@@ -11,7 +11,6 @@
 	"command.openInEditor.title": "エディタで開く",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "設定",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "ドキュメント",
 	"command.openInNewTab.title": "新しいタブで開く",
 	"command.explainCode.title": "コードの説明",

+ 0 - 1
src/package.nls.json

@@ -11,7 +11,6 @@
 	"command.openInEditor.title": "Open in Editor",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Settings",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Documentation",
 	"command.openInNewTab.title": "Open In New Tab",
 	"command.explainCode.title": "Explain Code",

+ 0 - 1
src/package.nls.ko.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "에디터에서 열기",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "설정",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "문서",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "'항상 실행 작업 승인' 이 활성화되어 있을 때 자동으로 실행할 수 있는 명령어",

+ 0 - 1
src/package.nls.nl.json

@@ -11,7 +11,6 @@
 	"command.openInEditor.title": "Openen in Editor",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Instellingen",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Documentatie",
 	"command.openInNewTab.title": "Openen in Nieuw Tabblad",
 	"command.explainCode.title": "Leg Code Uit",

+ 0 - 1
src/package.nls.pl.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "Otwórz w Edytorze",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Ustawienia",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Dokumentacja",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "Polecenia, które mogą być wykonywane automatycznie, gdy włączona jest opcja 'Zawsze zatwierdzaj operacje wykonania'",

+ 0 - 1
src/package.nls.pt-BR.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "Abrir no Editor",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Configurações",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Documentação",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "Comandos que podem ser executados automaticamente quando 'Sempre aprovar operações de execução' está ativado",

+ 0 - 1
src/package.nls.ru.json

@@ -11,7 +11,6 @@
 	"command.openInEditor.title": "Открыть в редакторе",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Настройки",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Документация",
 	"command.openInNewTab.title": "Открыть в новой вкладке",
 	"command.explainCode.title": "Объяснить код",

+ 0 - 1
src/package.nls.tr.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "Düzenleyicide Aç",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Ayarlar",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Dokümantasyon",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "'Her zaman yürütme işlemlerini onayla' etkinleştirildiğinde otomatik olarak yürütülebilen komutlar",

+ 0 - 1
src/package.nls.vi.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "Mở trong Trình Soạn Thảo",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "Cài Đặt",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "Tài Liệu",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "Các lệnh có thể được thực thi tự động khi 'Luôn phê duyệt các thao tác thực thi' được bật",

+ 0 - 1
src/package.nls.zh-CN.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "在编辑器中打开",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "设置",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "文档",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "当启用'始终批准执行操作'时可以自动执行的命令",

+ 0 - 1
src/package.nls.zh-TW.json

@@ -24,7 +24,6 @@
 	"command.openInEditor.title": "在編輯器中開啟",
 	"command.cloud.title": "Cloud",
 	"command.settings.title": "設定",
-	"command.worktrees.title": "Worktrees",
 	"command.documentation.title": "文件",
 	"configuration.title": "Roo Code",
 	"commands.allowedCommands.description": "當啟用'始終批准執行操作'時可以自動執行的命令",

+ 1 - 4
webview-ui/src/App.tsx

@@ -20,12 +20,11 @@ import { CheckpointRestoreDialog } from "./components/chat/CheckpointRestoreDial
 import { DeleteMessageDialog, EditMessageDialog } from "./components/chat/MessageModificationConfirmationDialog"
 import ErrorBoundary from "./components/ErrorBoundary"
 import { CloudView } from "./components/cloud/CloudView"
-import { WorktreesView } from "./components/worktrees"
 import { useAddNonInteractiveClickListener } from "./components/ui/hooks/useNonInteractiveClick"
 import { TooltipProvider } from "./components/ui/tooltip"
 import { STANDARD_TOOLTIP_DELAY } from "./components/ui/standard-tooltip"
 
-type Tab = "settings" | "history" | "chat" | "marketplace" | "cloud" | "worktrees"
+type Tab = "settings" | "history" | "chat" | "marketplace" | "cloud"
 
 interface DeleteMessageDialogState {
 	isOpen: boolean
@@ -51,7 +50,6 @@ const tabsByMessageAction: Partial<Record<NonNullable<ExtensionMessage["action"]
 	historyButtonClicked: "history",
 	marketplaceButtonClicked: "marketplace",
 	cloudButtonClicked: "cloud",
-	worktreesButtonClicked: "worktrees",
 }
 
 const App = () => {
@@ -247,7 +245,6 @@ const App = () => {
 					organizations={cloudOrganizations}
 				/>
 			)}
-			{tab === "worktrees" && <WorktreesView onDone={() => switchTab("chat")} />}
 			<ChatView
 				ref={chatViewRef}
 				isHidden={tab !== "chat"}

+ 4 - 0
webview-ui/src/components/chat/ChatView.tsx

@@ -45,6 +45,7 @@ import SystemPromptWarning from "./SystemPromptWarning"
 import ProfileViolationWarning from "./ProfileViolationWarning"
 import { CheckpointWarning } from "./CheckpointWarning"
 import { QueuedMessages } from "./QueuedMessages"
+import { WorktreeSelector } from "./WorktreeSelector"
 import DismissibleUpsell from "../common/DismissibleUpsell"
 import { useCloudUpsell } from "@src/hooks/useCloudUpsell"
 import { Cloud } from "lucide-react"
@@ -95,6 +96,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 		cloudIsAuthenticated,
 		messageQueue = [],
 		isBrowserSessionActive,
+		showWorktreesInHomeScreen,
 	} = useExtensionState()
 
 	const messagesRef = useRef(messages)
@@ -1543,6 +1545,8 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 				</div>
 			)}
 
+			{!task && showWorktreesInHomeScreen && <WorktreeSelector />}
+
 			{task && (
 				<>
 					<div className="grow flex" ref={scrollContainerRef}>

+ 193 - 0
webview-ui/src/components/chat/WorktreeSelector.tsx

@@ -0,0 +1,193 @@
+import React, { useState, useCallback, useEffect, useMemo } from "react"
+import { GitBranch, Check, ChevronDown, Plus } from "lucide-react"
+
+import type { Worktree, WorktreeListResponse } from "@roo-code/types"
+
+import { cn } from "@/lib/utils"
+import { useRooPortal } from "@/components/ui/hooks/useRooPortal"
+import { Popover, PopoverContent, PopoverTrigger, StandardTooltip, Button } from "@/components/ui"
+import { useAppTranslation } from "@/i18n/TranslationContext"
+import { vscode } from "@/utils/vscode"
+
+import { CreateWorktreeModal } from "../worktrees/CreateWorktreeModal"
+import { IconButton } from "./IconButton"
+
+interface WorktreeSelectorProps {
+	disabled?: boolean
+}
+
+export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) => {
+	const { t } = useAppTranslation()
+	const [open, setOpen] = useState(false)
+	const [worktrees, setWorktrees] = useState<Worktree[]>([])
+	const [isGitRepo, setIsGitRepo] = useState(true)
+	const [showCreateModal, setShowCreateModal] = useState(false)
+	const portalContainer = useRooPortal("roo-portal")
+
+	// Find current worktree
+	const currentWorktree = useMemo(() => worktrees.find((w) => w.isCurrent), [worktrees])
+
+	// Fetch worktrees when popover opens
+	const fetchWorktrees = useCallback(() => {
+		vscode.postMessage({ type: "listWorktrees" })
+	}, [])
+
+	// Handle messages from extension
+	useEffect(() => {
+		const handleMessage = (event: MessageEvent) => {
+			const message = event.data
+			if (message.type === "worktreeList") {
+				const response: WorktreeListResponse = message
+				setWorktrees(response.worktrees || [])
+				setIsGitRepo(response.isGitRepo)
+			}
+		}
+
+		window.addEventListener("message", handleMessage)
+		return () => window.removeEventListener("message", handleMessage)
+	}, [])
+
+	// Initial fetch and refresh on open
+	useEffect(() => {
+		fetchWorktrees()
+	}, [fetchWorktrees])
+
+	useEffect(() => {
+		if (open) {
+			fetchWorktrees()
+		}
+	}, [open, fetchWorktrees])
+
+	const handleSelect = useCallback((worktreePath: string) => {
+		vscode.postMessage({
+			type: "switchWorktree",
+			worktreePath: worktreePath,
+			worktreeNewWindow: false,
+		})
+		setOpen(false)
+	}, [])
+
+	const handleSettingsClick = useCallback(() => {
+		vscode.postMessage({
+			type: "switchTab",
+			tab: "settings",
+			values: { section: "worktrees" },
+		})
+		setOpen(false)
+	}, [])
+
+	// Don't render if not a git repo or only one worktree
+	if (!isGitRepo || worktrees.length <= 1) {
+		return null
+	}
+
+	const title = t("worktrees:selector.tooltip")
+
+	return (
+		<Popover open={open} onOpenChange={setOpen} data-testid="worktree-selector-root">
+			<StandardTooltip content={title}>
+				<PopoverTrigger
+					disabled={disabled}
+					data-testid="worktree-selector-trigger"
+					className={cn(
+						"inline-flex gap-1 mx-2 mb-1 items-center relative whitespace-nowrap px-3 py-2",
+						"bg-transparent rounded-full text-vscode-foreground text-left text-sm",
+						"transition-all duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder focus-visible:ring-inset",
+						disabled
+							? "opacity-50 cursor-not-allowed"
+							: "opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer",
+					)}>
+					<span className="font-semibold mr-2">{t("worktrees:selector.worktree")}:</span>
+					<GitBranch className="w-3 h-3" />
+					<span className="truncate">{currentWorktree?.branch || t("worktrees:noBranch")}</span>
+					<ChevronDown className="size-3" />
+				</PopoverTrigger>
+			</StandardTooltip>
+			<PopoverContent
+				align="start"
+				sideOffset={4}
+				container={portalContainer}
+				className="p-0 overflow-hidden min-w-80 max-w-9/10">
+				<div className="flex flex-col w-full">
+					{/* Bottom bar with settings cog and title */}
+					<div className="px-3 pb-4">
+						<div className="flex flex-row items-center justify-between">
+							<h4 className="">{t("worktrees:selector.title")}</h4>
+							<IconButton
+								iconClass="codicon-settings-gear"
+								title={t("worktrees:selector.settings")}
+								onClick={handleSettingsClick}
+							/>
+						</div>
+						<p className="m-0 text-xs text-vscode-descriptionForeground">
+							{t("worktrees:selector.description")}
+						</p>
+					</div>
+
+					{/* Worktree list */}
+					<div className="max-h-[300px] overflow-y-auto py-1">
+						{worktrees.map((worktree) => {
+							const isSelected = worktree.isCurrent
+							return (
+								<div
+									key={worktree.path}
+									onClick={() => !isSelected && handleSelect(worktree.path)}
+									data-testid="worktree-selector-item"
+									className={cn(
+										"px-3 py-1.5 text-sm cursor-pointer flex items-center",
+										"hover:bg-vscode-list-hoverBackground",
+										isSelected &&
+											"bg-vscode-list-activeSelectionBackground text-vscode-list-activeSelectionForeground",
+									)}>
+									<div className="flex-1 min-w-0">
+										<div className="flex items-center gap-2">
+											<GitBranch className="w-3 h-3 shrink-0" />
+											<span className="font-bold truncate">
+												{worktree.branch || t("worktrees:noBranch")}
+											</span>
+											{worktree.isBare && (
+												<span className="text-xs opacity-70">{t("worktrees:primary")}</span>
+											)}
+										</div>
+										<div className="text-xs text-vscode-descriptionForeground ml-5 truncate">
+											{worktree.path}
+										</div>
+									</div>
+									{isSelected && <Check className="ml-auto size-4 p-0.5" />}
+								</div>
+							)
+						})}
+					</div>
+
+					{/* New worktree button */}
+					<div className="px-3 py-2 border-t border-vscode-panel-border">
+						<Button
+							variant="ghost"
+							size="sm"
+							className="w-full justify-start"
+							onClick={() => {
+								setShowCreateModal(true)
+								setOpen(false)
+							}}>
+							<Plus className="w-3 h-3 mr-2" />
+							{t("worktrees:newWorktree")}
+						</Button>
+					</div>
+				</div>
+			</PopoverContent>
+
+			{/* Create Worktree Modal */}
+			{showCreateModal && (
+				<CreateWorktreeModal
+					open={showCreateModal}
+					onClose={() => setShowCreateModal(false)}
+					openAfterCreate={true}
+					onSuccess={() => {
+						setShowCreateModal(false)
+						fetchWorktrees()
+					}}
+				/>
+			)}
+		</Popover>
+	)
+}

+ 299 - 0
webview-ui/src/components/chat/__tests__/WorktreeSelector.spec.tsx

@@ -0,0 +1,299 @@
+import { render, screen, fireEvent, act } from "@/utils/test-utils"
+
+import type { Worktree, WorktreeListResponse } from "@roo-code/types"
+
+import { WorktreeSelector } from "../WorktreeSelector"
+
+const mockPostMessage = vi.fn()
+
+vi.mock("@/utils/vscode", () => ({
+	vscode: {
+		postMessage: (...args: unknown[]) => mockPostMessage(...args),
+	},
+}))
+
+vi.mock("@/i18n/TranslationContext", () => ({
+	useAppTranslation: () => ({
+		t: (key: string) => key,
+	}),
+}))
+
+vi.mock("@/components/ui/hooks/useRooPortal", () => ({
+	useRooPortal: () => document.body,
+}))
+
+const mockWorktrees: Worktree[] = [
+	{
+		path: "/path/to/main",
+		branch: "main",
+		commitHash: "abc123",
+		isCurrent: true,
+		isBare: true,
+		isDetached: false,
+		isLocked: false,
+	},
+	{
+		path: "/path/to/feature-branch",
+		branch: "feature-branch",
+		commitHash: "def456",
+		isCurrent: false,
+		isBare: false,
+		isDetached: false,
+		isLocked: false,
+	},
+	{
+		path: "/path/to/another-branch",
+		branch: "another-branch",
+		commitHash: "ghi789",
+		isCurrent: false,
+		isBare: false,
+		isDetached: false,
+		isLocked: false,
+	},
+]
+
+const simulateWorktreeListMessage = (worktrees: Worktree[], isGitRepo: boolean = true) => {
+	const message: Partial<WorktreeListResponse> & { type: string } = {
+		type: "worktreeList",
+		worktrees,
+		isGitRepo,
+		isMultiRoot: false,
+		isSubfolder: false,
+		gitRootPath: "/path/to/repo",
+	}
+
+	act(() => {
+		window.dispatchEvent(new MessageEvent("message", { data: message }))
+	})
+}
+
+describe("WorktreeSelector", () => {
+	beforeEach(() => {
+		mockPostMessage.mockClear()
+	})
+
+	test("requests worktrees on mount", () => {
+		render(<WorktreeSelector />)
+
+		expect(mockPostMessage).toHaveBeenCalledWith({ type: "listWorktrees" })
+	})
+
+	test("does not render when not a git repo", () => {
+		const { container } = render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage([], false)
+
+		expect(container.querySelector('[data-testid="worktree-selector-trigger"]')).not.toBeInTheDocument()
+	})
+
+	test("does not render when only one worktree exists", () => {
+		const { container } = render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage([mockWorktrees[0]])
+
+		expect(container.querySelector('[data-testid="worktree-selector-trigger"]')).not.toBeInTheDocument()
+	})
+
+	test("renders trigger when multiple worktrees exist", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		expect(screen.getByTestId("worktree-selector-trigger")).toBeInTheDocument()
+	})
+
+	test("shows current branch name on trigger", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		const trigger = screen.getByTestId("worktree-selector-trigger")
+		expect(trigger).toHaveTextContent("main")
+	})
+
+	test("opens popover and shows all worktrees when clicked", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		// Should show all worktree items
+		const items = screen.getAllByTestId("worktree-selector-item")
+		expect(items).toHaveLength(3)
+	})
+
+	test("shows worktree branch names and paths in popover", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		// "main" appears twice: once in trigger and once in popover list
+		expect(screen.getAllByText("main").length).toBeGreaterThanOrEqual(2)
+		expect(screen.getByText("feature-branch")).toBeInTheDocument()
+		expect(screen.getByText("another-branch")).toBeInTheDocument()
+		expect(screen.getByText("/path/to/main")).toBeInTheDocument()
+		expect(screen.getByText("/path/to/feature-branch")).toBeInTheDocument()
+	})
+
+	test("shows primary badge on primary worktree", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		expect(screen.getByText("worktrees:primary")).toBeInTheDocument()
+	})
+
+	test("sends switch message when selecting a different worktree", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		// Click on feature-branch worktree
+		const items = screen.getAllByTestId("worktree-selector-item")
+		fireEvent.click(items[1]) // Second item is feature-branch
+
+		expect(mockPostMessage).toHaveBeenCalledWith({
+			type: "switchWorktree",
+			worktreePath: "/path/to/feature-branch",
+			worktreeNewWindow: false,
+		})
+	})
+
+	test("does not send switch message when selecting current worktree", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		mockPostMessage.mockClear()
+
+		// Click on current worktree (main)
+		const items = screen.getAllByTestId("worktree-selector-item")
+		fireEvent.click(items[0])
+
+		expect(mockPostMessage).not.toHaveBeenCalledWith(
+			expect.objectContaining({
+				type: "switchWorktree",
+			}),
+		)
+	})
+
+	test("shows settings button in footer", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		// Check for settings gear icon button
+		const settingsButton = document.querySelector(".codicon-settings-gear")
+		expect(settingsButton).toBeInTheDocument()
+	})
+
+	test("navigates to worktree settings when settings button clicked", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		// Find and click the settings button
+		const settingsButton = document.querySelector(".codicon-settings-gear")
+		expect(settingsButton).toBeInTheDocument()
+
+		fireEvent.click(settingsButton!.closest("button")!)
+
+		expect(mockPostMessage).toHaveBeenCalledWith({
+			type: "switchTab",
+			tab: "settings",
+			values: { section: "worktrees" },
+		})
+	})
+
+	test("shows title in header", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		expect(screen.getByText("worktrees:selector.title")).toBeInTheDocument()
+	})
+
+	test("shows description in popover", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		expect(screen.getByText("worktrees:selector.description")).toBeInTheDocument()
+	})
+
+	test("is disabled when disabled prop is true", () => {
+		render(<WorktreeSelector disabled={true} />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		const trigger = screen.getByTestId("worktree-selector-trigger")
+		expect(trigger).toBeDisabled()
+	})
+
+	test("refreshes worktrees when popover opens", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		mockPostMessage.mockClear()
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		expect(mockPostMessage).toHaveBeenCalledWith({ type: "listWorktrees" })
+	})
+
+	test("shows check mark on current worktree", () => {
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(mockWorktrees)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		// The current worktree should have Check component (Check from lucide-react)
+		const items = screen.getAllByTestId("worktree-selector-item")
+		const currentItem = items[0] // main is current
+		const checkIcon = currentItem.querySelector("svg.lucide-check")
+		expect(checkIcon).toBeInTheDocument()
+	})
+
+	test("handles worktree with no branch (detached HEAD)", () => {
+		const worktreesWithDetached: Worktree[] = [
+			...mockWorktrees,
+			{
+				path: "/path/to/detached",
+				branch: "",
+				commitHash: "xyz999",
+				isCurrent: false,
+				isBare: false,
+				isDetached: true,
+				isLocked: false,
+			},
+		]
+
+		render(<WorktreeSelector />)
+
+		simulateWorktreeListMessage(worktreesWithDetached)
+
+		fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
+
+		// Should show "worktrees:noBranch" translation key for detached HEAD
+		expect(screen.getByText("worktrees:noBranch")).toBeInTheDocument()
+	})
+})

+ 8 - 1
webview-ui/src/components/settings/SettingsView.tsx

@@ -28,6 +28,7 @@ import {
 	Server,
 	Users2,
 	ArrowLeft,
+	GitCommitVertical,
 } from "lucide-react"
 
 import {
@@ -79,6 +80,7 @@ import { SlashCommandsSettings } from "./SlashCommandsSettings"
 import { UISettings } from "./UISettings"
 import ModesView from "../modes/ModesView"
 import McpView from "../mcp/McpView"
+import { WorktreesView } from "../worktrees/WorktreesView"
 import { SettingsSearch } from "./SettingsSearch"
 import { useSearchIndexRegistry, SearchIndexProvider } from "./useSettingsSearch"
 
@@ -104,6 +106,7 @@ export const sectionNames = [
 	"terminal",
 	"modes",
 	"mcp",
+	"worktrees",
 	"prompts",
 	"ui",
 	"experimental",
@@ -518,11 +521,12 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
 			{ id: "autoApprove", icon: CheckCheck },
 			{ id: "slashCommands", icon: SquareSlash },
 			{ id: "browser", icon: SquareMousePointer },
-			{ id: "checkpoints", icon: GitBranch },
+			{ id: "checkpoints", icon: GitCommitVertical },
 			{ id: "notifications", icon: Bell },
 			{ id: "contextManagement", icon: Database },
 			{ id: "terminal", icon: SquareTerminal },
 			{ id: "prompts", icon: MessageSquare },
+			{ id: "worktrees", icon: GitBranch },
 			{ id: "ui", icon: Glasses },
 			{ id: "experimental", icon: FlaskConical },
 			{ id: "language", icon: Globe },
@@ -889,6 +893,9 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
 						{/* MCP Section */}
 						{renderTab === "mcp" && <McpView />}
 
+						{/* Worktrees Section */}
+						{renderTab === "worktrees" && <WorktreesView />}
+
 						{/* Prompts Section */}
 						{renderTab === "prompts" && (
 							<PromptsSettings

+ 5 - 0
webview-ui/src/components/settings/__tests__/SettingsView.change-detection.spec.tsx

@@ -28,6 +28,11 @@ vi.mock("@src/i18n/TranslationContext", () => ({
 
 // Mock UI components
 vi.mock("@src/components/ui", () => ({
+	ToggleSwitch: ({ checked, onChange, "aria-label": ariaLabel, "data-testid": dataTestId }: any) => (
+		<button role="switch" aria-checked={checked} aria-label={ariaLabel} data-testid={dataTestId} onClick={onChange}>
+			Toggle
+		</button>
+	),
 	AlertDialog: ({ open, children }: any) => (open ? <div data-testid="alert-dialog">{children}</div> : null),
 	AlertDialogContent: ({ children }: any) => <div>{children}</div>,
 	AlertDialogTitle: ({ children }: any) => <div data-testid="alert-title">{children}</div>,

+ 5 - 0
webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx

@@ -116,6 +116,11 @@ vi.mock("../../../components/common/Tab", () => ({
 
 vi.mock("@/components/ui", () => ({
 	...vi.importActual("@/components/ui"),
+	ToggleSwitch: ({ checked, onChange, "aria-label": ariaLabel, "data-testid": dataTestId }: any) => (
+		<button role="switch" aria-checked={checked} aria-label={ariaLabel} data-testid={dataTestId} onClick={onChange}>
+			Toggle
+		</button>
+	),
 	Popover: ({ children }: any) => <div data-testid="popover">{children}</div>,
 	PopoverTrigger: ({ children }: any) => <div data-testid="popover-trigger">{children}</div>,
 	PopoverContent: ({ children }: any) => <div data-testid="popover-content">{children}</div>,

+ 5 - 0
webview-ui/src/components/settings/__tests__/SettingsView.unsaved-changes.spec.tsx

@@ -29,6 +29,11 @@ vi.mock("@src/i18n/TranslationContext", () => ({
 
 // Mock UI components
 vi.mock("@src/components/ui", () => ({
+	ToggleSwitch: ({ checked, onChange, "aria-label": ariaLabel, "data-testid": dataTestId }: any) => (
+		<button role="switch" aria-checked={checked} aria-label={ariaLabel} data-testid={dataTestId} onClick={onChange}>
+			Toggle
+		</button>
+	),
 	AlertDialog: ({ children }: any) => <div>{children}</div>,
 	AlertDialogContent: ({ children }: any) => <div>{children}</div>,
 	AlertDialogTitle: ({ children }: any) => <div>{children}</div>,

+ 4 - 4
webview-ui/src/components/ui/__tests__/toggle-switch.spec.tsx

@@ -85,8 +85,8 @@ describe("ToggleSwitch", () => {
 
 		const toggle = screen.getByRole("switch")
 		expect(toggle).toBeInTheDocument()
-		// Medium size should be 20px x 10px
-		expect(toggle).toHaveStyle({ width: "20px", height: "10px" })
+		// Medium size should be 26px x 10px
+		expect(toggle).toHaveStyle({ width: "26px", height: "10px" })
 	})
 
 	it("defaults to small size", () => {
@@ -95,7 +95,7 @@ describe("ToggleSwitch", () => {
 
 		const toggle = screen.getByRole("switch")
 		expect(toggle).toBeInTheDocument()
-		// Small size should be 16px x 8px
-		expect(toggle).toHaveStyle({ width: "16px", height: "8px" })
+		// Small size should be 20px x 10px
+		expect(toggle).toHaveStyle({ width: "20px", height: "10px" })
 	})
 })

+ 1 - 1
webview-ui/src/components/ui/button.tsx

@@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority"
 import { cn } from "@/lib/utils"
 
 const buttonVariants = cva(
-	"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-base font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer active:opacity-80",
+	"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-base font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-30 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer active:opacity-80",
 	{
 		variants: {
 			variant: {

+ 3 - 3
webview-ui/src/components/ui/dialog.tsx

@@ -40,12 +40,12 @@ function DialogContent({ className, children, ...props }: React.ComponentProps<t
 			<DialogPrimitive.Content
 				data-slot="dialog-content"
 				className={cn(
-					"bg-vscode-editor-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
+					"bg-vscode-editor-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl border p-6 shadow-lg duration-200 sm:max-w-lg",
 					className,
 				)}
 				{...props}>
 				{children}
-				<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
+				<DialogPrimitive.Close className="ring-offset-background cursor-pointer focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
 					<XIcon />
 					<span className="sr-only">Close</span>
 				</DialogPrimitive.Close>
@@ -68,7 +68,7 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
 	return (
 		<div
 			data-slot="dialog-footer"
-			className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
+			className={cn("flex justify-end gap-2 sm:flex-row sm:justify-end", className)}
 			{...props}
 		/>
 	)

+ 1 - 1
webview-ui/src/components/ui/input.tsx

@@ -8,7 +8,7 @@ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
 			<input
 				type={type}
 				className={cn(
-					"flex w-full text-vscode-input-foreground border border-vscode-dropdown-border  bg-vscode-input-background rounded-xs px-3 py-1 text-base transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus:outline-0 focus-visible:outline-none focus-visible:border-vscode-focusBorder disabled:cursor-not-allowed disabled:opacity-50",
+					"flex w-full text-vscode-input-foreground border border-vscode-dropdown-border  bg-vscode-input-background rounded-xs px-3 py-1 text-base transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-vscode-focusBorder disabled:cursor-not-allowed disabled:opacity-50",
 					className,
 				)}
 				ref={ref}

+ 4 - 4
webview-ui/src/components/ui/toggle-switch.tsx

@@ -17,7 +17,7 @@ export const ToggleSwitch: React.FC<ToggleSwitchProps> = ({
 	"aria-label": ariaLabel,
 	"data-testid": dataTestId,
 }) => {
-	const dimensions = size === "small" ? { width: 16, height: 8, dotSize: 4 } : { width: 20, height: 10, dotSize: 6 }
+	const dimensions = size === "small" ? { width: 20, height: 10, dotSize: 8 } : { width: 26, height: 10, dotSize: 6 }
 
 	const handleKeyDown = (e: React.KeyboardEvent) => {
 		if (e.key === "Enter" || e.key === " ") {
@@ -40,12 +40,12 @@ export const ToggleSwitch: React.FC<ToggleSwitchProps> = ({
 				height: `${dimensions.height}px`,
 				backgroundColor: checked
 					? "var(--vscode-button-background)"
-					: "var(--vscode-titleBar-inactiveForeground)",
+					: "var(--vscode-button-secondaryBackground)",
 				borderRadius: `${dimensions.height / 2}px`,
 				position: "relative",
 				cursor: disabled ? "not-allowed" : "pointer",
 				transition: "background-color 0.2s",
-				opacity: disabled ? 0.4 : checked ? 0.8 : 0.6,
+				opacity: disabled ? 0.6 : 1,
 			}}
 			onClick={disabled ? undefined : onChange}
 			onKeyDown={handleKeyDown}>
@@ -53,7 +53,7 @@ export const ToggleSwitch: React.FC<ToggleSwitchProps> = ({
 				style={{
 					width: `${dimensions.dotSize}px`,
 					height: `${dimensions.dotSize}px`,
-					backgroundColor: "var(--vscode-titleBar-activeForeground)",
+					backgroundColor: "var(--vscode-foreground)",
 					borderRadius: "50%",
 					position: "absolute",
 					top: `${(dimensions.height - dimensions.dotSize) / 2}px`,

+ 30 - 28
webview-ui/src/components/worktrees/CreateWorktreeModal.tsx

@@ -5,17 +5,9 @@ import type { WorktreeDefaultsResponse, BranchInfo, WorktreeIncludeStatus } from
 
 import { vscode } from "@/utils/vscode"
 import { useAppTranslation } from "@/i18n/TranslationContext"
-import {
-	Dialog,
-	DialogContent,
-	DialogDescription,
-	DialogFooter,
-	DialogHeader,
-	DialogTitle,
-	Button,
-	Input,
-} from "@/components/ui"
+import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Button, Input } from "@/components/ui"
 import { SearchableSelect, type SearchableSelectOption } from "@/components/ui/searchable-select"
+import { CornerDownRight, Folder, FolderSearch, Info } from "lucide-react"
 
 interface CreateWorktreeModalProps {
 	open: boolean
@@ -81,6 +73,12 @@ export const CreateWorktreeModal = ({
 					setIncludeStatus(message.worktreeIncludeStatus)
 					break
 				}
+				case "folderSelected": {
+					if (message.path) {
+						setWorktreePath(message.path)
+					}
+					break
+				}
 				case "worktreeCopyProgress": {
 					setCopyProgress({
 						bytesCopied: message.copyProgressBytesCopied ?? 0,
@@ -152,14 +150,13 @@ export const CreateWorktreeModal = ({
 			<DialogContent className="max-w-lg">
 				<DialogHeader>
 					<DialogTitle>{t("worktrees:createWorktree")}</DialogTitle>
-					<DialogDescription>{t("worktrees:createWorktreeDescription")}</DialogDescription>
 				</DialogHeader>
 
 				<div className="flex flex-col gap-3">
 					{/* No .worktreeinclude warning - shows when the current worktree doesn't have .worktreeinclude */}
 					{includeStatus?.exists === false && (
 						<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder text-sm">
-							<span className="codicon codicon-warning text-vscode-charts-yellow flex-shrink-0" />
+							<Info />
 							<span className="text-vscode-foreground">
 								<span className="font-medium">{t("worktrees:noIncludeFileWarning")}</span>
 								{" — "}
@@ -170,17 +167,6 @@ export const CreateWorktreeModal = ({
 						</div>
 					)}
 
-					{/* Branch name */}
-					<div className="flex flex-col gap-1">
-						<label className="text-sm text-vscode-foreground">{t("worktrees:branchName")}</label>
-						<Input
-							value={branchName}
-							onChange={(e) => setBranchName(e.target.value)}
-							placeholder={defaults?.suggestedBranch || "worktree/feature-name"}
-							className="rounded-full"
-						/>
-					</div>
-
 					{/* Base branch selector */}
 					<div className="flex flex-col gap-1">
 						<label className="text-sm text-vscode-foreground">{t("worktrees:baseBranch")}</label>
@@ -201,16 +187,32 @@ export const CreateWorktreeModal = ({
 						)}
 					</div>
 
+					{/* Branch name */}
+					<div className="flex items-center gap-2">
+						<CornerDownRight className="size-4 ml-2 shrink-0" />
+						<label className="text-sm text-vscode-foreground shrink-0">{t("worktrees:branchName")}</label>
+						<Input
+							value={branchName}
+							onChange={(e) => setBranchName(e.target.value)}
+							placeholder={defaults?.suggestedBranch || "worktree/feature-name"}
+							className="rounded-full"
+						/>
+					</div>
+
 					{/* Worktree path */}
-					<div className="flex flex-col gap-1">
-						<label className="text-sm text-vscode-foreground">{t("worktrees:worktreePath")}</label>
+					<div className="flex items-center gap-2 relative">
+						<Folder className="size-4 ml-2 shrink-0" />
+						<label className="text-sm text-vscode-foreground shrink-0">{t("worktrees:worktreePath")}</label>
 						<Input
 							value={worktreePath}
 							onChange={(e) => setWorktreePath(e.target.value)}
 							placeholder={defaults?.suggestedPath || "/path/to/worktree"}
-							className="rounded-full"
+							className="rounded-full flex-1 pr-9"
+						/>
+						<FolderSearch
+							className="size-4 shrink-0 absolute right-3 cursor-pointer hover:opacity-75 transition-opacity"
+							onClick={() => vscode.postMessage({ type: "browseForWorktreePath" })}
 						/>
-						<p className="text-xs text-vscode-descriptionForeground">{t("worktrees:pathHint")}</p>
 					</div>
 
 					{/* Error message */}
@@ -244,7 +246,7 @@ export const CreateWorktreeModal = ({
 					<Button variant="secondary" onClick={onClose} disabled={isCreating}>
 						{t("worktrees:cancel")}
 					</Button>
-					<Button onClick={handleCreate} disabled={!isValid || isCreating}>
+					<Button variant="primary" onClick={handleCreate} disabled={!isValid || isCreating}>
 						{isCreating ? (
 							<>
 								<span className="codicon codicon-loading codicon-modifier-spin mr-2" />

+ 22 - 27
webview-ui/src/components/worktrees/DeleteWorktreeModal.tsx

@@ -4,16 +4,8 @@ import type { Worktree } from "@roo-code/types"
 
 import { vscode } from "@/utils/vscode"
 import { useAppTranslation } from "@/i18n/TranslationContext"
-import {
-	Dialog,
-	DialogContent,
-	DialogDescription,
-	DialogFooter,
-	DialogHeader,
-	DialogTitle,
-	Button,
-	Checkbox,
-} from "@/components/ui"
+import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Button, Checkbox } from "@/components/ui"
+import { Folder, GitBranch, TriangleAlert } from "lucide-react"
 
 interface DeleteWorktreeModalProps {
 	open: boolean
@@ -63,35 +55,38 @@ export const DeleteWorktreeModal = ({ open, onClose, worktree, onSuccess }: Dele
 		<Dialog open={open} onOpenChange={(isOpen: boolean) => !isOpen && onClose()}>
 			<DialogContent>
 				<DialogHeader>
-					<div className="flex items-center gap-2">
-						<span className="codicon codicon-warning text-vscode-charts-yellow text-xl" />
-						<DialogTitle>{t("worktrees:deleteWorktree")}</DialogTitle>
-					</div>
-					<DialogDescription>{t("worktrees:deleteWorktreeDescription")}</DialogDescription>
+					<DialogTitle>{t("worktrees:deleteWorktree")}</DialogTitle>
 				</DialogHeader>
 
 				<div className="flex flex-col gap-3 overflow-hidden">
 					{/* Worktree info */}
-					<div className="px-2 py-1.5 rounded bg-vscode-input-background border border-vscode-input-border">
-						<div className="flex items-center gap-2">
-							<span className="codicon codicon-git-branch flex-shrink-0" />
-							<span className="font-medium text-vscode-foreground truncate">
+					<div className="flex flex-col p-5 gap-2 cursor-default rounded-xl text-vscode-foreground bg-vscode-input-background">
+						<p className="flex items-center gap-2 m-0">
+							<GitBranch className="size-4 shrink-0" />
+							<span className="font-medium truncate">
 								{worktree.branch ||
 									(worktree.isDetached ? t("worktrees:detachedHead") : t("worktrees:noBranch"))}
 							</span>
-						</div>
-						<div className="text-xs text-vscode-descriptionForeground mt-0.5 truncate">{worktree.path}</div>
+						</p>
+
+						<p className="flex items-start gap-2 m-0">
+							<Folder className="size-4 shrink-0" />
+							<span className="m-0 text-sm font-mono font-medium text-vscode-descriptionForeground">
+								{worktree.path}
+							</span>
+						</p>
 					</div>
 
 					{/* Warning message */}
-					<div className="flex items-start gap-2 p-2 rounded bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder text-sm">
-						<span className="codicon codicon-warning text-vscode-charts-yellow flex-shrink-0 mt-0.5" />
-						<div className="min-w-0">
-							<p className="text-vscode-foreground m-0">{t("worktrees:deleteWarning")}</p>
-							<ul className="mt-1 mb-0 pl-0 list-none space-y-0.5 text-vscode-descriptionForeground">
-								<li>• {t("worktrees:deleteWarningBranch", { branch: worktree.branch || "HEAD" })}</li>
+					<div className="flex items-start gap-2 px-5 py-2">
+						<TriangleAlert className="size-4 text-vscode-charts-yellow flex-shrink-0" />
+						<div className="flex flex-col min-w-0 gap-2">
+							<p className="m-0 text-vscode-foreground">{t("worktrees:deleteWarning")}</p>
+							<ul className="m-0 pl-0 list-none space-y-1 text-vscode-descriptionForeground">
+								<li>• {t("worktrees:deleteWarningBranch")}</li>
 								<li>• {t("worktrees:deleteWarningFiles")}</li>
 							</ul>
+							<p className="m-0 text-vscode-descriptionForeground">{t("worktrees:deleteNoticeLarge")}</p>
 						</div>
 					</div>
 

+ 138 - 138
webview-ui/src/components/worktrees/WorktreesView.tsx

@@ -2,21 +2,20 @@ import { useState, useEffect, useCallback } from "react"
 
 import type { Worktree, WorktreeListResponse, WorktreeIncludeStatus } from "@roo-code/types"
 
-import { Badge, Button, StandardTooltip } from "@/components/ui"
+import { Badge, Button, StandardTooltip, ToggleSwitch } from "@/components/ui"
+import { useExtensionState } from "@/context/ExtensionStateContext"
 import { useAppTranslation } from "@/i18n/TranslationContext"
 import { vscode } from "@/utils/vscode"
 
-import { Tab, TabContent, TabHeader } from "../common/Tab"
+import { SectionHeader } from "../settings/SectionHeader"
 
 import { CreateWorktreeModal } from "./CreateWorktreeModal"
 import { DeleteWorktreeModal } from "./DeleteWorktreeModal"
+import { Folder, GitBranch, Lock, Plus, SquareArrowOutUpRight, Trash } from "lucide-react"
 
-type WorktreesViewProps = {
-	onDone: () => void
-}
-
-export const WorktreesView = ({ onDone }: WorktreesViewProps) => {
+export const WorktreesView = () => {
 	const { t } = useAppTranslation()
+	const { showWorktreesInHomeScreen, setShowWorktreesInHomeScreen } = useExtensionState()
 
 	// State
 	const [worktrees, setWorktrees] = useState<Worktree[]>([])
@@ -123,103 +122,83 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => {
 		})
 	}, [])
 
+	// Handle toggle show in home screen
+	const handleToggleShowInHomeScreen = useCallback(() => {
+		const newValue = !showWorktreesInHomeScreen
+		setShowWorktreesInHomeScreen(newValue)
+		vscode.postMessage({
+			type: "updateSettings",
+			updatedSettings: { showWorktreesInHomeScreen: newValue },
+		})
+	}, [showWorktreesInHomeScreen, setShowWorktreesInHomeScreen])
+
 	// Render error states
 	if (!isGitRepo) {
 		return (
-			<Tab>
-				<TabHeader className="flex justify-between items-center">
-					<h3 className="text-vscode-foreground m-0">{t("worktrees:title")}</h3>
-					<Button onClick={onDone}>{t("worktrees:done")}</Button>
-				</TabHeader>
-				<TabContent>
-					<div className="flex flex-col items-center justify-center h-48 text-vscode-descriptionForeground">
-						<span className="codicon codicon-warning text-4xl mb-4" />
-						<p className="text-center">{t("worktrees:notGitRepo")}</p>
-					</div>
-				</TabContent>
-			</Tab>
+			<div>
+				<SectionHeader>{t("worktrees:title")}</SectionHeader>
+				<div className="px-5 text-sm">
+					<p className="text-vscode-descriptionForeground">{t("worktrees:description")}</p>
+					<p>{t("worktrees:notGitRepo")}</p>
+				</div>
+			</div>
 		)
 	}
 
 	if (isMultiRoot) {
 		return (
-			<Tab>
-				<TabHeader className="flex justify-between items-center">
-					<h3 className="text-vscode-foreground m-0">{t("worktrees:title")}</h3>
-					<Button onClick={onDone}>{t("worktrees:done")}</Button>
-				</TabHeader>
-				<TabContent>
-					<div className="flex flex-col items-center justify-center h-48 text-vscode-descriptionForeground">
-						<span className="codicon codicon-warning text-4xl mb-4" />
-						<p className="text-center">{t("worktrees:multiRootNotSupported")}</p>
-					</div>
-				</TabContent>
-			</Tab>
+			<div>
+				<SectionHeader>{t("worktrees:title")}</SectionHeader>
+				<div className="px-5 text-sm">
+					<p className="text-vscode-descriptionForeground">{t("worktrees:description")}</p>
+					<p>{t("worktrees:multiRootNotSupported")}</p>
+				</div>
+			</div>
 		)
 	}
 
 	if (isSubfolder) {
 		return (
-			<Tab>
-				<TabHeader className="flex justify-between items-center">
-					<h3 className="text-vscode-foreground m-0">{t("worktrees:title")}</h3>
-					<Button onClick={onDone}>{t("worktrees:done")}</Button>
-				</TabHeader>
-				<TabContent>
-					<div className="flex flex-col items-center justify-center h-48 text-vscode-descriptionForeground">
-						<span className="codicon codicon-warning text-4xl mb-4" />
-						<p className="text-center">{t("worktrees:subfolderNotSupported")}</p>
-						<p className="text-sm mt-2 text-center">
-							{t("worktrees:gitRoot")}:{" "}
-							<code className="bg-vscode-input-background px-2 py-1 rounded">{gitRootPath}</code>
-						</p>
-					</div>
-				</TabContent>
-			</Tab>
+			<div>
+				<SectionHeader>{t("worktrees:title")}</SectionHeader>
+				<div className="px-5 text-sm">
+					<p className="text-vscode-descriptionForeground">{t("worktrees:description")}</p>
+					<p>{t("worktrees:subfolderNotSupported")}</p>
+					<p>
+						{t("worktrees:gitRoot")}:{" "}
+						<code className="bg-vscode-input-background p-1 rounded-md">{gitRootPath}</code>
+					</p>
+				</div>
+			</div>
 		)
 	}
 
 	return (
-		<Tab>
-			<TabHeader className="flex flex-col gap-2">
-				<div className="flex justify-between items-center">
-					<h3 className="text-vscode-foreground m-0">{t("worktrees:title")}</h3>
-					<Button onClick={onDone}>{t("worktrees:done")}</Button>
-				</div>
-				<p className="text-vscode-descriptionForeground text-sm m-0">{t("worktrees:description")}</p>
+		<div className="flex flex-col h-full overflow-hidden">
+			{/* Fixed Header */}
+			<div className="flex-shrink-0">
+				<SectionHeader>{t("worktrees:title")}</SectionHeader>
+				<div className="flex flex-col gap-2 px-5 py-2">
+					<p className="text-vscode-descriptionForeground text-sm m-0">{t("worktrees:description")}</p>
 
-				{/* Worktree include status */}
-				{includeStatus && (
-					<div className="flex items-center gap-2 text-sm">
-						{includeStatus.exists ? (
-							<>
-								<span className="codicon codicon-check text-vscode-charts-green" />
-								<span className="text-vscode-descriptionForeground">
-									{t("worktrees:includeFileExists")}
-								</span>
-							</>
-						) : (
-							<>
-								<span className="codicon codicon-warning text-vscode-charts-yellow" />
-								<span className="text-vscode-descriptionForeground">
-									{t("worktrees:noIncludeFile")}
-								</span>
-								{includeStatus.hasGitignore && (
-									<Button
-										variant="secondary"
-										size="sm"
-										onClick={handleCreateWorktreeInclude}
-										disabled={isCreatingInclude}>
-										{t("worktrees:createFromGitignore")}
-									</Button>
-								)}
-							</>
-						)}
-					</div>
-				)}
-			</TabHeader>
+					{/* Show in Home Screen toggle */}
+					<label
+						className="flex cursor-pointer items-center gap-2 text-sm text-vscode-descriptionForeground"
+						onClick={handleToggleShowInHomeScreen}>
+						<ToggleSwitch checked={showWorktreesInHomeScreen} onChange={handleToggleShowInHomeScreen} />
+						<span>{t("worktrees:showInHomeScreen")}</span>
+					</label>
 
-			<TabContent className="px-2 py-0">
+					{/* New Worktree button */}
+					<Button variant="secondary" className="py-1" onClick={() => setShowCreateModal(true)}>
+						<Plus />
+						{t("worktrees:newWorktree")}
+					</Button>
+				</div>
+			</div>
+
+			{/* Scrollable List Area */}
+			<div className="flex-1 overflow-y-auto px-4 py-2 min-h-0">
 				{isLoading ? (
 					<div className="flex items-center justify-center h-48">
 						<span className="codicon codicon-loading codicon-modifier-spin text-2xl" />
@@ -230,84 +209,105 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => {
 						<p className="text-center">{error}</p>
 					</div>
 				) : (
-					<div className="flex flex-col gap-1 py-2">
+					<div className="flex flex-col gap-1">
 						{worktrees.map((worktree) => (
 							<div
 								key={worktree.path}
-								className={`p-3 rounded-xl border transition-colors ${
+								className={`p-2.5 px-3.5 rounded-xl hover:bg-vscode-list-hoverBackground border border-transparent ${
 									worktree.isCurrent
-										? "border-vscode-focusBorder bg-vscode-list-activeSelectionBackground"
-										: "border-transparent bg-vscode-editor-background hover:bg-vscode-editor-foreground/10"
-								}`}>
-								<div className="flex items-start justify-between">
-									<div className="flex-1 min-w-0">
-										<div className="flex items-center gap-2 flex-wrap">
-											<span className="codicon codicon-git-branch" />
+										? " bg-vscode-list-activeSelectionBackground border-vscode-list-activeSelectionForeground/20"
+										: "cursor-pointer"
+								}`}
+								onClick={
+									worktree.isCurrent ? undefined : () => handleSwitchWorktree(worktree.path, false)
+								}>
+								<div className="flex items-start min-[400px]:items-center justify-between gap-2 flex-col min-[400px]:flex-row overflow-hidden">
+									<div className={`flex-1 min-w-0 ${worktree.isCurrent && "cursor-default"}`}>
+										{/* Info */}
+										<div className="flex items-center gap-2 overflow-hidden">
+											<GitBranch className="size-3 shrink-0" />
 											<span className="font-medium truncate">
 												{worktree.branch ||
 													(worktree.isDetached
 														? t("worktrees:detachedHead")
 														: t("worktrees:noBranch"))}
 											</span>
-											{worktree.isBare && <Badge>{t("worktrees:primary")}</Badge>}
-											{worktree.isCurrent && (
-												<Badge variant="secondary">{t("worktrees:current")}</Badge>
+											{worktree.isBare && (
+												<Badge className="text-[0.7em] -mt-0.25 py-0.5">
+													{t("worktrees:primary")}
+												</Badge>
 											)}
 											{worktree.isLocked && (
 												<StandardTooltip content={worktree.lockReason || t("worktrees:locked")}>
-													<span className="codicon codicon-lock text-vscode-charts-yellow" />
+													<Lock className="text-vscode-charts-yellow" />
 												</StandardTooltip>
 											)}
 										</div>
-										<div className="text-xs text-vscode-descriptionForeground mt-1 truncate">
-											{worktree.path}
+										<div className="flex gap-2 text-xs text-vscode-descriptionForeground mt-1">
+											<Folder className="size-3 shrink-0 mt-0.5" />
+											<span className="truncate">{worktree.path}</span>
 										</div>
 									</div>
 
-									<div className="flex items-center gap-1 ml-2 flex-shrink-0">
-										{!worktree.isCurrent && (
-											<>
-												<StandardTooltip content={t("worktrees:openInCurrentWindow")}>
-													<Button
-														variant="ghost"
-														size="sm"
-														onClick={() => handleSwitchWorktree(worktree.path, false)}>
-														<span className="codicon codicon-window" />
-													</Button>
-												</StandardTooltip>
-												<StandardTooltip content={t("worktrees:openInNewWindow")}>
-													<Button
-														variant="ghost"
-														size="sm"
-														onClick={() => handleSwitchWorktree(worktree.path, true)}>
-														<span className="codicon codicon-empty-window" />
-													</Button>
-												</StandardTooltip>
-											</>
-										)}
-										{!worktree.isBare && !worktree.isCurrent && (
-											<StandardTooltip content={t("worktrees:delete")}>
-												<Button
-													variant="ghost"
-													size="sm"
-													onClick={() => setDeleteWorktree(worktree)}>
-													<span className="codicon codicon-trash text-vscode-errorForeground" />
-												</Button>
-											</StandardTooltip>
-										)}
+									{/* Actions */}
+									<div className="flex items-center gap-1 ml-3 min-[400px]:ml-0 flex-shrink-0">
+										<StandardTooltip content={t("worktrees:openInNewWindow")}>
+											<Button
+												variant="ghost"
+												size="icon"
+												disabled={worktree.isCurrent}
+												onClick={(e) => {
+													e.stopPropagation()
+													handleSwitchWorktree(worktree.path, true)
+												}}>
+												<SquareArrowOutUpRight />
+											</Button>
+										</StandardTooltip>
+
+										<StandardTooltip content={t("worktrees:delete")}>
+											<Button
+												variant="ghost"
+												size="icon"
+												disabled={worktree.isCurrent || worktree.isBare}
+												onClick={(e) => {
+													e.stopPropagation()
+													setDeleteWorktree(worktree)
+												}}>
+												<Trash className="text-destructive" />
+											</Button>
+										</StandardTooltip>
 									</div>
 								</div>
 							</div>
 						))}
+					</div>
+				)}
+			</div>
 
-						{/* New Worktree button */}
-						<Button variant="secondary" className="mt-2" onClick={() => setShowCreateModal(true)}>
-							<span className="codicon codicon-add mr-2" />
-							{t("worktrees:newWorktree")}
-						</Button>
+			{/* Fixed Footer - Settings */}
+			<div className="flex-shrink-0 flex flex-col border-t border-vscode-sideBar-background">
+				{/* Worktree include status */}
+				{includeStatus && (
+					<div className="flex items-center gap-2 text-sm px-5 py-3 justify-between text-vscode-descriptionForeground border-t border-vscode-sideBar-background">
+						{includeStatus.exists ? (
+							<span>{t("worktrees:includeFileExists")}</span>
+						) : (
+							<>
+								<span>{t("worktrees:noIncludeFile")}</span>
+								{includeStatus.hasGitignore && (
+									<Button
+										variant="secondary"
+										size="sm"
+										onClick={handleCreateWorktreeInclude}
+										disabled={isCreatingInclude}>
+										{t("worktrees:createFromGitignore")}
+									</Button>
+								)}
+							</>
+						)}
 					</div>
 				)}
-			</TabContent>
+			</div>
 
 			{/* Create Modal */}
 			{showCreateModal && (
@@ -333,6 +333,6 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => {
 					}}
 				/>
 			)}
-		</Tab>
+		</div>
 	)
 }

+ 0 - 3
webview-ui/src/components/worktrees/index.ts

@@ -1,3 +0,0 @@
-export { WorktreesView } from "./WorktreesView"
-export { CreateWorktreeModal } from "./CreateWorktreeModal"
-export { DeleteWorktreeModal } from "./DeleteWorktreeModal"

+ 5 - 0
webview-ui/src/context/ExtensionStateContext.tsx

@@ -161,6 +161,8 @@ export interface ExtensionStateContextType extends ExtensionState {
 	setIncludeCurrentTime: (value: boolean) => void
 	includeCurrentCost?: boolean
 	setIncludeCurrentCost: (value: boolean) => void
+	showWorktreesInHomeScreen: boolean
+	setShowWorktreesInHomeScreen: (value: boolean) => void
 }
 
 export const ExtensionStateContext = createContext<ExtensionStateContextType | undefined>(undefined)
@@ -621,6 +623,9 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
 		setIncludeCurrentTime,
 		includeCurrentCost,
 		setIncludeCurrentCost,
+		showWorktreesInHomeScreen: state.showWorktreesInHomeScreen ?? true,
+		setShowWorktreesInHomeScreen: (value) =>
+			setState((prevState) => ({ ...prevState, showWorktreesInHomeScreen: value })),
 	}
 
 	return <ExtensionStateContext.Provider value={contextValue}>{children}</ExtensionStateContext.Provider>

+ 1 - 0
webview-ui/src/i18n/locales/ca/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Proveïdors",
 		"modes": "Modes",
 		"mcp": "Servidors MCP",
+		"worktrees": "Worktrees",
 		"autoApprove": "Auto-aprovació",
 		"browser": "Accés a l'ordinador",
 		"checkpoints": "Punts de control",

+ 18 - 7
webview-ui/src/i18n/locales/ca/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "HEAD separat",
 	"noBranch": "Sense branca",
 
-	"openInCurrentWindow": "Obre a la finestra actual",
+	"switchInThisWindow": "Canvia a worktree",
 	"openInNewWindow": "Obre en una finestra nova",
 	"delete": "Suprimeix",
 	"newWorktree": "Worktree nou",
 
 	"createWorktree": "Crea worktree",
-	"createWorktreeDescription": "Crea un worktree nou per treballar en una branca diferent dins del seu propi directori.",
 	"branchName": "Nom de la branca",
 	"createNewBranch": "Crea una branca nova",
 	"checkoutExisting": "Fes checkout d'una branca existent",
@@ -35,8 +34,9 @@
 	"noBranchFound": "No s'ha trobat cap branca",
 	"localBranches": "Branques locals",
 	"remoteBranches": "Branques remotes",
-	"worktreePath": "Camí del worktree",
-	"pathHint": "El camí on es crearà el worktree",
+	"worktreePath": "En",
+	"selectWorktreeLocation": "Selecciona la ubicació del Worktree",
+	"selectFolderForWorktree": "Selecciona carpeta per al worktree nou",
 	"noIncludeFileWarning": "No hi ha cap fitxer .worktreeinclude",
 	"noIncludeFileHint": "Sense un fitxer .worktreeinclude, fitxers com node_modules no es copiaran al worktree nou. Potser hauràs d'executar npm install després de crear-lo.",
 	"create": "Crea",
@@ -46,13 +46,24 @@
 	"cancel": "Cancel·la",
 
 	"deleteWorktree": "Suprimeix worktree",
-	"deleteWorktreeDescription": "Això eliminarà el worktree i tots els seus fitxers.",
 	"deleteWarning": "Aquesta acció no es pot desfer. S'eliminarà:",
-	"deleteWarningBranch": "La branca '{{branch}}' i tots els canvis sense confirmar",
+	"deleteWarningBranch": "La branca i qualsevol canvi sense confirmar",
 	"deleteWarningFiles": "Tots els fitxers del directori del worktree",
+	"deleteNoticeLarge": "Si és un gran repositori, podria trigar una mica.",
 	"forceDelete": "Força la supressió",
 	"worktreeIsLocked": "el worktree està bloquejat",
 	"deleting": "S'està suprimint...",
 
-	"close": "Tanca"
+	"close": "Tanca",
+
+	"showInHomeScreen": "Mostra worktrees a la pantalla d'inici",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Canvia entre worktrees",
+		"description": "Els worktrees de Git et permeten treballar en diverses branques simultàniament. Fes clic per canviar l'espai de treball.",
+		"settings": "Gestiona Worktrees",
+		"info": "Els worktrees de Git et permeten tenir diversos directoris de treball adjunts al mateix repositori."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/de/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Anbieter",
 		"modes": "Modi",
 		"mcp": "MCP-Server",
+		"worktrees": "Worktrees",
 		"autoApprove": "Auto-Genehmigung",
 		"browser": "Computerzugriff",
 		"checkpoints": "Kontrollpunkte",

+ 18 - 7
webview-ui/src/i18n/locales/de/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "Kein Branch",
 
-	"openInCurrentWindow": "Im aktuellen Fenster öffnen",
+	"switchInThisWindow": "Zu Worktree wechseln",
 	"openInNewWindow": "In neuem Fenster öffnen",
 	"delete": "Löschen",
 	"newWorktree": "Neuer Worktree",
 
 	"createWorktree": "Worktree erstellen",
-	"createWorktreeDescription": "Erstelle einen neuen Worktree, um in einem eigenen Verzeichnis an einem separaten Branch zu arbeiten.",
 	"branchName": "Branch-Name",
 	"createNewBranch": "Neuen Branch erstellen",
 	"checkoutExisting": "Vorhandenen Branch auschecken",
@@ -35,8 +34,9 @@
 	"noBranchFound": "Kein Branch gefunden",
 	"localBranches": "Lokale Branches",
 	"remoteBranches": "Remote-Branches",
-	"worktreePath": "Worktree-Pfad",
-	"pathHint": "Der Pfad, in dem der Worktree erstellt wird",
+	"worktreePath": "In",
+	"selectWorktreeLocation": "Worktree-Speicherort auswählen",
+	"selectFolderForWorktree": "Ordner für neuen Worktree auswählen",
 	"noIncludeFileWarning": "Keine .worktreeinclude-Datei",
 	"noIncludeFileHint": "Ohne eine .worktreeinclude-Datei werden Dateien wie node_modules nicht in den neuen Worktree kopiert. Möglicherweise musst du nach dem Erstellen npm install ausführen.",
 	"create": "Erstellen",
@@ -46,13 +46,24 @@
 	"cancel": "Abbrechen",
 
 	"deleteWorktree": "Worktree löschen",
-	"deleteWorktreeDescription": "Dadurch wird der Worktree und alle seine Dateien entfernt.",
 	"deleteWarning": "Diese Aktion kann nicht rückgängig gemacht werden. Folgendes wird gelöscht:",
-	"deleteWarningBranch": "Der Branch '{{branch}}' und alle nicht committeten Änderungen",
+	"deleteWarningBranch": "Der Branch und alle nicht committeten Änderungen",
 	"deleteWarningFiles": "Alle Dateien im Worktree-Verzeichnis",
+	"deleteNoticeLarge": "Bei großen Repositorys kann dies eine Weile dauern.",
 	"forceDelete": "Löschen erzwingen",
 	"worktreeIsLocked": "Worktree ist gesperrt",
 	"deleting": "Wird gelöscht...",
 
-	"close": "Schließen"
+	"close": "Schließen",
+
+	"showInHomeScreen": "Worktrees auf dem Startbildschirm anzeigen",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Zwischen Worktrees wechseln",
+		"description": "Git Worktrees ermöglichen dir, gleichzeitig an mehreren Branches zu arbeiten. Klicke hier, um den Workspace zu wechseln.",
+		"settings": "Worktrees verwalten",
+		"info": "Git Worktrees ermöglichen dir, mehrere Arbeitsverzeichnisse mit demselben Repository zu verbinden."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/en/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Providers",
 		"modes": "Modes",
 		"mcp": "MCP Servers",
+		"worktrees": "Worktrees",
 		"autoApprove": "Auto-Approve",
 		"browser": "Browser",
 		"checkpoints": "Checkpoints",

+ 26 - 15
webview-ui/src/i18n/locales/en/worktrees.json

@@ -1,14 +1,14 @@
 {
 	"title": "Worktrees",
 	"done": "Done",
-	"description": "Git worktrees allow you to work on multiple branches simultaneously in separate directories. Each worktree gets its own VS Code window with Roo Code.",
+	"description": "Git worktrees are great for agentic coding, because they allow you to work on multiple branches of a repo at the same time, by keeping them in different directories. Each worktree gets its own VS Code window with Roo Code.",
 
-	"notGitRepo": "This workspace is not a Git repository. Worktrees require a Git repository to function.",
+	"notGitRepo": "This workspace is not a Git repository. Open a workspace with a Git repository to set up worktrees.",
 	"multiRootNotSupported": "Worktrees are not supported in multi-root workspaces. Please open a single folder to use worktrees.",
 	"subfolderNotSupported": "This workspace is a subfolder of a Git repository. Please open the repository root to use worktrees.",
 	"gitRoot": "Git root",
 
-	"includeFileExists": ".worktreeinclude file found - files will be copied to new worktrees",
+	"includeFileExists": ".worktreeinclude file found. Files will be copied to new worktrees.",
 	"noIncludeFile": "No .worktreeinclude file found",
 	"createFromGitignore": "Create from .gitignore",
 
@@ -18,27 +18,27 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "No branch",
 
-	"openInCurrentWindow": "Open in current window",
+	"switchInThisWindow": "Switch to worktree",
 	"openInNewWindow": "Open in new window",
 	"delete": "Delete",
-	"newWorktree": "New Worktree",
+	"newWorktree": "Create worktree",
 
 	"createWorktree": "Create Worktree",
-	"createWorktreeDescription": "Create a new worktree to work on a separate branch in its own directory.",
-	"branchName": "Branch name",
+	"branchName": "New branch",
 	"createNewBranch": "Create new branch",
 	"checkoutExisting": "Checkout existing branch",
-	"baseBranch": "Base branch",
+	"baseBranch": "From base branch",
 	"loadingBranches": "Loading branches...",
 	"selectBranch": "Select branch",
 	"searchBranch": "Search branches...",
 	"noBranchFound": "No branch found",
 	"localBranches": "Local branches",
 	"remoteBranches": "Remote branches",
-	"worktreePath": "Worktree path",
-	"pathHint": "The path where the worktree will be created",
+	"worktreePath": "In",
+	"selectWorktreeLocation": "Select Worktree Location",
+	"selectFolderForWorktree": "Select folder for new worktree",
 	"noIncludeFileWarning": "No .worktreeinclude file",
-	"noIncludeFileHint": "Without a .worktreeinclude file, files like node_modules won't be copied to the new worktree. You may need to run npm install after creating it.",
+	"noIncludeFileHint": "Worktrees are created with just the files from their branch. If you want to copy over local files like .env and node_modules, include them in a .worktreeinclude file at the root of the repository.",
 	"create": "Create",
 	"creating": "Creating...",
 	"copyingFiles": "Copying files...",
@@ -46,13 +46,24 @@
 	"cancel": "Cancel",
 
 	"deleteWorktree": "Delete Worktree",
-	"deleteWorktreeDescription": "This will remove the worktree and all its files.",
-	"deleteWarning": "This action cannot be undone. The following will be deleted:",
-	"deleteWarningBranch": "The branch '{{branch}}' and all uncommitted changes",
+	"deleteWarning": "This can't be undone. It will delete:",
+	"deleteWarningBranch": "The branch and any uncommitted changes",
 	"deleteWarningFiles": "All files in the worktree directory",
+	"deleteNoticeLarge": "If this is a large repository, it may take a little while.",
 	"forceDelete": "Force delete",
 	"worktreeIsLocked": "worktree is locked",
 	"deleting": "Deleting...",
 
-	"close": "Close"
+	"close": "Close",
+
+	"showInHomeScreen": "Show worktrees in home screen",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Switch between worktrees",
+		"description": "Git worktrees let you work on multiple branches simultaneously. Click to switch workspace.",
+		"settings": "Manage Worktrees",
+		"info": "Git worktrees allow you to have multiple working directories attached to the same repository."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/es/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Proveedores",
 		"modes": "Modos",
 		"mcp": "Servidores MCP",
+		"worktrees": "Worktrees",
 		"autoApprove": "Auto-aprobación",
 		"browser": "Acceso al ordenador",
 		"checkpoints": "Puntos de control",

+ 18 - 7
webview-ui/src/i18n/locales/es/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "HEAD separado",
 	"noBranch": "Sin rama",
 
-	"openInCurrentWindow": "Abrir en la ventana actual",
+	"switchInThisWindow": "Cambiar a worktree",
 	"openInNewWindow": "Abrir en una ventana nueva",
 	"delete": "Eliminar",
 	"newWorktree": "Nuevo Worktree",
 
 	"createWorktree": "Crear Worktree",
-	"createWorktreeDescription": "Crea un worktree nuevo para trabajar en una rama separada en su propio directorio.",
 	"branchName": "Nombre de la rama",
 	"createNewBranch": "Crear rama nueva",
 	"checkoutExisting": "Hacer checkout de una rama existente",
@@ -35,8 +34,9 @@
 	"noBranchFound": "No se encontró ninguna rama",
 	"localBranches": "Ramas locales",
 	"remoteBranches": "Ramas remotas",
-	"worktreePath": "Ruta del worktree",
-	"pathHint": "La ruta donde se creará el worktree",
+	"worktreePath": "En",
+	"selectWorktreeLocation": "Seleccionar ubicación del Worktree",
+	"selectFolderForWorktree": "Seleccionar carpeta para el worktree nuevo",
 	"noIncludeFileWarning": "No hay archivo .worktreeinclude",
 	"noIncludeFileHint": "Sin un archivo .worktreeinclude, archivos como node_modules no se copiarán al worktree nuevo. Puede que tengas que ejecutar npm install después de crearlo.",
 	"create": "Crear",
@@ -46,13 +46,24 @@
 	"cancel": "Cancelar",
 
 	"deleteWorktree": "Eliminar Worktree",
-	"deleteWorktreeDescription": "Esto eliminará el worktree y todos sus archivos.",
 	"deleteWarning": "Esta acción no se puede deshacer. Se eliminará lo siguiente:",
-	"deleteWarningBranch": "La rama '{{branch}}' y todos los cambios sin confirmar",
+	"deleteWarningBranch": "La rama y todos los cambios sin confirmar",
 	"deleteWarningFiles": "Todos los archivos del directorio del worktree",
+	"deleteNoticeLarge": "Si es un repositorio grande, podría tomar un tiempo.",
 	"forceDelete": "Forzar eliminación",
 	"worktreeIsLocked": "el worktree está bloqueado",
 	"deleting": "Eliminando...",
 
-	"close": "Cerrar"
+	"close": "Cerrar",
+
+	"showInHomeScreen": "Mostrar worktrees en la pantalla de inicio",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Cambiar entre worktrees",
+		"description": "Los worktrees de Git te permiten trabajar en varias ramas simultáneamente. Haz clic para cambiar el espacio de trabajo.",
+		"settings": "Gestionar Worktrees",
+		"info": "Los worktrees de Git te permiten tener varios directorios de trabajo adjuntos al mismo repositorio."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/fr/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Fournisseurs",
 		"modes": "Modes",
 		"mcp": "Serveurs MCP",
+		"worktrees": "Worktrees",
 		"autoApprove": "Auto-approbation",
 		"browser": "Accès ordinateur",
 		"checkpoints": "Points de contrôle",

+ 18 - 7
webview-ui/src/i18n/locales/fr/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "HEAD détachée",
 	"noBranch": "Aucune branche",
 
-	"openInCurrentWindow": "Ouvrir dans la fenêtre actuelle",
+	"switchInThisWindow": "Changer vers worktree",
 	"openInNewWindow": "Ouvrir dans une nouvelle fenêtre",
 	"delete": "Supprimer",
 	"newWorktree": "Nouveau Worktree",
 
 	"createWorktree": "Créer un worktree",
-	"createWorktreeDescription": "Crée un worktree pour travailler sur une autre branche dans son propre répertoire.",
 	"branchName": "Nom de la branche",
 	"createNewBranch": "Créer une nouvelle branche",
 	"checkoutExisting": "Checkout d'une branche existante",
@@ -35,8 +34,9 @@
 	"noBranchFound": "Aucune branche trouvée",
 	"localBranches": "Branches locales",
 	"remoteBranches": "Branches distantes",
-	"worktreePath": "Chemin du worktree",
-	"pathHint": "Le chemin où le worktree sera créé",
+	"worktreePath": "En",
+	"selectWorktreeLocation": "Sélectionner l'emplacement du Worktree",
+	"selectFolderForWorktree": "Sélectionner le dossier pour le nouveau worktree",
 	"noIncludeFileWarning": "Aucun fichier .worktreeinclude",
 	"noIncludeFileHint": "Sans fichier .worktreeinclude, des fichiers comme node_modules ne seront pas copiés dans le nouveau worktree. Tu devras peut-être exécuter npm install après l'avoir créé.",
 	"create": "Créer",
@@ -46,13 +46,24 @@
 	"cancel": "Annuler",
 
 	"deleteWorktree": "Supprimer le worktree",
-	"deleteWorktreeDescription": "Cela supprimera le worktree et tous ses fichiers.",
 	"deleteWarning": "Cette action est irréversible. Les éléments suivants seront supprimés :",
-	"deleteWarningBranch": "La branche '{{branch}}' et toutes les modifications non validées",
+	"deleteWarningBranch": "La branche et toutes les modifications non validées",
 	"deleteWarningFiles": "Tous les fichiers dans le répertoire du worktree",
+	"deleteNoticeLarge": "Si c'est un grand dépôt, cela peut prendre un peu de temps.",
 	"forceDelete": "Forcer la suppression",
 	"worktreeIsLocked": "le worktree est verrouillé",
 	"deleting": "Suppression...",
 
-	"close": "Fermer"
+	"close": "Fermer",
+
+	"showInHomeScreen": "Afficher les worktrees sur l'écran d'accueil",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Changer entre les worktrees",
+		"description": "Les worktrees Git te permettent de travailler sur plusieurs branches en même temps. Clique pour changer d'espace de travail.",
+		"settings": "Gérer les Worktrees",
+		"info": "Les worktrees Git te permettent d'avoir plusieurs répertoires de travail attachés au même dépôt."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/hi/settings.json

@@ -29,6 +29,7 @@
 		"providers": "प्रदाता",
 		"modes": "मोड",
 		"mcp": "एमसीपी सर्वर",
+		"worktrees": "Worktrees",
 		"autoApprove": "अनुमोदन",
 		"browser": "ब्राउज़र",
 		"checkpoints": "चेकपॉइंट",

+ 18 - 7
webview-ui/src/i18n/locales/hi/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "कोई ब्रांच नहीं",
 
-	"openInCurrentWindow": "वर्तमान विंडो में खोलें",
+	"switchInThisWindow": "Worktree पर स्विच करें",
 	"openInNewWindow": "नई विंडो में खोलें",
 	"delete": "हटाएँ",
 	"newWorktree": "नया Worktree",
 
 	"createWorktree": "Worktree बनाएँ",
-	"createWorktreeDescription": "अपने अलग डायरेक्टरी में किसी अलग ब्रांच पर काम करने के लिए नया worktree बनाएँ।",
 	"branchName": "ब्रांच नाम",
 	"createNewBranch": "नई ब्रांच बनाएँ",
 	"checkoutExisting": "मौजूदा ब्रांच checkout करें",
@@ -35,8 +34,9 @@
 	"noBranchFound": "कोई ब्रांच नहीं मिली",
 	"localBranches": "लोकल ब्रांच",
 	"remoteBranches": "रिमोट ब्रांच",
-	"worktreePath": "Worktree पाथ",
-	"pathHint": "वह पाथ जहाँ worktree बनाया जाएगा",
+	"worktreePath": "में",
+	"selectWorktreeLocation": "Worktree स्थान चुनें",
+	"selectFolderForWorktree": "नए worktree के लिए फ़ोल्डर चुनें",
 	"noIncludeFileWarning": ".worktreeinclude फ़ाइल नहीं है",
 	"noIncludeFileHint": ".worktreeinclude फ़ाइल के बिना, node_modules जैसी फ़ाइलें नए worktree में कॉपी नहीं होंगी। इसे बनाने के बाद आपको npm install चलाना पड़ सकता है।",
 	"create": "बनाएँ",
@@ -46,13 +46,24 @@
 	"cancel": "रद्द करें",
 
 	"deleteWorktree": "Worktree हटाएँ",
-	"deleteWorktreeDescription": "यह worktree और उसकी सभी फ़ाइलें हटा देगा।",
 	"deleteWarning": "यह कार्रवाई वापस नहीं ली जा सकती। निम्नलिखित हटाया जाएगा:",
-	"deleteWarningBranch": "ब्रांच '{{branch}}' और सभी uncommitted बदलाव",
+	"deleteWarningBranch": "ब्रांच और सभी uncommitted बदलाव",
 	"deleteWarningFiles": "worktree डायरेक्टरी की सभी फ़ाइलें",
+	"deleteNoticeLarge": "अगर यह एक बड़ी रिपोज़िटरी है तो यह कुछ समय ले सकता है।",
 	"forceDelete": "जबरन हटाएँ",
 	"worktreeIsLocked": "worktree लॉक्ड है",
 	"deleting": "हटाया जा रहा है...",
 
-	"close": "बंद करें"
+	"close": "बंद करें",
+
+	"showInHomeScreen": "होम स्क्रीन में worktrees दिखाएँ",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Worktrees के बीच स्विच करें",
+		"description": "Git worktrees आपको एक साथ कई ब्रांच पर काम करने देते हैं। workspace स्विच करने के लिए क्लिक करें।",
+		"settings": "Worktrees को प्रबंधित करें",
+		"info": "Git worktrees आपको एक ही रिपोज़िटरी से जुड़ी कई working directories रखने देते हैं।"
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/id/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Provider",
 		"modes": "Mode",
 		"mcp": "Server MCP",
+		"worktrees": "Worktrees",
 		"autoApprove": "Auto-Approve",
 		"browser": "Browser",
 		"checkpoints": "Checkpoint",

+ 18 - 7
webview-ui/src/i18n/locales/id/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "Tidak ada branch",
 
-	"openInCurrentWindow": "Buka di jendela saat ini",
+	"switchInThisWindow": "Beralih ke worktree",
 	"openInNewWindow": "Buka di jendela baru",
 	"delete": "Hapus",
 	"newWorktree": "Worktree Baru",
 
 	"createWorktree": "Buat Worktree",
-	"createWorktreeDescription": "Buat worktree baru untuk bekerja pada branch terpisah di direktori sendiri.",
 	"branchName": "Nama branch",
 	"createNewBranch": "Buat branch baru",
 	"checkoutExisting": "Checkout branch yang sudah ada",
@@ -35,8 +34,9 @@
 	"noBranchFound": "Branch tidak ditemukan",
 	"localBranches": "Branch lokal",
 	"remoteBranches": "Branch remote",
-	"worktreePath": "Path worktree",
-	"pathHint": "Path tempat worktree akan dibuat",
+	"worktreePath": "Di",
+	"selectWorktreeLocation": "Pilih Lokasi Worktree",
+	"selectFolderForWorktree": "Pilih folder untuk worktree baru",
 	"noIncludeFileWarning": "Tidak ada file .worktreeinclude",
 	"noIncludeFileHint": "Tanpa file .worktreeinclude, file seperti node_modules tidak akan disalin ke worktree baru. Kamu mungkin perlu menjalankan npm install setelah membuatnya.",
 	"create": "Buat",
@@ -46,13 +46,24 @@
 	"cancel": "Batal",
 
 	"deleteWorktree": "Hapus Worktree",
-	"deleteWorktreeDescription": "Ini akan menghapus worktree dan semua filenya.",
 	"deleteWarning": "Tindakan ini tidak dapat dibatalkan. Yang berikut akan dihapus:",
-	"deleteWarningBranch": "Branch '{{branch}}' dan semua perubahan yang belum di-commit",
+	"deleteWarningBranch": "Branch dan semua perubahan yang belum di-commit",
 	"deleteWarningFiles": "Semua file di direktori worktree",
+	"deleteNoticeLarge": "Jika ini adalah repositori besar, mungkin memerlukan waktu beberapa saat.",
 	"forceDelete": "Paksa hapus",
 	"worktreeIsLocked": "worktree terkunci",
 	"deleting": "Menghapus...",
 
-	"close": "Tutup"
+	"close": "Tutup",
+
+	"showInHomeScreen": "Tampilkan worktrees di layar beranda",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Beralih antar worktrees",
+		"description": "Git worktrees memungkinkan kamu bekerja di beberapa branch secara bersamaan. Klik untuk beralih workspace.",
+		"settings": "Kelola Worktrees",
+		"info": "Git worktrees memungkinkan kamu memiliki beberapa direktori kerja yang terhubung ke repositori yang sama."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/it/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Fornitori",
 		"modes": "Modalità",
 		"mcp": "Server MCP",
+		"worktrees": "Worktrees",
 		"autoApprove": "Auto-approvazione",
 		"browser": "Accesso computer",
 		"checkpoints": "Punti di controllo",

+ 18 - 7
webview-ui/src/i18n/locales/it/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "HEAD staccata",
 	"noBranch": "Nessun branch",
 
-	"openInCurrentWindow": "Apri nella finestra corrente",
+	"switchInThisWindow": "Passa a worktree",
 	"openInNewWindow": "Apri in una nuova finestra",
 	"delete": "Elimina",
 	"newWorktree": "Nuovo Worktree",
 
 	"createWorktree": "Crea Worktree",
-	"createWorktreeDescription": "Crea un nuovo worktree per lavorare su un branch separato nella sua directory.",
 	"branchName": "Nome del branch",
 	"createNewBranch": "Crea nuovo branch",
 	"checkoutExisting": "Fai checkout di un branch esistente",
@@ -35,8 +34,9 @@
 	"noBranchFound": "Nessun branch trovato",
 	"localBranches": "Branch locali",
 	"remoteBranches": "Branch remoti",
-	"worktreePath": "Percorso del worktree",
-	"pathHint": "Il percorso in cui verrà creato il worktree",
+	"worktreePath": "In",
+	"selectWorktreeLocation": "Seleziona posizione Worktree",
+	"selectFolderForWorktree": "Seleziona cartella per il nuovo worktree",
 	"noIncludeFileWarning": "Nessun file .worktreeinclude",
 	"noIncludeFileHint": "Senza un file .worktreeinclude, file come node_modules non verranno copiati nel nuovo worktree. Potresti dover eseguire npm install dopo averlo creato.",
 	"create": "Crea",
@@ -46,13 +46,24 @@
 	"cancel": "Annulla",
 
 	"deleteWorktree": "Elimina Worktree",
-	"deleteWorktreeDescription": "Questo rimuoverà il worktree e tutti i suoi file.",
 	"deleteWarning": "Questa azione non può essere annullata. Verrà eliminato quanto segue:",
-	"deleteWarningBranch": "Il branch '{{branch}}' e tutte le modifiche non committate",
+	"deleteWarningBranch": "Il branch e tutte le modifiche non committate",
 	"deleteWarningFiles": "Tutti i file nella directory del worktree",
+	"deleteNoticeLarge": "Se è un repository grande, potrebbe volerci un po'.",
 	"forceDelete": "Forza eliminazione",
 	"worktreeIsLocked": "il worktree è bloccato",
 	"deleting": "Eliminazione...",
 
-	"close": "Chiudi"
+	"close": "Chiudi",
+
+	"showInHomeScreen": "Mostra worktrees nella schermata iniziale",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Passa tra i worktrees",
+		"description": "I worktree di Git ti permettono di lavorare su più branch contemporaneamente. Fai clic per cambiare workspace.",
+		"settings": "Gestisci Worktrees",
+		"info": "I worktree di Git ti permettono di avere più directory di lavoro collegate allo stesso repository."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/ja/settings.json

@@ -29,6 +29,7 @@
 		"providers": "プロバイダー",
 		"modes": "モード",
 		"mcp": "MCPサーバー",
+		"worktrees": "Worktrees",
 		"autoApprove": "自動承認",
 		"browser": "コンピューターアクセス",
 		"checkpoints": "チェックポイント",

+ 18 - 7
webview-ui/src/i18n/locales/ja/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "ブランチなし",
 
-	"openInCurrentWindow": "現在のウィンドウで開く",
+	"switchInThisWindow": "Worktree に切り替え",
 	"openInNewWindow": "新しいウィンドウで開く",
 	"delete": "削除",
 	"newWorktree": "新しい Worktree",
 
 	"createWorktree": "Worktree を作成",
-	"createWorktreeDescription": "別のブランチで作業するために、専用ディレクトリに新しい worktree を作成します。",
 	"branchName": "ブランチ名",
 	"createNewBranch": "新しいブランチを作成",
 	"checkoutExisting": "既存のブランチをチェックアウト",
@@ -35,8 +34,9 @@
 	"noBranchFound": "ブランチが見つかりません",
 	"localBranches": "ローカルブランチ",
 	"remoteBranches": "リモートブランチ",
-	"worktreePath": "Worktree のパス",
-	"pathHint": "worktree を作成するパス",
+	"worktreePath": "In",
+	"selectWorktreeLocation": "Worktree の場所を選択",
+	"selectFolderForWorktree": "新しい worktree のフォルダーを選択",
 	"noIncludeFileWarning": ".worktreeinclude ファイルなし",
 	"noIncludeFileHint": ".worktreeinclude ファイルがない場合、node_modules などのファイルは新しい worktree にコピーされません。作成後に npm install を実行する必要があるかもしれません。",
 	"create": "作成",
@@ -46,13 +46,24 @@
 	"cancel": "キャンセル",
 
 	"deleteWorktree": "Worktree を削除",
-	"deleteWorktreeDescription": "これにより worktree とそのファイルがすべて削除されます。",
 	"deleteWarning": "この操作は元に戻せません。次のものが削除されます:",
-	"deleteWarningBranch": "ブランチ '{{branch}}' と未コミットの変更すべて",
+	"deleteWarningBranch": "ブランチと未コミットの変更すべて",
 	"deleteWarningFiles": "worktree ディレクトリ内のすべてのファイル",
+	"deleteNoticeLarge": "大規模なリポジトリの場合、少し時間がかかる場合があります。",
 	"forceDelete": "強制削除",
 	"worktreeIsLocked": "worktree がロックされています",
 	"deleting": "削除中...",
 
-	"close": "閉じる"
+	"close": "閉じる",
+
+	"showInHomeScreen": "ホーム画面に worktrees を表示",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Worktree を切り替え",
+		"description": "Git worktrees を使うと、複数のブランチで同時に作業できます。クリックしてワークスペースを切り替えます。",
+		"settings": "Worktrees を管理",
+		"info": "Git worktrees を使うと、同じリポジトリに複数の作業ディレクトリを附属できます。"
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/ko/settings.json

@@ -29,6 +29,7 @@
 		"providers": "공급자",
 		"modes": "모드",
 		"mcp": "MCP 서버",
+		"worktrees": "Worktrees",
 		"autoApprove": "자동 승인",
 		"browser": "컴퓨터 접근",
 		"checkpoints": "체크포인트",

+ 18 - 7
webview-ui/src/i18n/locales/ko/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "브랜치 없음",
 
-	"openInCurrentWindow": "현재 창에서 열기",
+	"switchInThisWindow": "Worktree로 전환",
 	"openInNewWindow": "새 창에서 열기",
 	"delete": "삭제",
 	"newWorktree": "새 Worktree",
 
 	"createWorktree": "Worktree 만들기",
-	"createWorktreeDescription": "별도의 브랜치에서 작업하기 위해 전용 디렉터리에 새 worktree를 만듭니다.",
 	"branchName": "브랜치 이름",
 	"createNewBranch": "새 브랜치 만들기",
 	"checkoutExisting": "기존 브랜치 체크아웃",
@@ -35,8 +34,9 @@
 	"noBranchFound": "브랜치를 찾을 수 없습니다",
 	"localBranches": "로컬 브랜치",
 	"remoteBranches": "원격 브랜치",
-	"worktreePath": "Worktree 경로",
-	"pathHint": "worktree가 생성될 경로",
+	"worktreePath": "In",
+	"selectWorktreeLocation": "Worktree 위치 선택",
+	"selectFolderForWorktree": "새 worktree의 폴더 선택",
 	"noIncludeFileWarning": ".worktreeinclude 파일 없음",
 	"noIncludeFileHint": ".worktreeinclude 파일이 없으면 node_modules 같은 파일이 새 worktree로 복사되지 않습니다. 생성 후 npm install을 실행해야 할 수도 있습니다.",
 	"create": "만들기",
@@ -46,13 +46,24 @@
 	"cancel": "취소",
 
 	"deleteWorktree": "Worktree 삭제",
-	"deleteWorktreeDescription": "이 작업은 worktree와 그 안의 모든 파일을 제거합니다.",
 	"deleteWarning": "이 작업은 되돌릴 수 없습니다. 다음이 삭제됩니다:",
-	"deleteWarningBranch": "브랜치 '{{branch}}' 및 커밋되지 않은 모든 변경 사항",
+	"deleteWarningBranch": "브랜치 및 커밋되지 않은 모든 변경 사항",
 	"deleteWarningFiles": "worktree 디렉터리의 모든 파일",
+	"deleteNoticeLarge": "대규모 저장소의 경우 시간이 조금 걸릴 수 있습니다.",
 	"forceDelete": "강제 삭제",
 	"worktreeIsLocked": "worktree가 잠겨 있습니다",
 	"deleting": "삭제 중...",
 
-	"close": "닫기"
+	"close": "닫기",
+
+	"showInHomeScreen": "홈 화면에 worktrees 표시",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Worktree 간 전환",
+		"description": "Git worktree를 사용하면 동시에 여러 브랜치에서 작업할 수 있습니다. 클릭하여 워크스페이스를 전환합니다.",
+		"settings": "Worktree 관리",
+		"info": "Git worktree를 사용하면 동일한 저장소에 여러 작업 디렉터리를 연결할 수 있습니다."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/nl/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Providers",
 		"modes": "Modi",
 		"mcp": "MCP-servers",
+		"worktrees": "Worktrees",
 		"autoApprove": "Auto-goedkeuren",
 		"browser": "Browser",
 		"checkpoints": "Checkpoints",

+ 18 - 7
webview-ui/src/i18n/locales/nl/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "Geen branch",
 
-	"openInCurrentWindow": "Openen in huidig venster",
+	"switchInThisWindow": "Naar worktree wisselen",
 	"openInNewWindow": "Openen in nieuw venster",
 	"delete": "Verwijderen",
 	"newWorktree": "Nieuwe Worktree",
 
 	"createWorktree": "Worktree aanmaken",
-	"createWorktreeDescription": "Maak een nieuwe worktree aan om in een aparte branch in zijn eigen map te werken.",
 	"branchName": "Branchnaam",
 	"createNewBranch": "Nieuwe branch aanmaken",
 	"checkoutExisting": "Bestaande branch uitchecken",
@@ -35,8 +34,9 @@
 	"noBranchFound": "Geen branch gevonden",
 	"localBranches": "Lokale branches",
 	"remoteBranches": "Remote-branches",
-	"worktreePath": "Worktree-pad",
-	"pathHint": "Het pad waar de worktree wordt aangemaakt",
+	"worktreePath": "In",
+	"selectWorktreeLocation": "Locatie Worktree selecteren",
+	"selectFolderForWorktree": "Map voor nieuwe worktree selecteren",
 	"noIncludeFileWarning": "Geen .worktreeinclude-bestand",
 	"noIncludeFileHint": "Zonder een .worktreeinclude-bestand worden bestanden zoals node_modules niet naar de nieuwe worktree gekopieerd. Mogelijk moet je na het aanmaken npm install uitvoeren.",
 	"create": "Aanmaken",
@@ -46,13 +46,24 @@
 	"cancel": "Annuleren",
 
 	"deleteWorktree": "Worktree verwijderen",
-	"deleteWorktreeDescription": "Hiermee wordt de worktree en alle bestanden verwijderd.",
 	"deleteWarning": "Deze actie kan niet ongedaan worden gemaakt. Het volgende wordt verwijderd:",
-	"deleteWarningBranch": "De branch '{{branch}}' en alle niet-gecommitte wijzigingen",
+	"deleteWarningBranch": "De branch en alle niet-gecommitte wijzigingen",
 	"deleteWarningFiles": "Alle bestanden in de worktree-map",
+	"deleteNoticeLarge": "Als dit een grote repository is, kan dit even duren.",
 	"forceDelete": "Geforceerd verwijderen",
 	"worktreeIsLocked": "worktree is vergrendeld",
 	"deleting": "Bezig met verwijderen...",
 
-	"close": "Sluiten"
+	"close": "Sluiten",
+
+	"showInHomeScreen": "Worktrees weergeven op startscherm",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Tussen worktrees wisselen",
+		"description": "Met Git worktrees kun je tegelijkertijd aan meerdere branches werken. Klik om van workspace te wisselen.",
+		"settings": "Worktrees beheren",
+		"info": "Met Git worktrees kun je meerdere werkdirectories aan dezelfde repository koppelen."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/pl/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Dostawcy",
 		"modes": "Tryby",
 		"mcp": "Serwery MCP",
+		"worktrees": "Worktrees",
 		"autoApprove": "Auto-zatwierdzanie",
 		"browser": "Dostęp komputera",
 		"checkpoints": "Punkty kontrolne",

+ 18 - 7
webview-ui/src/i18n/locales/pl/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "Brak brancha",
 
-	"openInCurrentWindow": "Otwórz w bieżącym oknie",
+	"switchInThisWindow": "Przełącz na worktree",
 	"openInNewWindow": "Otwórz w nowym oknie",
 	"delete": "Usuń",
 	"newWorktree": "Nowy Worktree",
 
 	"createWorktree": "Utwórz Worktree",
-	"createWorktreeDescription": "Utwórz nowy worktree, aby pracować na oddzielnym branchu w osobnym katalogu.",
 	"branchName": "Nazwa brancha",
 	"createNewBranch": "Utwórz nowy branch",
 	"checkoutExisting": "Checkout istniejącego brancha",
@@ -35,8 +34,9 @@
 	"noBranchFound": "Nie znaleziono brancha",
 	"localBranches": "Branche lokalne",
 	"remoteBranches": "Branche zdalne",
-	"worktreePath": "Ścieżka worktree",
-	"pathHint": "Ścieżka, w której zostanie utworzony worktree",
+	"worktreePath": "W",
+	"selectWorktreeLocation": "Wybierz lokalizację Worktree",
+	"selectFolderForWorktree": "Wybierz folder dla nowego worktree",
 	"noIncludeFileWarning": "Brak pliku .worktreeinclude",
 	"noIncludeFileHint": "Bez pliku .worktreeinclude pliki takie jak node_modules nie zostaną skopiowane do nowego worktree. Po utworzeniu może być konieczne uruchomienie npm install.",
 	"create": "Utwórz",
@@ -46,13 +46,24 @@
 	"cancel": "Anuluj",
 
 	"deleteWorktree": "Usuń Worktree",
-	"deleteWorktreeDescription": "To usunie worktree oraz wszystkie jego pliki.",
 	"deleteWarning": "Tej akcji nie można cofnąć. Zostanie usunięte:",
-	"deleteWarningBranch": "Branch '{{branch}}' i wszystkie niezatwierdzone zmiany",
+	"deleteWarningBranch": "Branch i wszystkie niezatwierdzone zmiany",
 	"deleteWarningFiles": "Wszystkie pliki w katalogu worktree",
+	"deleteNoticeLarge": "Jeśli jest to duże repozytorium, może to chwilę potrwać.",
 	"forceDelete": "Wymuś usunięcie",
 	"worktreeIsLocked": "worktree jest zablokowany",
 	"deleting": "Usuwanie...",
 
-	"close": "Zamknij"
+	"close": "Zamknij",
+
+	"showInHomeScreen": "Pokaż worktrees na ekranie głównym",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Przełączaj się między worktrees",
+		"description": "Git worktrees pozwalają pracować jednocześnie na wielu branchach. Kliknij, aby zmienić workspace.",
+		"settings": "Zarządzaj Worktrees",
+		"info": "Git worktrees pozwalają mieć wiele katalogów roboczych dołączonych do tego samego repozytorium."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/pt-BR/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Provedores",
 		"modes": "Modos",
 		"mcp": "Servidores MCP",
+		"worktrees": "Worktrees",
 		"autoApprove": "Aprovação",
 		"browser": "Navegador",
 		"checkpoints": "Checkpoints",

+ 18 - 7
webview-ui/src/i18n/locales/pt-BR/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "Sem branch",
 
-	"openInCurrentWindow": "Abrir na janela atual",
+	"switchInThisWindow": "Mudar para worktree",
 	"openInNewWindow": "Abrir em uma nova janela",
 	"delete": "Excluir",
 	"newWorktree": "Novo Worktree",
 
 	"createWorktree": "Criar Worktree",
-	"createWorktreeDescription": "Crie um novo worktree para trabalhar em um branch separado no seu próprio diretório.",
 	"branchName": "Nome do branch",
 	"createNewBranch": "Criar novo branch",
 	"checkoutExisting": "Fazer checkout de um branch existente",
@@ -35,8 +34,9 @@
 	"noBranchFound": "Nenhum branch encontrado",
 	"localBranches": "Branches locais",
 	"remoteBranches": "Branches remotos",
-	"worktreePath": "Caminho do worktree",
-	"pathHint": "O caminho onde o worktree será criado",
+	"worktreePath": "Em",
+	"selectWorktreeLocation": "Selecionar local do Worktree",
+	"selectFolderForWorktree": "Selecionar pasta para o novo worktree",
 	"noIncludeFileWarning": "Sem arquivo .worktreeinclude",
 	"noIncludeFileHint": "Sem um arquivo .worktreeinclude, arquivos como node_modules não serão copiados para o novo worktree. Você pode precisar executar npm install depois de criá-lo.",
 	"create": "Criar",
@@ -46,13 +46,24 @@
 	"cancel": "Cancelar",
 
 	"deleteWorktree": "Excluir Worktree",
-	"deleteWorktreeDescription": "Isso removerá o worktree e todos os seus arquivos.",
 	"deleteWarning": "Esta ação não pode ser desfeita. O seguinte será excluído:",
-	"deleteWarningBranch": "O branch '{{branch}}' e todas as alterações não commitadas",
+	"deleteWarningBranch": "O branch e todas as alterações não commitadas",
 	"deleteWarningFiles": "Todos os arquivos no diretório do worktree",
+	"deleteNoticeLarge": "Se for um repositório grande, pode levar um pouco.",
 	"forceDelete": "Forçar exclusão",
 	"worktreeIsLocked": "worktree está bloqueado",
 	"deleting": "Excluindo...",
 
-	"close": "Fechar"
+	"close": "Fechar",
+
+	"showInHomeScreen": "Mostrar worktrees na tela inicial",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Alterne entre worktrees",
+		"description": "Os worktrees do Git permitem trabalhar em vários branches simultaneamente. Clique para alternar o workspace.",
+		"settings": "Gerenciar Worktrees",
+		"info": "Os worktrees do Git permitem ter vários diretórios de trabalho conectados ao mesmo repositório."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/ru/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Провайдеры",
 		"modes": "Режимы",
 		"mcp": "Серверы MCP",
+		"worktrees": "Worktrees",
 		"autoApprove": "Автоодобрение",
 		"browser": "Доступ к компьютеру",
 		"checkpoints": "Контрольные точки",

+ 18 - 7
webview-ui/src/i18n/locales/ru/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "Нет ветки",
 
-	"openInCurrentWindow": "Открыть в текущем окне",
+	"switchInThisWindow": "Перейти на worktree",
 	"openInNewWindow": "Открыть в новом окне",
 	"delete": "Удалить",
 	"newWorktree": "Новый Worktree",
 
 	"createWorktree": "Создать Worktree",
-	"createWorktreeDescription": "Создай новый worktree, чтобы работать с отдельной веткой в своём каталоге.",
 	"branchName": "Имя ветки",
 	"createNewBranch": "Создать новую ветку",
 	"checkoutExisting": "Переключиться на существующую ветку",
@@ -35,8 +34,9 @@
 	"noBranchFound": "Ветка не найдена",
 	"localBranches": "Локальные ветки",
 	"remoteBranches": "Удалённые ветки",
-	"worktreePath": "Путь worktree",
-	"pathHint": "Путь, где будет создан worktree",
+	"worktreePath": "В",
+	"selectWorktreeLocation": "Выбрать расположение Worktree",
+	"selectFolderForWorktree": "Выбрать папку для нового worktree",
 	"noIncludeFileWarning": "Нет файла .worktreeinclude",
 	"noIncludeFileHint": "Без файла .worktreeinclude файлы вроде node_modules не будут скопированы в новый worktree. Возможно, после создания нужно будет выполнить npm install.",
 	"create": "Создать",
@@ -46,13 +46,24 @@
 	"cancel": "Отмена",
 
 	"deleteWorktree": "Удалить Worktree",
-	"deleteWorktreeDescription": "Это удалит worktree и все его файлы.",
 	"deleteWarning": "Это действие нельзя отменить. Будет удалено:",
-	"deleteWarningBranch": "Ветка '{{branch}}' и все незакоммиченные изменения",
+	"deleteWarningBranch": "Ветка и все незакоммиченные изменения",
 	"deleteWarningFiles": "Все файлы в каталоге worktree",
+	"deleteNoticeLarge": "Если это большой репозиторий, это может занять некоторое время.",
 	"forceDelete": "Удалить принудительно",
 	"worktreeIsLocked": "worktree заблокирован",
 	"deleting": "Удаление...",
 
-	"close": "Закрыть"
+	"close": "Закрыть",
+
+	"showInHomeScreen": "Показывать worktrees на главном экране",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Переключайтесь между worktrees",
+		"description": "Git worktrees позволяют работать с несколькими ветками одновременно. Нажми, чтобы переключить workspace.",
+		"settings": "Управление Worktrees",
+		"info": "Git worktrees позволяют иметь несколько рабочих каталогов, подключенных к одному репозиторию."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/tr/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Sağlayıcılar",
 		"modes": "Modlar",
 		"mcp": "MCP Sunucuları",
+		"worktrees": "Worktrees",
 		"autoApprove": "Oto-Onay",
 		"browser": "Bilgisayar Erişimi",
 		"checkpoints": "Kontrol Noktaları",

+ 18 - 7
webview-ui/src/i18n/locales/tr/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "Branch yok",
 
-	"openInCurrentWindow": "Mevcut pencerede aç",
+	"switchInThisWindow": "Worktree'ye geç",
 	"openInNewWindow": "Yeni pencerede aç",
 	"delete": "Sil",
 	"newWorktree": "Yeni Worktree",
 
 	"createWorktree": "Worktree oluştur",
-	"createWorktreeDescription": "Kendi dizininde ayrı bir branch üzerinde çalışmak için yeni bir worktree oluştur.",
 	"branchName": "Branch adı",
 	"createNewBranch": "Yeni branch oluştur",
 	"checkoutExisting": "Mevcut branch'i checkout et",
@@ -35,8 +34,9 @@
 	"noBranchFound": "Branch bulunamadı",
 	"localBranches": "Yerel branch'ler",
 	"remoteBranches": "Uzak branch'ler",
-	"worktreePath": "Worktree yolu",
-	"pathHint": "Worktree'nin oluşturulacağı yol",
+	"worktreePath": "In",
+	"selectWorktreeLocation": "Worktree Konumunu Seç",
+	"selectFolderForWorktree": "Yeni worktree için klasör seç",
 	"noIncludeFileWarning": ".worktreeinclude dosyası yok",
 	"noIncludeFileHint": ".worktreeinclude dosyası olmadan node_modules gibi dosyalar yeni worktree'ye kopyalanmaz. Oluşturduktan sonra npm install çalıştırman gerekebilir.",
 	"create": "Oluştur",
@@ -46,13 +46,24 @@
 	"cancel": "İptal",
 
 	"deleteWorktree": "Worktree'yi sil",
-	"deleteWorktreeDescription": "Bu işlem worktree'yi ve tüm dosyalarını kaldırır.",
 	"deleteWarning": "Bu işlem geri alınamaz. Şunlar silinecek:",
-	"deleteWarningBranch": "'{{branch}}' branch'i ve commit edilmemiş tüm değişiklikler",
+	"deleteWarningBranch": "Branch'i ve commit edilmemiş tüm değişiklikler",
 	"deleteWarningFiles": "worktree dizinindeki tüm dosyalar",
+	"deleteNoticeLarge": "Bu büyük bir depo ise, biraz zaman alabilir.",
 	"forceDelete": "Silmeye zorla",
 	"worktreeIsLocked": "worktree kilitli",
 	"deleting": "Siliniyor...",
 
-	"close": "Kapat"
+	"close": "Kapat",
+
+	"showInHomeScreen": "Ana ekranda worktrees göster",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Worktree'ler arasında geç",
+		"description": "Git worktree'leri aynı anda birden fazla branch'te çalışmanı sağlar. Workspace'i değiştirmek için tıkla.",
+		"settings": "Worktree'leri Yönet",
+		"info": "Git worktree'leri aynı depo ile bağlantılı birden fazla çalışma dizinine sahip olmanı sağlar."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/vi/settings.json

@@ -29,6 +29,7 @@
 		"providers": "Nhà cung cấp",
 		"modes": "Chế độ",
 		"mcp": "Máy chủ MCP",
+		"worktrees": "Worktrees",
 		"autoApprove": "Phê duyệt",
 		"browser": "Trình duyệt",
 		"checkpoints": "Điểm kiểm tra",

+ 18 - 7
webview-ui/src/i18n/locales/vi/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "Không có nhánh",
 
-	"openInCurrentWindow": "Mở trong cửa sổ hiện tại",
+	"switchInThisWindow": "Chuyển sang worktree",
 	"openInNewWindow": "Mở trong cửa sổ mới",
 	"delete": "Xóa",
 	"newWorktree": "Worktree Mới",
 
 	"createWorktree": "Tạo Worktree",
-	"createWorktreeDescription": "Tạo worktree mới để làm việc trên một nhánh riêng trong thư mục riêng của nó.",
 	"branchName": "Tên nhánh",
 	"createNewBranch": "Tạo nhánh mới",
 	"checkoutExisting": "Checkout nhánh hiện có",
@@ -35,8 +34,9 @@
 	"noBranchFound": "Không tìm thấy nhánh",
 	"localBranches": "Nhánh cục bộ",
 	"remoteBranches": "Nhánh từ xa",
-	"worktreePath": "Đường dẫn worktree",
-	"pathHint": "Đường dẫn nơi worktree sẽ được tạo",
+	"worktreePath": "Trong",
+	"selectWorktreeLocation": "Chọn vị trí Worktree",
+	"selectFolderForWorktree": "Chọn thư mục cho worktree mới",
 	"noIncludeFileWarning": "Không có tệp .worktreeinclude",
 	"noIncludeFileHint": "Không có tệp .worktreeinclude thì các tệp như node_modules sẽ không được sao chép sang worktree mới. Bạn có thể cần chạy npm install sau khi tạo.",
 	"create": "Tạo",
@@ -46,13 +46,24 @@
 	"cancel": "Hủy",
 
 	"deleteWorktree": "Xóa Worktree",
-	"deleteWorktreeDescription": "Thao tác này sẽ xóa worktree và tất cả các tệp của nó.",
 	"deleteWarning": "Không thể hoàn tác thao tác này. Những thứ sau sẽ bị xóa:",
-	"deleteWarningBranch": "Nhánh '{{branch}}' và tất cả thay đổi chưa commit",
+	"deleteWarningBranch": "Nhánh và tất cả thay đổi chưa commit",
 	"deleteWarningFiles": "Tất cả tệp trong thư mục worktree",
+	"deleteNoticeLarge": "Nếu đây là kho lớn, có thể mất một chút thời gian.",
 	"forceDelete": "Buộc xóa",
 	"worktreeIsLocked": "worktree đang bị khóa",
 	"deleting": "Đang xóa...",
 
-	"close": "Đóng"
+	"close": "Đóng",
+
+	"showInHomeScreen": "Hiển thị worktrees trên màn hình chính",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "Chuyển đổi giữa các worktrees",
+		"description": "Git worktrees cho phép bạn làm việc trên nhiều nhánh cùng lúc. Nhấp để chuyển workspace.",
+		"settings": "Quản lý Worktrees",
+		"info": "Git worktrees cho phép bạn có nhiều thư mục làm việc được kết nối với cùng một kho."
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/zh-CN/settings.json

@@ -29,6 +29,7 @@
 		"providers": "提供商",
 		"modes": "模式",
 		"mcp": "MCP 服务",
+		"worktrees": "Worktrees",
 		"autoApprove": "自动批准",
 		"browser": "计算机交互",
 		"checkpoints": "存档点",

+ 18 - 7
webview-ui/src/i18n/locales/zh-CN/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "无分支",
 
-	"openInCurrentWindow": "在当前窗口打开",
+	"switchInThisWindow": "切换到 worktree",
 	"openInNewWindow": "在新窗口打开",
 	"delete": "删除",
 	"newWorktree": "新建 Worktree",
 
 	"createWorktree": "创建 Worktree",
-	"createWorktreeDescription": "创建一个新的 worktree,在独立目录中处理单独的分支。",
 	"branchName": "分支名称",
 	"createNewBranch": "创建新分支",
 	"checkoutExisting": "Checkout 现有分支",
@@ -35,8 +34,9 @@
 	"noBranchFound": "未找到分支",
 	"localBranches": "本地分支",
 	"remoteBranches": "远程分支",
-	"worktreePath": "Worktree 路径",
-	"pathHint": "worktree 将创建到的路径",
+	"worktreePath": "在",
+	"selectWorktreeLocation": "选择 Worktree 位置",
+	"selectFolderForWorktree": "为新 worktree 选择文件夹",
 	"noIncludeFileWarning": "没有 .worktreeinclude 文件",
 	"noIncludeFileHint": "没有 .worktreeinclude 文件时,node_modules 等文件不会复制到新 worktree。创建后你可能需要运行 npm install。",
 	"create": "创建",
@@ -46,13 +46,24 @@
 	"cancel": "取消",
 
 	"deleteWorktree": "删除 Worktree",
-	"deleteWorktreeDescription": "这将删除 worktree 及其所有文件。",
 	"deleteWarning": "此操作不可逆。将删除以下内容:",
-	"deleteWarningBranch": "分支 '{{branch}}' 以及所有未提交的更改",
+	"deleteWarningBranch": "分支以及所有未提交的更改",
 	"deleteWarningFiles": "worktree 目录中的所有文件",
+	"deleteNoticeLarge": "如果这是一个大型仓库,可能需要一些时间。",
 	"forceDelete": "强制删除",
 	"worktreeIsLocked": "worktree 已锁定",
 	"deleting": "正在删除...",
 
-	"close": "关闭"
+	"close": "关闭",
+
+	"showInHomeScreen": "在主屏幕显示 worktrees",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "在 worktrees 之间切换",
+		"description": "Git worktrees 让你能在多个分支上同时工作。点击以切换 workspace。",
+		"settings": "管理 Worktrees",
+		"info": "Git worktrees 允许你将多个工作目录连接到同一个仓库。"
+	}
 }

+ 1 - 0
webview-ui/src/i18n/locales/zh-TW/settings.json

@@ -29,6 +29,7 @@
 		"providers": "供應商",
 		"modes": "模式",
 		"mcp": "MCP 伺服器",
+		"worktrees": "Worktrees",
 		"autoApprove": "自動核准",
 		"browser": "電腦存取",
 		"checkpoints": "檢查點",

+ 18 - 7
webview-ui/src/i18n/locales/zh-TW/worktrees.json

@@ -18,13 +18,12 @@
 	"detachedHead": "Detached HEAD",
 	"noBranch": "無分支",
 
-	"openInCurrentWindow": "在目前視窗開啟",
+	"switchInThisWindow": "切換到 worktree",
 	"openInNewWindow": "在新視窗開啟",
 	"delete": "刪除",
 	"newWorktree": "新增 Worktree",
 
 	"createWorktree": "建立 Worktree",
-	"createWorktreeDescription": "建立新的 worktree,讓你在獨立目錄中處理單獨的分支。",
 	"branchName": "分支名稱",
 	"createNewBranch": "建立新分支",
 	"checkoutExisting": "Checkout 現有分支",
@@ -35,8 +34,9 @@
 	"noBranchFound": "找不到分支",
 	"localBranches": "本機分支",
 	"remoteBranches": "遠端分支",
-	"worktreePath": "Worktree 路徑",
-	"pathHint": "worktree 將建立到的路徑",
+	"worktreePath": "位於",
+	"selectWorktreeLocation": "選取 Worktree 位置",
+	"selectFolderForWorktree": "為新 worktree 選取資料夾",
 	"noIncludeFileWarning": "沒有 .worktreeinclude 檔案",
 	"noIncludeFileHint": "沒有 .worktreeinclude 檔案時,node_modules 等檔案不會複製到新的 worktree。建立後你可能需要執行 npm install。",
 	"create": "建立",
@@ -46,13 +46,24 @@
 	"cancel": "取消",
 
 	"deleteWorktree": "刪除 Worktree",
-	"deleteWorktreeDescription": "這會刪除 worktree 及其所有檔案。",
 	"deleteWarning": "此操作無法復原。將刪除以下內容:",
-	"deleteWarningBranch": "分支 '{{branch}}' 以及所有未提交的變更",
+	"deleteWarningBranch": "分支以及所有未提交的變更",
 	"deleteWarningFiles": "worktree 目錄中的所有檔案",
+	"deleteNoticeLarge": "如果這是大型儲存庫,可能需要一些時間。",
 	"forceDelete": "強制刪除",
 	"worktreeIsLocked": "worktree 已鎖定",
 	"deleting": "正在刪除...",
 
-	"close": "關閉"
+	"close": "關閉",
+
+	"showInHomeScreen": "在主畫面顯示 worktrees",
+
+	"selector": {
+		"worktree": "Worktree",
+		"title": "Worktrees",
+		"tooltip": "在 worktrees 之間切換",
+		"description": "Git worktrees 讓你能在多個分支上同時工作。點選以切換工作區。",
+		"settings": "管理 Worktrees",
+		"info": "Git worktrees 允許你將多個工作目錄連線到同一個儲存庫。"
+	}
 }

+ 1 - 1
webview-ui/src/index.css

@@ -163,7 +163,7 @@
 		--accent: var(--vscode-list-hoverBackground);
 		--accent-foreground: var(--vscode-list-hoverForeground);
 		--destructive: var(--vscode-errorForeground);
-		--destructive-foreground: var(--vscode-button-foreground);
+		--destructive-foreground: var(--vscode-editor-background);
 		--border: var(--vscode-input-border, transparent); /* --border gets theme value or transparent fallback */
 		--input: var(--vscode-input-background);
 		--ring: var(--vscode-input-border);