diff --git a/packages/app/src/constants/platform.ts b/packages/app/src/constants/platform.ts
index 97fb6d932..3dfcabe6a 100644
--- a/packages/app/src/constants/platform.ts
+++ b/packages/app/src/constants/platform.ts
@@ -10,6 +10,7 @@ import { isElectronRuntime, isElectronRuntimeMac } from "@/desktop/host";
// Default is cross-platform. Gate only when you must:
// isWeb → DOM APIs (document, window,
, addEventListener)
// isNative → Native-only APIs (Haptics, StatusBar, push tokens, camera)
+// isDev → Development-only diagnostics and instrumentation
// isElectron → Desktop wrapper features (file dialogs, titlebar, updates)
//
// For layout decisions, use useIsCompactFormFactor() from constants/layout.ts.
@@ -22,6 +23,9 @@ export const isWeb = Platform.OS === "web";
/** iOS or Android — the JS runtime is React Native. */
export const isNative = Platform.OS !== "web";
+/** Development build/runtime — true in Metro dev bundles, false in production. */
+export const isDev = Boolean((globalThis as { __DEV__?: boolean }).__DEV__);
+
// ---------------------------------------------------------------------------
// Electron detection (cached — only caches `true`, keeps checking if false
// because the desktop bridge may load after initial module evaluation)
diff --git a/packages/app/src/runtime/host-runtime.ts b/packages/app/src/runtime/host-runtime.ts
index 562bc278e..e02390952 100644
--- a/packages/app/src/runtime/host-runtime.ts
+++ b/packages/app/src/runtime/host-runtime.ts
@@ -30,6 +30,7 @@ import {
buildLocalDaemonTransportUrl,
createDesktopLocalDaemonTransportFactory,
} from "@/desktop/daemon/desktop-daemon-transport";
+import { isDev } from "@/constants/platform";
import { applyFetchedAgentDirectory } from "@/utils/agent-directory-sync";
import { useSessionStore, type Agent } from "@/stores/session-store";
@@ -433,6 +434,7 @@ function createDefaultDeps(): HostRuntimeControllerDeps {
clientType: "mobile" as const,
appVersion: resolveAppVersion() ?? undefined,
runtimeGeneration,
+ ...(isDev ? { runtimeMetricsIntervalMs: 10_000 } : {}),
};
if (connection.type === "directSocket" || connection.type === "directPipe") {
return new DaemonClient({
diff --git a/packages/app/src/utils/scroll-jank-investigation.ts b/packages/app/src/utils/scroll-jank-investigation.ts
index 50d66765b..2582a79b5 100644
--- a/packages/app/src/utils/scroll-jank-investigation.ts
+++ b/packages/app/src/utils/scroll-jank-investigation.ts
@@ -1,4 +1,4 @@
-import { isWeb } from "@/constants/platform";
+import { isDev, isWeb } from "@/constants/platform";
type ListenerStats = {
adds: number;
@@ -91,7 +91,6 @@ const SOURCE_LABEL = "[ScrollJankInvestigation]";
function shouldInstall(): boolean {
const runtime = globalThis as ScrollInvestigationGlobal;
- const isDev = Boolean((globalThis as { __DEV__?: boolean }).__DEV__);
return isWeb && isDev && !runtime.__PASEO_SCROLL_JANK_INVESTIGATION_DISABLED__;
}
diff --git a/packages/app/src/utils/test-daemon-connection.ts b/packages/app/src/utils/test-daemon-connection.ts
index 997be2b94..8d321856d 100644
--- a/packages/app/src/utils/test-daemon-connection.ts
+++ b/packages/app/src/utils/test-daemon-connection.ts
@@ -8,6 +8,7 @@ import {
buildLocalDaemonTransportUrl,
createDesktopLocalDaemonTransportFactory,
} from "@/desktop/daemon/desktop-daemon-transport";
+import { isDev } from "@/constants/platform";
function normalizeNonEmptyString(value: unknown): string | null {
if (typeof value !== "string") return null;
@@ -57,6 +58,7 @@ export async function buildClientConfig(
appVersion: resolveAppVersion() ?? undefined,
suppressSendErrors: true,
reconnect: { enabled: false },
+ ...(isDev ? { runtimeMetricsIntervalMs: 10_000 } : {}),
...(connection.type === "directSocket" || connection.type === "directPipe"
? localTransportFactory
? { transportFactory: localTransportFactory }