diff --git a/packages/app/src/components/create-agent-modal.tsx b/packages/app/src/components/create-agent-modal.tsx
index 93493d075..bb575c59e 100644
--- a/packages/app/src/components/create-agent-modal.tsx
+++ b/packages/app/src/components/create-agent-modal.tsx
@@ -35,7 +35,7 @@ import Animated, {
runOnJS,
} from "react-native-reanimated";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
-import { Mic, Check, X, RefreshCcw } from "lucide-react-native";
+import { Mic, Check, X, RefreshCcw, Monitor } from "lucide-react-native";
import { theme as defaultTheme } from "@/styles/theme";
import { useRecentPaths } from "@/hooks/use-recent-paths";
import { useRouter } from "expo-router";
@@ -169,7 +169,13 @@ type ImportCandidate = {
};
type ProviderFilter = "all" | AgentProvider;
-type DropdownKey = "assistant" | "permissions" | "model" | "workingDir" | "baseBranch";
+type DropdownKey =
+ | "assistant"
+ | "permissions"
+ | "model"
+ | "workingDir"
+ | "baseBranch"
+ | "host";
type RepoInfoState = {
cwd: string;
@@ -426,6 +432,7 @@ function AgentFlowModal({
"Selected host";
const selectedDaemonStatusLabel = formatConnectionStatus(selectedDaemonStatus);
const hasSelectedDaemon = Boolean(selectedServerId);
+ const hostBadgeLabel = hasSelectedDaemon ? selectedDaemonLabel : "Select host";
const selectedDaemonIsOffline = selectedDaemonStatus !== "online";
const selectedDaemonLastError = selectedDaemonConnection?.lastError?.trim();
const daemonAvailabilityError = !hasSelectedDaemon
@@ -1787,6 +1794,23 @@ function AgentFlowModal({
paddingRight={horizontalPaddingRight}
onClose={handleClose}
title={modalTitle}
+ rightContent={
+ isImportFlow ? (
+ openDropdownSheet("host")}
+ >
+
+ {hostBadgeLabel}
+
+
+ ) : undefined
+ }
/>
{isCreateFlow ? (
<>
@@ -2133,6 +2157,40 @@ function AgentFlowModal({
)}
)}
+
+ {daemonEntries.length === 0 ? (
+ No hosts available yet.
+ ) : (
+
+ {daemonEntries.map(({ daemon, status }) => {
+ const isSelected = daemon.id === selectedServerId;
+ const label = daemon.label ?? daemon.wsUrl ?? daemon.id;
+ return (
+ {
+ setSelectedServerIdFromUser(daemon.id);
+ closeDropdown();
+ }}
+ >
+ {label}
+
+ {formatConnectionStatus(status)}
+
+
+ );
+ })}
+
+ )}
+
@@ -2175,6 +2233,7 @@ interface ModalHeaderProps {
paddingRight: number;
onClose: () => void;
title: string;
+ rightContent?: ReactNode;
}
function ModalHeader({
@@ -2183,13 +2242,17 @@ function ModalHeader({
paddingRight,
onClose,
title,
+ rightContent,
}: ModalHeaderProps): ReactElement {
return (
{title}
-
-
-
+
+ {rightContent}
+
+
+
+
);
}
@@ -2652,12 +2715,40 @@ const styles = StyleSheet.create(((theme: any) => ({
fontSize: theme.fontSize["2xl"],
fontWeight: theme.fontWeight.semibold,
},
+ headerActions: {
+ flexDirection: "row",
+ alignItems: "center",
+ gap: theme.spacing[3],
+ },
closeButton: {
padding: theme.spacing[2],
borderRadius: theme.borderRadius.full,
alignItems: "center",
justifyContent: "center",
},
+ hostBadge: {
+ flexDirection: "row",
+ alignItems: "center",
+ gap: theme.spacing[2],
+ paddingHorizontal: theme.spacing[3],
+ paddingVertical: theme.spacing[2],
+ backgroundColor: theme.colors.muted,
+ borderRadius: theme.borderRadius.full,
+ },
+ hostBadgeLabel: {
+ color: theme.colors.mutedForeground,
+ fontSize: theme.fontSize.xs,
+ fontWeight: theme.fontWeight.semibold,
+ },
+ hostStatusDot: {
+ width: 6,
+ height: 6,
+ borderRadius: theme.borderRadius.full,
+ backgroundColor: theme.colors.mutedForeground,
+ },
+ hostStatusDotOnline: {
+ backgroundColor: theme.colors.palette.green[500],
+ },
scroll: {
flex: 1,
},
diff --git a/plan.md b/plan.md
index 41a7e9a1f..9b12ccd74 100644
--- a/plan.md
+++ b/plan.md
@@ -58,11 +58,12 @@ Improvements to the new agent screen in the app.
- Add daemon-level E2E test to verify import works correctly.
- **Done (2025-12-28 23:58)**: WHAT: `packages/server/src/server/agent/providers/codex-mcp-agent.ts:4133-4476` adds Codex persisted session listing from rollout files plus JSON/JSONL timeline parsing and session metadata extraction; `packages/server/src/server/daemon.e2e.test.ts:2597-2662` adds Codex persisted agent import E2E coverage. RESULT: Codex import list now populates from on-disk rollouts with timeline previews and is covered by a daemon E2E. EVIDENCE: Not run (not requested).
-- [ ] **Iteration 5**: Add host selector to import agent screen.
+- [x] **Iteration 5**: Add host selector to import agent screen.
- When importing an agent, user should be able to choose which host to import to.
- Use the same UI pattern as the new agent screen: host selector in the header.
- Reference the new agent screen implementation for consistency.
+ - **Done (2025-12-29 00:05)**: WHAT: `packages/app/src/components/create-agent-modal.tsx:172-2193` adds a host dropdown key, renders the header host badge in the import flow, and adds a host selection sheet; `packages/app/src/components/create-agent-modal.tsx:2718-2751` adds host badge/header action styles. RESULT: import agent modal now lets users pick the target host from the header selector. EVIDENCE: Not run (not requested).
- [x] **Iteration 6**: Fix gallery 15s timeout causing full-screen error crash.