diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index 9d765fc..5584f84 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -21,7 +21,10 @@
"Bash(git -C /home/naps62/tea/maestro push)",
"Bash(curl:*)",
"Bash(nix build:*)",
- "Bash(cargo fmt:*)"
+ "Bash(cargo fmt:*)",
+ "Skill(impeccable)",
+ "Skill(impeccable:*)",
+ "Bash(node:*)"
]
}
}
diff --git a/web/src/App.tsx b/web/src/App.tsx
index 1b58c27..d880949 100644
--- a/web/src/App.tsx
+++ b/web/src/App.tsx
@@ -314,6 +314,7 @@ function Shell() {
activeId={focusedSessionId}
openIds={openIds}
previewId={previewedSessionId}
+ linkStore={linkStore}
onSelect={(id) => focusSession(id)}
onPreview={preview}
onSpawn={openPlainSpawn}
diff --git a/web/src/components/dialogs/HelpOverlay.tsx b/web/src/components/dialogs/HelpOverlay.tsx
index f9a680c..66d2827 100644
--- a/web/src/components/dialogs/HelpOverlay.tsx
+++ b/web/src/components/dialogs/HelpOverlay.tsx
@@ -6,6 +6,7 @@ import { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { CommandSet, defineCommands, keyCaps } from "../../commands.js";
+import { TOGGLE_HELP_EVENT } from "../../uiEvents.js";
import { groupedCommands } from "./model.js";
export function HelpOverlay() {
@@ -18,8 +19,13 @@ export function HelpOverlay() {
if (open && overlayKeys.handle(e)) return;
helpKeys.handle(e);
};
+ const onToggle = () => setOpen((o) => !o);
window.addEventListener("keydown", onKeydown);
- return () => window.removeEventListener("keydown", onKeydown);
+ document.addEventListener(TOGGLE_HELP_EVENT, onToggle);
+ return () => {
+ window.removeEventListener("keydown", onKeydown);
+ document.removeEventListener(TOGGLE_HELP_EVENT, onToggle);
+ };
}, [open]);
if (!open) return null;
diff --git a/web/src/components/sidebar/SessionCard.tsx b/web/src/components/sidebar/SessionCard.tsx
index f429b3f..0411c18 100644
--- a/web/src/components/sidebar/SessionCard.tsx
+++ b/web/src/components/sidebar/SessionCard.tsx
@@ -62,7 +62,7 @@ export function SessionCard(props: SessionCardProps) {
return (
-
+
{renaming ? (
) : (
{name}
)}
-
+
-
-
- Spawn
-
-
+ {!externalSubmit && (
+
+
+ Spawn
+
+
+ )}
);
}
diff --git a/web/src/components/spawn/SpawnModal.tsx b/web/src/components/spawn/SpawnModal.tsx
index 696d529..b33aae6 100644
--- a/web/src/components/spawn/SpawnModal.tsx
+++ b/web/src/components/spawn/SpawnModal.tsx
@@ -64,16 +64,23 @@ export function SpawnModal({ seed, onSuccess, onClose }: SpawnModalProps) {
-
+
Cancel
+
+ Spawn
+
,
diff --git a/web/src/contexts/ThemeContext.tsx b/web/src/contexts/ThemeContext.tsx
index 7589cde..2362069 100644
--- a/web/src/contexts/ThemeContext.tsx
+++ b/web/src/contexts/ThemeContext.tsx
@@ -26,15 +26,23 @@ export type Palette = (typeof PALETTES)[number];
const PALETTE_KEY = "maestro-palette";
function storedTheme(): Theme | null {
- const v = localStorage.getItem(THEME_KEY);
- return v === "light" || v === "dark" ? v : null;
+ try {
+ const v = localStorage.getItem(THEME_KEY);
+ return v === "light" || v === "dark" ? v : null;
+ } catch {
+ return null;
+ }
}
function storedPalette(): Palette | null {
- const v = localStorage.getItem(PALETTE_KEY);
- return (PALETTES as readonly string[]).includes(v ?? "")
- ? (v as Palette)
- : null;
+ try {
+ const v = localStorage.getItem(PALETTE_KEY);
+ return (PALETTES as readonly string[]).includes(v ?? "")
+ ? (v as Palette)
+ : null;
+ } catch {
+ return null;
+ }
}
function systemPrefersLight(): boolean {
@@ -89,7 +97,7 @@ export function ThemeProvider({ children }: { children: ReactNode }) {
}, [palette]);
const setTheme = useCallback((t: Theme) => {
- localStorage.setItem(THEME_KEY, t);
+ try { localStorage.setItem(THEME_KEY, t); } catch { /* test env */ }
setPinnedTheme(t);
}, []);
@@ -98,7 +106,7 @@ export function ThemeProvider({ children }: { children: ReactNode }) {
}, [theme, setTheme]);
const setPalette = useCallback((p: Palette) => {
- localStorage.setItem(PALETTE_KEY, p);
+ try { localStorage.setItem(PALETTE_KEY, p); } catch { /* test env */ }
setPaletteState(p);
}, []);
diff --git a/web/src/uiEvents.ts b/web/src/uiEvents.ts
index 935993e..5acc5b0 100644
--- a/web/src/uiEvents.ts
+++ b/web/src/uiEvents.ts
@@ -56,3 +56,11 @@ export const TOGGLE_DRAWER_EVENT = "maestro-toggle-drawer";
export function requestToggleDrawer(): void {
document.dispatchEvent(new CustomEvent(TOGGLE_DRAWER_EVENT));
}
+
+/** Toggle the help overlay from a button click (the `?` key is handled by
+ * HelpOverlay's own command set). */
+export const TOGGLE_HELP_EVENT = "maestro-toggle-help";
+
+export function requestToggleHelp(): void {
+ document.dispatchEvent(new CustomEvent(TOGGLE_HELP_EVENT));
+}