diff --git a/packages/app/src/components/agent-list.tsx b/packages/app/src/components/agent-list.tsx
index a444976d2..1ecbeaab3 100644
--- a/packages/app/src/components/agent-list.tsx
+++ b/packages/app/src/components/agent-list.tsx
@@ -14,12 +14,12 @@ import { StyleSheet, useUnistyles } from "react-native-unistyles";
import { useQueryClient } from "@tanstack/react-query";
import { formatTimeAgo } from "@/utils/time";
import { shortenPath } from "@/utils/shorten-path";
+import { deriveBranchLabel, deriveProjectPath } from "@/utils/agent-display-info";
import { type AggregatedAgent } from "@/hooks/use-aggregated-agents";
import { useSessionStore } from "@/stores/session-store";
import {
CHECKOUT_STATUS_STALE_TIME,
checkoutStatusQueryKey,
- type CheckoutStatusPayload,
useCheckoutStatusCacheOnly,
} from "@/hooks/use-checkout-status-query";
import {
@@ -105,35 +105,6 @@ export function AgentList({
setActionAgent(null);
}, [actionAgent, deleteAgent]);
- const deriveBranchLabel = useCallback((checkout: CheckoutStatusPayload | null): string | null => {
- if (!checkout || !checkout.isGit) {
- return null;
- }
- const currentBranch: string | null = checkout.currentBranch ?? null;
- const baseRef: string | null = checkout.baseRef ?? null;
- if (!currentBranch) {
- return null;
- }
- if (baseRef && currentBranch === baseRef) {
- return null;
- }
- return currentBranch;
- }, []);
-
- const deriveProjectPath = useCallback(
- (agent: AggregatedAgent, checkout: CheckoutStatusPayload | null): string => {
- const basePath = checkout?.isGit ? (checkout.repoRoot ?? agent.cwd) : agent.cwd;
- const worktreeMarker = ".paseo/worktrees/";
- const idx = basePath.indexOf(worktreeMarker);
- if (idx !== -1) {
- const afterMarker = basePath.slice(idx + worktreeMarker.length);
- return afterMarker;
- }
- return basePath;
- },
- []
- );
-
const viewabilityConfig = useMemo(
() => ({ itemVisiblePercentThreshold: 30 }),
[]
@@ -190,7 +161,7 @@ export function AgentList({
agentId: agent.id,
});
const checkout = checkoutQuery.data ?? null;
- const projectPath = deriveProjectPath(agent, checkout);
+ const projectPath = deriveProjectPath(agent.cwd, checkout);
const branchLabel = deriveBranchLabel(checkout);
return (
@@ -233,8 +204,6 @@ export function AgentList({
);
},
[
- deriveBranchLabel,
- deriveProjectPath,
handleAgentLongPress,
handleAgentPress,
selectedAgentId,
diff --git a/packages/app/src/components/headers/menu-header.tsx b/packages/app/src/components/headers/menu-header.tsx
index c211e7072..b861cf4c5 100644
--- a/packages/app/src/components/headers/menu-header.tsx
+++ b/packages/app/src/components/headers/menu-header.tsx
@@ -1,5 +1,5 @@
import type { ReactNode } from "react";
-import { Pressable, Text } from "react-native";
+import { Pressable, Text, View } from "react-native";
import { StyleSheet, UnistylesRuntime, useUnistyles } from "react-native-unistyles";
import { Menu, PanelLeft } from "lucide-react-native";
import { ScreenHeader } from "./screen-header";
@@ -7,10 +7,11 @@ import { usePanelStore } from "@/stores/panel-store";
interface MenuHeaderProps {
title?: string;
+ subtitle?: string;
rightContent?: ReactNode;
}
-export function MenuHeader({ title, rightContent }: MenuHeaderProps) {
+export function MenuHeader({ title, subtitle, rightContent }: MenuHeaderProps) {
const { theme } = useUnistyles();
const isMobile =
UnistylesRuntime.breakpoint === "xs" || UnistylesRuntime.breakpoint === "sm";
@@ -32,9 +33,16 @@ export function MenuHeader({ title, rightContent }: MenuHeaderProps) {
{title && (
-
- {title}
-
+
+
+ {title}
+
+ {subtitle && (
+
+ {subtitle}
+
+ )}
+
)}
>
}
@@ -55,13 +63,21 @@ const styles = StyleSheet.create((theme) => ({
},
borderRadius: theme.borderRadius.lg,
},
- title: {
+ titleContainer: {
flex: 1,
- fontSize: theme.fontSize.lg,
+ gap: theme.spacing[0],
+ },
+ title: {
+ fontSize: theme.fontSize.base,
fontWeight: {
- xs: theme.fontWeight.semibold,
- md: "400",
+ xs: "400",
+ md: "300",
},
color: theme.colors.foreground,
},
+ subtitle: {
+ fontSize: theme.fontSize.sm,
+ fontWeight: "300",
+ color: theme.colors.foregroundMuted,
+ },
}));
diff --git a/packages/app/src/screens/agent/agent-ready-screen.tsx b/packages/app/src/screens/agent/agent-ready-screen.tsx
index 3c7b2148e..f3e007ab6 100644
--- a/packages/app/src/screens/agent/agent-ready-screen.tsx
+++ b/packages/app/src/screens/agent/agent-ready-screen.tsx
@@ -57,6 +57,8 @@ import {
import { extractAgentModel } from "@/utils/extract-agent-model";
import { startPerfMonitor } from "@/utils/perf-monitor";
import { shortenPath } from "@/utils/shorten-path";
+import { deriveBranchLabel, deriveProjectPath } from "@/utils/agent-display-info";
+import { useCheckoutStatusQuery } from "@/hooks/use-checkout-status-query";
import {
DropdownMenu,
DropdownMenuContent,
@@ -406,6 +408,13 @@ function AgentScreenContent({
? branchError ?? "Unavailable"
: branchLabel ?? "Unknown";
+ // Checkout status for header subtitle
+ const checkoutStatusQuery = useCheckoutStatusQuery({
+ serverId,
+ agentId: resolvedAgentId ?? "",
+ });
+ const checkout = checkoutStatusQuery.status;
+
useEffect(() => {
if (!resolvedAgentId) {
setFocusedAgentId(null);
@@ -490,6 +499,20 @@ function AgentScreenContent({
const effectiveAgent = agent ?? placeholderAgent;
+ // Header subtitle: project path + branch (matching agent list row format)
+ const headerProjectPath = effectiveAgent
+ ? deriveProjectPath(effectiveAgent.cwd, checkout)
+ : null;
+ const headerBranchLabel = deriveBranchLabel(checkout);
+ const headerSubtitle = useMemo(() => {
+ if (!headerProjectPath) return undefined;
+ const path = shortenPath(headerProjectPath);
+ if (headerBranchLabel) {
+ return `${path} · ${headerBranchLabel}`;
+ }
+ return path;
+ }, [headerProjectPath, headerBranchLabel]);
+
useEffect(() => {
if (!isPendingCreateForRoute || !pendingCreate) {
return;
@@ -596,6 +619,7 @@ function AgentScreenContent({
{/* Header */}
diff --git a/packages/app/src/utils/agent-display-info.ts b/packages/app/src/utils/agent-display-info.ts
new file mode 100644
index 000000000..8fb4351b0
--- /dev/null
+++ b/packages/app/src/utils/agent-display-info.ts
@@ -0,0 +1,41 @@
+import type { CheckoutStatusPayload } from "@/hooks/use-checkout-status-query";
+
+/**
+ * Derives the branch label to display for an agent.
+ * Returns null if there's no branch to show (not a git repo, or on the base branch).
+ */
+export function deriveBranchLabel(
+ checkout: CheckoutStatusPayload | null
+): string | null {
+ if (!checkout || !checkout.isGit) {
+ return null;
+ }
+ const currentBranch: string | null = checkout.currentBranch ?? null;
+ const baseRef: string | null = checkout.baseRef ?? null;
+ if (!currentBranch) {
+ return null;
+ }
+ if (baseRef && currentBranch === baseRef) {
+ return null;
+ }
+ return currentBranch;
+}
+
+/**
+ * Derives the project path to display for an agent.
+ * If inside a Paseo worktree, shows just the worktree-relative path.
+ * Otherwise uses the repo root or cwd.
+ */
+export function deriveProjectPath(
+ cwd: string,
+ checkout: CheckoutStatusPayload | null
+): string {
+ const basePath = checkout?.isGit ? (checkout.repoRoot ?? cwd) : cwd;
+ const worktreeMarker = ".paseo/worktrees/";
+ const idx = basePath.indexOf(worktreeMarker);
+ if (idx !== -1) {
+ const afterMarker = basePath.slice(idx + worktreeMarker.length);
+ return afterMarker;
+ }
+ return basePath;
+}
diff --git a/scripts/dev.sh b/scripts/dev.sh
index 630f3e618..5ca49bec5 100755
--- a/scripts/dev.sh
+++ b/scripts/dev.sh
@@ -9,9 +9,9 @@ export PATH="$SCRIPT_DIR/../node_modules/.bin:$PATH"
DAEMON_PORT=$(get-port 6767 6768 6769 6770 6771 6772 6773)
METRO_PORT=$(get-port 8081 8082 8083 8084 8085 8086 8087)
-# Use a temporary PASEO_HOME to avoid conflicts between dev instances
-export PASEO_HOME=$(mktemp -d "${TMPDIR:-/tmp}/paseo-dev.XXXXXX")
-trap "rm -rf '$PASEO_HOME'" EXIT
+# # Use a temporary PASEO_HOME to avoid conflicts between dev instances
+# export PASEO_HOME=$(mktemp -d "${TMPDIR:-/tmp}/paseo-dev.XXXXXX")
+# trap "rm -rf '$PASEO_HOME'" EXIT
# Build CORS origins for this Expo instance
CORS_ORIGINS="http://localhost:${METRO_PORT},http://127.0.0.1:${METRO_PORT}"
@@ -24,7 +24,7 @@ echo " Paseo Dev"
echo "══════════════════════════════════════════════════════"
echo " Daemon: http://localhost:${DAEMON_PORT}"
echo " Metro: http://localhost:${METRO_PORT}"
-echo " Home: ${PASEO_HOME}"
+# echo " Home: ${PASEO_HOME}"
echo "══════════════════════════════════════════════════════"
# Export for child processes (overrides .env values)