From 83f21510f33a13bfcf2dd099a1b52169f9c528d2 Mon Sep 17 00:00:00 2001 From: centdix Date: Sat, 21 Feb 2026 21:19:34 +0000 Subject: [PATCH] feat: add open in Cursor button with SSH remote support Co-Authored-By: Claude Opus 4.6 --- dev-dashboard/backend/src/server.ts | 1 + dev-dashboard/frontend/src/App.svelte | 16 ++++++ .../frontend/src/lib/SettingsDialog.svelte | 56 +++++++++++++++++++ dev-dashboard/frontend/src/lib/TopBar.svelte | 19 ++++++- dev-dashboard/frontend/src/lib/types.ts | 1 + 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 dev-dashboard/frontend/src/lib/SettingsDialog.svelte diff --git a/dev-dashboard/backend/src/server.ts b/dev-dashboard/backend/src/server.ts index 05c3d6422c..2cae1fa486 100644 --- a/dev-dashboard/backend/src/server.ts +++ b/dev-dashboard/backend/src/server.ts @@ -178,6 +178,7 @@ async function handleApi(req: Request, url: URL): Promise { ]); return { ...wt, + dir: wtDir ?? null, status: st?.status ?? "", elapsed: st?.elapsed ?? "", title: st?.title ?? "", diff --git a/dev-dashboard/frontend/src/App.svelte b/dev-dashboard/frontend/src/App.svelte index d097ecdb3d..da2cc82c60 100644 --- a/dev-dashboard/frontend/src/App.svelte +++ b/dev-dashboard/frontend/src/App.svelte @@ -5,6 +5,7 @@ import Terminal from "./lib/Terminal.svelte"; import ConfirmDialog from "./lib/ConfirmDialog.svelte"; import CreateWorktreeDialog from "./lib/CreateWorktreeDialog.svelte"; + import SettingsDialog from "./lib/SettingsDialog.svelte"; import type { WorktreeInfo } from "./lib/types"; import type { Profile, Agent } from "./lib/api"; import * as api from "./lib/api"; @@ -13,8 +14,11 @@ let selectedBranch = $state(null); let removeBranch = $state(null); let removingBranches = $state>(new Set()); + const SSH_STORAGE_KEY = "wt-ssh-host"; let showCreateDialog = $state(false); + let showSettingsDialog = $state(false); let creating = $state(false); + let sshHost = $state(localStorage.getItem(SSH_STORAGE_KEY) ?? ""); let visibleWorktrees = $derived( worktrees.filter((w) => w.path === "(here)" || w.branch === "main" || w.mux === "✓") @@ -145,6 +149,10 @@
NavigateCmd+Up/Down
New worktreeCmd+K
RemoveCmd+D
+ @@ -152,6 +160,7 @@ { if (selectedBranch) removeBranch = selectedBranch; }} /> @@ -188,3 +197,10 @@ oncancel={() => (removeBranch = null)} /> {/if} + +{#if showSettingsDialog} + { sshHost = host; showSettingsDialog = false; }} + onclose={() => (showSettingsDialog = false)} + /> +{/if} diff --git a/dev-dashboard/frontend/src/lib/SettingsDialog.svelte b/dev-dashboard/frontend/src/lib/SettingsDialog.svelte new file mode 100644 index 0000000000..83a6512271 --- /dev/null +++ b/dev-dashboard/frontend/src/lib/SettingsDialog.svelte @@ -0,0 +1,56 @@ + + + +
{ e.preventDefault(); handleSave(); }}> +

Settings

+
+ + +

+ Must match an entry in your local ~/.ssh/config. Leave empty for local mode. +

+
+
+ + +
+
+
diff --git a/dev-dashboard/frontend/src/lib/TopBar.svelte b/dev-dashboard/frontend/src/lib/TopBar.svelte index 131bce3dff..cd24437e3d 100644 --- a/dev-dashboard/frontend/src/lib/TopBar.svelte +++ b/dev-dashboard/frontend/src/lib/TopBar.svelte @@ -1,12 +1,22 @@ @@ -29,6 +39,13 @@ class="text-[11px] px-1.5 py-0.5 rounded border font-mono no-underline hover:opacity-80 {worktree.frontendRunning ? 'text-success border-success/40' : 'text-muted border-edge pointer-events-none'}" >FE :{worktree.frontendPort} {/if} + {#if cursorUrl} + Cursor + {/if} {#if name}
diff --git a/dev-dashboard/frontend/src/lib/types.ts b/dev-dashboard/frontend/src/lib/types.ts index 569974ba33..911ae94f02 100644 --- a/dev-dashboard/frontend/src/lib/types.ts +++ b/dev-dashboard/frontend/src/lib/types.ts @@ -3,6 +3,7 @@ export interface WorktreeInfo { agent: string; mux: string; path: string; + dir: string | null; status: string; elapsed: string; title: string;