diff --git a/site/src/pages/AgentsPage/AgentSettingsBehaviorPageView.tsx b/site/src/pages/AgentsPage/AgentSettingsBehaviorPageView.tsx
index 5af5c7235c..1c1bbbba8b 100644
--- a/site/src/pages/AgentsPage/AgentSettingsBehaviorPageView.tsx
+++ b/site/src/pages/AgentsPage/AgentSettingsBehaviorPageView.tsx
@@ -13,7 +13,11 @@ import { DurationField } from "./components/DurationField/DurationField";
import { SectionHeader } from "./components/SectionHeader";
import { TextPreviewDialog } from "./components/TextPreviewDialog";
import { UserCompactionThresholdSettings } from "./components/UserCompactionThresholdSettings";
-import { getKylesophyEnabled, setKylesophyEnabled } from "./utils/chime";
+import {
+ getKylesophyEnabled,
+ isKylesophyForced,
+ setKylesophyEnabled,
+} from "./utils/chime";
const textareaMaxHeight = 240;
const textareaBaseClassName =
@@ -125,6 +129,7 @@ export const AgentSettingsBehaviorPageView: FC<
const [isUserPromptOverflowing, setIsUserPromptOverflowing] = useState(false);
const [isSystemPromptOverflowing, setIsSystemPromptOverflowing] =
useState(false);
+ const kylesophyForced = isKylesophyForced();
const [kylesophyEnabled, setKylesophyLocal] = useState(getKylesophyEnabled);
// ── Derived state ──
@@ -521,6 +526,11 @@ export const AgentSettingsBehaviorPageView: FC<
Replace the standard completion chime. IYKYK.
+ {kylesophyForced && (
+
+ Kyleosophy is mandatory on dev.coder.com.
+
+ )}
diff --git a/site/src/pages/AgentsPage/utils/chime.test.ts b/site/src/pages/AgentsPage/utils/chime.test.ts
index 74a743fa25..e9a56d27f8 100644
--- a/site/src/pages/AgentsPage/utils/chime.test.ts
+++ b/site/src/pages/AgentsPage/utils/chime.test.ts
@@ -2,6 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
getChimeEnabled,
getKylesophyEnabled,
+ isKylesophyForced,
KYLEOSOPHY_SOUNDS,
LOCK_HOLD_MS,
maybePlayChime,
@@ -313,3 +314,38 @@ describe("maybePlayChime", () => {
expect(url).toBe("/chime.mp3");
});
});
+
+// ---------------------------------------------------------------------------
+// isKylesophyForced
+// ---------------------------------------------------------------------------
+
+describe("isKylesophyForced", () => {
+ const originalLocation = globalThis.location;
+
+ afterEach(() => {
+ Object.defineProperty(globalThis, "location", {
+ value: originalLocation,
+ writable: true,
+ configurable: true,
+ });
+ });
+
+ it("returns true on dev.coder.com", () => {
+ Object.defineProperty(globalThis, "location", {
+ value: { hostname: "dev.coder.com" },
+ writable: true,
+ configurable: true,
+ });
+ expect(isKylesophyForced()).toBe(true);
+ expect(getKylesophyEnabled()).toBe(true);
+ });
+
+ it("returns false on other hosts", () => {
+ Object.defineProperty(globalThis, "location", {
+ value: { hostname: "coder.example.com" },
+ writable: true,
+ configurable: true,
+ });
+ expect(isKylesophyForced()).toBe(false);
+ });
+});
diff --git a/site/src/pages/AgentsPage/utils/chime.ts b/site/src/pages/AgentsPage/utils/chime.ts
index f0339055a0..35665ef92c 100644
--- a/site/src/pages/AgentsPage/utils/chime.ts
+++ b/site/src/pages/AgentsPage/utils/chime.ts
@@ -20,7 +20,14 @@ export function setChimeEnabled(enabled: boolean): void {
}
}
+/**
+ * Whether Kyleosophy mode is active. Force-enabled on
+ * dev.coder.com because the people deserve Kyle.
+ */
export function getKylesophyEnabled(): boolean {
+ if (isKylesophyForced()) {
+ return true;
+ }
try {
const stored = localStorage.getItem(KYLEOSOPHY_PREFERENCE_KEY);
return stored === null ? false : stored === "true";
@@ -29,6 +36,18 @@ export function getKylesophyEnabled(): boolean {
}
}
+/**
+ * Whether the current deployment force-enables Kyleosophy,
+ * bypassing the user preference.
+ */
+export function isKylesophyForced(): boolean {
+ try {
+ return globalThis.location?.hostname === "dev.coder.com";
+ } catch {
+ return false;
+ }
+}
+
export function setKylesophyEnabled(enabled: boolean): void {
try {
localStorage.setItem(KYLEOSOPHY_PREFERENCE_KEY, String(enabled));