Skip to content

Commit 21cb88e

Browse files
sorlen008claude
andcommitted
feat: Resume button on project-detail Sessions tab — v2.6.3
The project-detail page lists sessions for the project but had no way to resume them directly from there — you had to click into the main Sessions page first. Adds the same one-click Resume button as the Sessions list, with consistent loading/done states. - Each session row gets a green Terminal-icon "Resume" button. - Clicking it POSTs /api/sessions/<id>/open, which spawns a new terminal in the session's recorded cwd and runs `claude --resume`. - Three visual states: idle (Terminal icon), opening (spinner), done (check) — done state auto-clears after 2s. - Tooltip shows the exact directory the terminal will open in. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7b81df5 commit 21cb88e

2 files changed

Lines changed: 39 additions & 3 deletions

File tree

client/src/pages/project-detail.tsx

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { useParams, Link, useLocation } from "wouter";
22
import { useProjectDetail } from "@/hooks/use-projects";
33
import { useMarkdownContent } from "@/hooks/use-markdown";
4-
import { useSessions } from "@/hooks/use-sessions";
4+
import { useSessions, useOpenSession } from "@/hooks/use-sessions";
55
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
66
import { Badge } from "@/components/ui/badge";
77
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
88
import { EntityBadge, entityConfig } from "@/components/entity-badge";
99
import { Button } from "@/components/ui/button";
10-
import { ArrowLeft, FileText, Server, Wand2, HardDrive, MessageSquare, ExternalLink, Edit3, ChevronRight, Layers, Zap, Clock, Terminal, Code2, Copy, X, Check, Briefcase } from "lucide-react";
10+
import { ArrowLeft, FileText, Server, Wand2, HardDrive, MessageSquare, ExternalLink, Edit3, ChevronRight, Layers, Zap, Clock, Terminal, Code2, Copy, X, Check, Briefcase, Loader2 } from "lucide-react";
1111
import type { MCPEntity, SkillEntity, MarkdownEntity, ScriptEntity } from "@shared/types";
1212
import { formatBytes, relativeTime } from "@/lib/utils";
1313
import { useEffect, useState } from "react";
@@ -63,6 +63,21 @@ export default function ProjectDetail() {
6363
})();
6464
const inferredOnlyCount = projectSessions.filter(p => p.origin === "inferred").length;
6565

66+
// One-click Resume — opens a new terminal in the session's recorded cwd
67+
// and runs `claude --resume <id>`. Same flow as the main Sessions page.
68+
const openSession = useOpenSession();
69+
const [openState, setOpenState] = useState<{ id: string; phase: "opening" | "done" } | null>(null);
70+
const handleResume = (id: string, e: React.MouseEvent) => {
71+
e.stopPropagation();
72+
setOpenState({ id, phase: "opening" });
73+
openSession.mutate(id, {
74+
onSettled: () => {
75+
setOpenState({ id, phase: "done" });
76+
setTimeout(() => setOpenState(prev => prev?.id === id ? null : prev), 2000);
77+
},
78+
});
79+
};
80+
6681
return (
6782
<div className="p-6 space-y-6">
6883
{/* Breadcrumb */}
@@ -348,6 +363,27 @@ export default function ProjectDetail() {
348363
</span>
349364
<span className="font-mono">{s.messageCount} msgs</span>
350365
<span className="font-mono">{formatBytes(s.sizeBytes)}</span>
366+
<Button
367+
size="sm"
368+
variant="outline"
369+
className="gap-1.5 h-7"
370+
disabled={openState?.id === s.id && openState.phase === "opening"}
371+
onClick={(e) => handleResume(s.id, e)}
372+
title={`Open a terminal in ${s.cwd || "the session's directory"} and run claude --resume`}
373+
>
374+
{openState?.id === s.id && openState.phase === "opening" ? (
375+
<Loader2 className="h-3.5 w-3.5 animate-spin text-green-400" />
376+
) : openState?.id === s.id && openState.phase === "done" ? (
377+
<Check className="h-3.5 w-3.5 text-green-400" />
378+
) : (
379+
<Terminal className="h-3.5 w-3.5 text-green-400" />
380+
)}
381+
{openState?.id === s.id && openState.phase === "opening"
382+
? "Opening…"
383+
: openState?.id === s.id && openState.phase === "done"
384+
? "Opened"
385+
: "Resume"}
386+
</Button>
351387
</div>
352388
</div>
353389
</CardContent>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "claude-command-center",
3-
"version": "2.6.2",
3+
"version": "2.6.3",
44
"description": "Dashboard for visualizing and managing your Claude Code ecosystem",
55
"license": "MIT",
66
"type": "module",

0 commit comments

Comments
 (0)