Skip to content
Development
Command

/chatgroup-architecture

ChatGroup architecture — how conversation data flows from raw JSONL to rendered chat groups. Use when working on UserGroup, AIGroup, SystemGroup, display items, tool linking, chunks, or the rendering hierarchy.

From plugin
claude-devtools
3.8k5 skills2 agents5 commands

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/chatgroup-architecture

Context preview

What this command does when you run it.

ChatGroup architecture — how conversation data flows from raw JSONL to rendered chat groups. Use when working on UserGroup, AIGroup, SystemGroup, display items, tool linking, chunks, or the rendering hierarchy.

Command definition

chatgroup-architecture.md
name: claude-devtools:chatgroup-architecture
description: ChatGroup architecture — how conversation data flows from raw JSONL to rendered chat groups. Use when working on UserGroup, AIGroup, SystemGroup, display items, tool linking, chunks, or the rendering hierarchy.

ChatGroup Architecture

How conversation data flows from raw JSONL messages to rendered chat groups.

Core Design Principle

Chat groups are **independent items in a flat chronological list**, not paired turns. There is no UserTurn/AITurn pairing — each group stands alone.

// src/renderer/types/groups.ts
export type ChatItem =
  | { type: 'user'; group: UserGroup }
  | { type: 'system'; group: SystemGroup }
  | { type: 'ai'; group: AIGroup }
  | { type: 'compact'; group: CompactGroup };

export interface SessionConversation {
  sessionId: string;
  items: ChatItem[];  // Flat chronological list
  totalUserGroups: number;
  totalSystemGroups: number;
  totalAIGroups: number;
  totalCompactGroups: number;
}

Pipeline Overview

Raw JSONL messages
  → MessageClassifier (classify into user/system/ai/hardNoise)
  → ChunkBuilder (buffer AI messages, flush on user/system boundary)
  → ChunkFactory (build EnhancedAIChunk with SemanticSteps)
  → groupTransformer (chunks → flat ChatItem[] conversation)
  → aiGroupEnhancer (AIGroup → EnhancedAIGroup with displayItems, linkedTools, lastOutput)
  → React components render

Primary source files:

  • `src/main/services/parsing/MessageClassifier.ts`
  • `src/main/services/analysis/ChunkBuilder.ts`
  • `src/main/services/analysis/ChunkFactory.ts`
  • `src/renderer/utils/groupTransformer.ts`
  • `src/renderer/utils/aiGroupEnhancer.ts`
  • `src/renderer/utils/displayItemBuilder.ts`
  • `src/renderer/types/groups.ts`
  • `src/main/types/chunks.ts`

Data Models

UserGroup

// src/renderer/types/groups.ts
interface UserGroup {
  id: string;
  message: ParsedMessage;
  timestamp: Date;
  content: UserGroupContent;
  index: number;  // Ordering index within session
}

interface UserGroupContent {
  text?: string;                 // Plain text (commands removed)
  rawText?: string;              // Original text
  commands: CommandInfo[];       // Extracted /commands
  images: ImageData[];           // Attached images
  fileReferences: FileReference[]; // @file.ts mentions
}

Renders right-aligned blue bubble. Contains markdown text, slash commands, images, and file references.

AIGroup

interface AIGroup {
  id: string;
  turnIndex: number;             // 0-based (for turn navigation)
  startTime: Date;
  endTime: Date;
  durationMs: number;
  steps: SemanticStep[];         // Core semantic steps
  tokens: AIGroupTokens;
  summary: AIGroupSummary;       // For collapsed view
  status: AIGroupStatus;         // 'complete' | 'interrupted' | 'error' | 'in_progress'
  processes: Process[];          // Subagent processes
  chunkId: string;
  metrics: SessionMetrics;
  responses: ParsedMessage[];    // All assistant + internal messages
  isOngoing?: boolean;           // True for last group in ongoing session
}

EnhancedAIGroup

The renderer enhances `AIGroup` before rendering:

interface EnhancedAIGroup extends AIGroup {
  lastOutput: AIGroupLastOutput | null;      // Always-visible output
  displayItems: AIGroupDisplayItem[];        // Flattened chronological items
  linkedTools: Map<string, LinkedToolItem>;  // Tool call/result pairs
  itemsSummary: string;                      // "2 thinking, 4 tool calls, 3 subagents"
  mainModel: ModelInfo | null;
  subagentModels: ModelInfo[];
  claudeMdStats: ClaudeMdStats | null;
}

Enhancement happens in `src/renderer/utils/aiGroupEnhancer.ts`:

1. `findLastOutput` — extracts the final visible output (text, tool result, interruption, plan exit, ongoing) 2. `linkToolCallsToResults` — pairs tool calls with their results into `LinkedToolItem` 3. `buildDisplayItems` — flattens steps into chronological `AIGroupDisplayItem[]` 4. `buildSummary` — generates human-readable summary string 5. `extractMainModel` / `extractSubagentModels` — extracts model info

AIGroupDisplayItem

type AIGroupDisplayItem =
  | { type: 'thinking'; content: string; timestamp: Date; tokenCount?: number }
  | { type: 'tool'; tool: LinkedToolItem }
  | { type: 'subagent'; subagent: Process }
  | { type: 'output'; content: string; timestamp: Date; tokenCount?: number }
  | { type: 'slash'; slash: SlashItem }
  | { type: 'teammate_message'; teammateMessage: TeammateMessage };

Display items are sorted chronologically in `src/renderer/utils/displayItemBuilder.ts`.

LinkedToolItem

interface LinkedToolItem {
  id: string;
  name: string;
  input: Record<string, unknown>;
  callTokens?: number;
  result?: {
    content: string | unknown[];
    isError: boolean;
    toolUseResult?: ToolUseResultData;
    tokenCount?: number;
  };
  inputPreview: string;          // First 100 chars
  outputPreview?: string;        // First 200 chars
  startTime: Date;
  endTime?: Date;
  durationMs?: number;
  isOrphaned: boolean;           // No result received
  sourceModel?: string;
  skillInstructions?: string;    // For Skill tool calls
  skillInstructionsTokenCount?: number;
}

AIGroupLastOutput

Always-visible output below the AI group header:

interface AIGroupLastOutput {
  type: 'text' | 'tool_result' | 'interruption' | 'ongoing' | 'plan_exit';
  text?: string;
  toolName?: string;
  toolResult?: string;
  isError?: boolean;
  interruptionMessage?: string;
  planContent?: string;
  planPreamble?: string;
  timestamp: Date;
}

SystemGroup

interface SystemGroup {
  id: string;
  message: ParsedMessage;
  timestamp: Date;
  commandOutput: string;
  commandName?: string;
}

Renders left-aligned with neutral gray styling. Monospace pre with ANSI escape codes cleaned.

CompactGroup

interface CompactGroup {
  id: s
Read more
Ships withclaude-devtools

The missing DevTools for Claude Code — inspect session logs, tool calls, token usage, subagents, and context window in a visual UI. Free, open source.

Get the whole plugin
Stats
3,815
Stars
291
Forks
Maintained
Maintenance
TypeScript
Language
MIT
License
2mo ago
Last commit
6mo ago
Created

Repo: matt1398/claude-devtools