The Session Explorer provides a comprehensive view of all your coding sessions with Claude, including full conversation history and detailed metrics.
Session List
The main session list is implemented in src/components/session-table.tsx:10 and provides a searchable, expandable interface.
Each session displays:
- First prompt: The initial user message (or “(empty session)” if none)
- Project path: Last two segments of the project directory
- Timestamp: Date and time the session started
- Duration: Total session length in minutes
- Message count: Combined user and assistant messages
Session Badges
Badges provide quick insights into session activity:
// Message count badge
<Badge variant="secondary">
{s.user_message_count + s.assistant_message_count} msgs
</Badge>
// Code changes
{s.lines_added > 0 && (
<Badge variant="secondary" className="!text-emerald-400">
+{s.lines_added}
</Badge>
)}
{s.lines_removed > 0 && (
<Badge variant="secondary" className="!text-red-400">
-{s.lines_removed}
</Badge>
)}
// Git activity
{s.git_commits > 0 && (
<Badge variant="secondary">
{s.git_commits} commit{s.git_commits > 1 ? "s" : ""}
</Badge>
)}
// Language usage
{Object.entries(s.languages).map(([lang, count]) => (
<Badge key={lang} variant="outline">
{lang}: {count}
</Badge>
))}
Feature Detection Badges
Special badges indicate advanced feature usage:
- web search: Session used web search functionality
- MCP: Session used Model Context Protocol servers
- agents: Session used the task agent system
- X errors: Number of tool execution errors (destructive variant)
From src/components/session-table.tsx:139:
{s.uses_web_search && <Badge variant="outline">web search</Badge>}
{s.uses_mcp && <Badge variant="outline">MCP</Badge>}
{s.uses_task_agent && <Badge variant="outline">agents</Badge>}
Search Functionality
The search input filters sessions in real-time by prompt content or project path:
const filtered = sessions.filter(
(s) =>
s.first_prompt.toLowerCase().includes(search.toLowerCase()) ||
s.project_path.toLowerCase().includes(search.toLowerCase())
);
Search is case-insensitive and searches both the prompt text and project path simultaneously.
Expandable Session Details
Clicking any session expands it to reveal detailed information.
Token Statistics
The expanded view shows a two-column grid of token metrics (src/components/session-table.tsx:153):
- User messages count
- Assistant messages count
- Input tokens (with locale formatting)
- Output tokens (with locale formatting)
Message Thread
Each expanded session loads and displays the full conversation thread.
Lazy Loading
Messages are fetched on-demand when a session is expanded:
const fetchMessages = useCallback(async (session: SessionMeta) => {
if (messages[session.session_id]) return;
setLoading(session.session_id);
try {
const params = new URLSearchParams({
session_id: session.session_id,
project_path: session.project_path,
});
const res = await fetch(`/api/session-messages?${params}`);
if (res.ok) {
const data = await res.json();
setMessages((prev) => ({ ...prev, [session.session_id]: data.messages }));
}
} finally {
setLoading(null);
}
}, [messages]);
Message Display
Messages are rendered by the MessageBubble component (src/components/session-table.tsx:204):
User messages are displayed with:
- User icon in a white/10 opacity background
- “You” label
- Full text content
Assistant messages include:
- Bot icon in a white/5 opacity background
- “Claude” label
- Text with subtle gray styling
- Tool usage indicators
When Claude uses tools, they appear as inline badges:
{message.toolUse && message.toolUse.length > 0 && (
<div className="mt-1 flex flex-wrap gap-1">
{message.toolUse.map((tool) => (
<span
key={tool.id}
className="inline-flex items-center gap-1 rounded bg-white/5 px-1.5 py-0.5 text-[10px] text-gray-500"
>
<Wrench className="h-2.5 w-2.5" />
{tool.name}
</span>
))}
</div>
)}
Long Message Handling
Messages longer than 300 characters are truncated with a “click to expand” prompt:
const isLong = message.text.length > 300;
const displayText = expanded ? message.text : message.text.slice(0, 300);
Clicking the message toggles between truncated and full view.
Session Data Structure
Sessions use the SessionMeta interface from src/lib/types.ts:1:
export interface SessionMeta {
session_id: string;
project_path: string;
start_time: string;
duration_minutes: number;
user_message_count: number;
assistant_message_count: number;
tool_counts: Record<string, number>;
languages: Record<string, number>;
git_commits: number;
git_pushes: number;
input_tokens: number;
output_tokens: number;
first_prompt: string;
user_interruptions: number;
tool_errors: number;
tool_error_categories: Record<string, number>;
uses_task_agent: boolean;
uses_mcp: boolean;
uses_web_search: boolean;
uses_web_fetch: boolean;
lines_added: number;
lines_removed: number;
files_modified: number;
message_hours: number[];
user_message_timestamps: number[];
}
Messages use the SessionMessage interface (src/lib/types.ts:77):
export interface SessionMessage {
role: "user" | "assistant";
text: string;
timestamp: string;
toolUse?: { name: string; id: string }[];
}
The session list uses a fixed-height scroll area for better navigation:
<ScrollArea className="h-[600px]">
<div className="space-y-3">
{filtered.map((s) => (
// Session card
))}
</div>
</ScrollArea>
Project Filtering
When a project is selected in the dashboard header, only sessions from that project are shown:
// From dashboard.tsx:58
const filteredSessions = useMemo(
() =>
selectedProject === "all"
? data.sessions
: data.sessions.filter((s) => s.project_path === selectedProject),
[data.sessions, selectedProject]
);
Sessions are sorted by start time with the most recent sessions appearing first.