diff --git a/packages/shared/src/analytics-events.ts b/packages/shared/src/analytics-events.ts
index 66b8b9d500..9a2a1a968e 100644
--- a/packages/shared/src/analytics-events.ts
+++ b/packages/shared/src/analytics-events.ts
@@ -56,6 +56,7 @@ export type CommandMenuAction =
| "open-channel"
| "open-command-center"
| "open-inbox"
+ | "open-loops"
| "open-usage"
| "search-files"
| "open-file"
diff --git a/packages/ui/src/features/command/CommandMenu.tsx b/packages/ui/src/features/command/CommandMenu.tsx
index ee1d39516c..bed635d6a8 100644
--- a/packages/ui/src/features/command/CommandMenu.tsx
+++ b/packages/ui/src/features/command/CommandMenu.tsx
@@ -4,6 +4,7 @@ import {
ChartLine,
EnvelopeSimple,
HashIcon,
+ RepeatIcon,
} from "@phosphor-icons/react";
import { workspaceIdSet } from "@posthog/core/command-center/eligibility";
import { resolveService } from "@posthog/di/container";
@@ -24,7 +25,7 @@ import {
DialogContent,
Kbd,
} from "@posthog/quill";
-import { PROJECT_BLUEBIRD_FLAG } from "@posthog/shared";
+import { LOOPS_FLAG, PROJECT_BLUEBIRD_FLAG } from "@posthog/shared";
import {
ANALYTICS_EVENTS,
type CommandMenuAction,
@@ -59,6 +60,7 @@ import {
navigateToChannel,
navigateToCommandCenter,
navigateToInbox,
+ navigateToLoops,
} from "@posthog/ui/router/navigationBridge";
import { useAppView } from "@posthog/ui/router/useAppView";
import { openTask, openTaskInput } from "@posthog/ui/router/useOpenTask";
@@ -141,6 +143,7 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
PROJECT_BLUEBIRD_FLAG,
import.meta.env.DEV,
);
+ const loopsEnabled = useFeatureFlag(LOOPS_FLAG, import.meta.env.DEV);
const { channels } = useChannels({ enabled: bluebirdEnabled });
const taskChannelMap = useTaskChannelMap(channels, {
enabled: open && bluebirdEnabled,
@@ -278,6 +281,21 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
navigateToCommandCenter();
},
},
+ ...(loopsEnabled
+ ? [
+ {
+ id: "loops",
+ label: "Loops",
+ keywords: "automations schedules recurring",
+ icon: ,
+ action: "open-loops" as CommandMenuAction,
+ onRun: () => {
+ closeSettingsDialog();
+ navigateToLoops();
+ },
+ },
+ ]
+ : []),
{
id: "plan-usage",
label: "Plan & usage",
@@ -449,6 +467,7 @@ export function CommandMenu({ open, onOpenChange }: CommandMenuProps) {
reviewTaskId,
canSearchFiles,
openFilePicker,
+ loopsEnabled,
]);
const taskSections = useMemo(() => {
diff --git a/packages/ui/src/features/command/keyboard-shortcuts.ts b/packages/ui/src/features/command/keyboard-shortcuts.ts
index 177de7666a..70dc6870a3 100644
--- a/packages/ui/src/features/command/keyboard-shortcuts.ts
+++ b/packages/ui/src/features/command/keyboard-shortcuts.ts
@@ -32,7 +32,7 @@ export const SHORTCUTS = {
MESSAGE_JUMP: "mod+j",
BLUR: "escape",
SUBMIT_BLUR: "mod+enter",
- SWITCH_MESSAGING_MODE: "mod+s",
+ SWITCH_MESSAGING_MODE: "ctrl+s",
RELOAD_WINDOW: "mod+shift+r",
ZOOM_IN: "mod+=",
ZOOM_OUT: "mod+-",
diff --git a/packages/ui/src/features/sessions/components/ImageBuilderBuildButton.tsx b/packages/ui/src/features/sessions/components/ImageBuilderBuildButton.tsx
index 9e3592a9d9..301dcd1969 100644
--- a/packages/ui/src/features/sessions/components/ImageBuilderBuildButton.tsx
+++ b/packages/ui/src/features/sessions/components/ImageBuilderBuildButton.tsx
@@ -1,10 +1,12 @@
+import { Info } from "@phosphor-icons/react";
import {
isImageBuildFailed,
isImageBuildInProgress,
} from "@posthog/shared/domain-types";
import { imageFailureDetail } from "@posthog/ui/features/settings/sections/environments/imageBuildWatcher";
import { useSandboxCustomImages } from "@posthog/ui/features/settings/sections/environments/useSandboxCustomImages";
-import { Button, Flex, Text } from "@radix-ui/themes";
+import { Tooltip } from "@posthog/ui/primitives/Tooltip";
+import { Button, Flex, IconButton, Text } from "@radix-ui/themes";
export function ImageBuilderBuildButton({ taskId }: { taskId: string }) {
const { images, buildMutation } = useSandboxCustomImages();
@@ -25,13 +27,32 @@ export function ImageBuilderBuildButton({ taskId }: { taskId: string }) {
ready ยท v{image.version}
) : isFailed ? (
-
- {image.status === "scan_failed" ? "scan failed" : "build failed"}
-
+
+
+ {image.status === "scan_failed" ? "scan failed" : "build failed"}
+
+
+ Failure reason
+
+ {imageFailureDetail(image)}
+
+
+ }
+ >
+
+
+
+
+
) : null}