import { useCallback, useEffect, useState } from "react"; import type { ClaudeSession, Project } from "../../../lib/types"; import { listClaudeSessions, resumeSessionCommand } from "../../../lib/tauri-commands"; import type { useProjectActions } from "../../../hooks/useProjectActions"; import { useAppState } from "../../../store/appState"; import Button from "../../ui/Button"; import { formatAge, formatBytes } from "./format"; interface Props { project: Project; actions: ReturnType; } /** * The stop/start container model buries "which conversation was I in?" in the * config volume. This lists it and makes [Resume] one click. */ export default function SessionsTab({ project, actions }: Props) { const [sessions, setSessions] = useState([]); const [loading, setLoading] = useState(false); const pushToast = useAppState((s) => s.pushToast); const running = project.status === "running"; const load = useCallback(() => { if (!running) { setSessions([]); return; } setLoading(true); listClaudeSessions(project.id) .then(setSessions) .catch(() => setSessions([])) .finally(() => setLoading(false)); }, [project.id, running]); useEffect(load, [load]); const resume = async (session: ClaudeSession) => { try { const command = await resumeSessionCommand(project.id, session.id); await actions.openTerminalWithCommand(command, session.name ?? "resume"); } catch (e) { pushToast({ kind: "error", message: "Could not resume that session", detail: String(e), }); } }; return (

Conversations stored on this project’s config volume. Resume opens a terminal running the resume command.

{!running ? (

Start the container to read its saved sessions.

) : sessions.length === 0 && !loading ? (

No sessions recorded yet. Open a Claude terminal to start one.

) : (
    {sessions.map((session) => (
  • {session.name ?? session.summary ?? "(untitled session)"}
    {session.id} {session.cwd ? ` · ${session.cwd}` : ""}
    {formatAge(session.last_modified) ?? "—"}
    {formatBytes(session.size_bytes)} · {session.message_count} msg
  • ))}
)}
); }