diff --git a/CLAUDE.md b/CLAUDE.md index d1497b5..5a80c9e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -16,31 +16,34 @@ This runs Next.js on port 3400 with Turbopack for fast development. **Build and type checking:** ```bash -pnpm build -pnpm typecheck +pnpm build # Next.js standalone build + asset copying +pnpm typecheck # TypeScript compilation check ``` -**Linting and formatting:** +**Linting and formatting (Biome):** ```bash -pnpm lint # Run all lint checks -pnpm fix # Fix all linting and formatting issues +pnpm lint # Run format and lint checks in sequence (biome format + biome check) +pnpm fix # Auto-fix format and lint issues with unsafe fixes ``` -**Testing:** +**Testing (Vitest):** ```bash -pnpm test # Run tests once +pnpm test # Run all tests once pnpm test:watch # Run tests in watch mode ``` ## Architecture Overview ### Technology Stack -- **Frontend**: Next.js 15 with React 19, TypeScript -- **Backend**: Hono.js API routes (served via Next.js API routes) -- **Styling**: Tailwind CSS with shadcn/ui components -- **Data fetching**: TanStack Query (React Query) -- **Validation**: Zod schemas -- **Code formatting**: Biome (replaces ESLint + Prettier) +- **Frontend**: Next.js 15.5.2 with React 19.1.1, TypeScript (strict mode via @tsconfig/strictest) +- **Backend**: Hono.js 4.9.5 API routes (served via Next.js API routes with Zod validation) +- **Styling**: Tailwind CSS 4.1.12 with shadcn/ui components (Radix UI primitives) +- **Data fetching**: TanStack Query 5.85.5 with Suspense integration +- **State management**: Jotai 2.13.1 atoms for client-side filtering +- **Validation**: Zod 4.1.5 schemas with modular conversation parsing +- **Code formatting**: Biome 2.2.2 (replaces ESLint + Prettier completely) +- **Testing**: Vitest 3.2.4 with global test setup +- **Package manager**: pnpm 10.8.1 ### Key Architecture Patterns @@ -105,13 +108,16 @@ The application reads Claude Code history from: ### Key Features **Real-time Updates**: -- `FileWatcherService` monitors `~/.claude/projects/` using Node.js `fs.watch()` -- Server-Sent Events stream for live UI updates -- Automatic refresh when conversation files are modified -- Heartbeat mechanism for connection health monitoring +- FileWatcherService singleton monitors `~/.claude/projects/` using Node.js `fs.watch()` +- Server-Sent Events via Hono's `streamSSE()` for live UI updates +- Event types: `connected`, `project_changed`, `session_changed`, `heartbeat` +- Automatic TanStack Query cache invalidation when conversation files are modified +- Heartbeat mechanism (30s intervals) for connection health monitoring +- Proper cleanup and abort handling on client disconnection **CLI Installation**: -- Can be installed via `PORT=3400 npx github:d-kimuson/claude-code-viewer` +- Can be installed via `PORT=3400 npx @kimuson/claude-code-viewer@latest` +- Published as `@kimuson/claude-code-viewer` (v0.0.5) on npm - Standalone Next.js build with embedded dependencies - Binary entry point at `dist/index.js` diff --git a/README.md b/README.md index c68e709..154a9a4 100644 --- a/README.md +++ b/README.md @@ -6,26 +6,39 @@ A web-based viewer for browsing Claude Code conversation history files. View and Claude Code Viewer parses JSONL conversation files stored in `~/.claude/projects/` and presents them in a human-readable web UI. Browse projects, sessions, and detailed conversation history with support for tool usage, subtasks, and real-time file monitoring. +![](./docs/assets/basic.png) + ## Features - **Project Browser** - View all Claude Code projects with metadata and session counts -- **Session Navigation** - Browse conversation sessions within projects with filtering options +- **Session Navigation** - Browse conversation sessions within projects with filtering options - **Conversation Display** - Human-readable format for Claude Code logs with syntax highlighting -- **Subtask Support** - Separate display for subtasks and sidechain conversations -- **Real-time Updates** - Automatic refresh when conversation files are modified -- **File System Watching** - Monitors `~/.claude/projects/` for changes and updates the UI -- **Responsive Design** - Works on desktop and mobile devices +- **Command Detection** - Parses XML-like command structures for enhanced display +- **Real-time Updates** - Server-Sent Events provide live updates when files change +- **Tool Usage Display** - Clear presentation of tool calls, parameters, and results + - ![](./docs/assets/expand_tool_use.png) +- **Sub Task Display** + - ![](./docs/assets/sub_task.png) ## Installation & Usage -### Quick Start +### Quick Start (CLI) -Run directly from GitHub without installation: +Run directly from npm without installation: ```bash -PORT=3400 npx github:d-kimuson/claude-code-viewer +PORT=3400 npx @kimuson/claude-code-viewer@latest ``` +Alternatively, install globally: + +```bash +npm install -g @kimuson/claude-code-viewer +claude-code-viewer +``` + +The application uses pnpm as the package manager (v10.8.1) and is published as version 0.0.5. + The server will start on port 3400 (or the specified PORT). Open `http://localhost:3400` in your browser. ### Alternative Installation @@ -83,44 +96,17 @@ The application reads Claude Code conversation files from: Set a custom port using the `PORT` environment variable: ```bash -PORT=8080 npx github:d-kimuson/claude-code-viewer +PORT=8080 npx @kimuson/claude-code-viewer@latest ``` ### Data Directory The application automatically detects the standard Claude Code directory at `~/.claude/projects/`. No additional configuration is required. -## Browser Support - -- Chrome/Chromium 90+ -- Firefox 88+ -- Safari 14+ -- Edge 90+ - -## Troubleshooting - -### No Projects Found - -- Ensure Claude Code has been used and has created conversation files -- Check that `~/.claude/projects/` exists and contains project directories -- Verify file permissions allow reading the projects directory - -### Connection Issues - -- Check that the specified port is not in use -- Ensure firewall settings allow local connections -- Try a different port using the `PORT` environment variable - -### Real-time Updates Not Working - -- The application uses Server-Sent Events for real-time updates -- Some browsers or network configurations may block SSE connections -- Refresh the page manually to see latest changes - ## License -This project is available under the MIT License. See the LICENSE file for details. +This project is available under the MIT License. ## Contributing -See [docs/dev.md](docs/dev.md) for development setup and contribution guidelines. +See [docs/dev.md](docs/dev.md) for detailed development setup and contribution guidelines. diff --git a/docs/assets/basic.png b/docs/assets/basic.png new file mode 100644 index 0000000..c6b48cd Binary files /dev/null and b/docs/assets/basic.png differ diff --git a/docs/assets/expand_tool_use.png b/docs/assets/expand_tool_use.png new file mode 100644 index 0000000..0f03101 Binary files /dev/null and b/docs/assets/expand_tool_use.png differ diff --git a/docs/assets/sub_task.png b/docs/assets/sub_task.png new file mode 100644 index 0000000..e4f06ab Binary files /dev/null and b/docs/assets/sub_task.png differ diff --git a/docs/dev.md b/docs/dev.md index 214c605..b5660fa 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -6,34 +6,64 @@ This document provides technical details for developers contributing to Claude C ### Tech Stack -- **Frontend**: Next.js 15 with React 19, TypeScript (strict configuration) -- **Backend**: Hono.js API routes with Zod validation -- **Styling**: Tailwind CSS with Radix UI components (shadcn/ui pattern) -- **State Management**: TanStack Query + Jotai atoms -- **Code Quality**: Biome (replaces ESLint + Prettier) -- **Testing**: Vitest with watch mode +- **Frontend**: Next.js 15.5.2 with React 19.1.1, TypeScript with @tsconfig/strictest +- **Backend**: Hono.js 4.9.5 API routes mounted via Next.js API routes with Zod validation +- **Styling**: Tailwind CSS 4.1.12 with Radix UI components (shadcn/ui pattern), Geist fonts +- **State Management**: TanStack Query 5.85.5 + Jotai 2.13.1 atoms with localStorage persistence +- **Code Quality**: Biome 2.2.2 (replaces ESLint + Prettier completely) with double quotes, 2-space indentation +- **Testing**: Vitest 3.2.4 with global test setup and watch mode +- **Validation**: Zod 4.1.5 schemas throughout the stack with modular conversation parsing +- **Real-time**: Server-Sent Events with FileWatcherService singleton and heartbeat mechanism +- **Package Manager**: pnpm 10.8.1 with npm-run-all2 for parallel script execution ### Project Structure ```text src/ -├── app/ # Next.js app router -│ ├── projects/ # Project listing and detail pages -│ │ └── [projectId]/ # Dynamic project routes -│ └── layout.tsx # Root layout with providers -├── server/ # Backend API implementation -│ ├── service/ # Core business logic -│ │ ├── file-watcher.ts # Real-time file monitoring -│ │ ├── paths.ts # File system path constants -│ │ └── project.ts # Project/session operations -│ └── api/ # Hono API route handlers +├── app/ # Next.js 15 app router +│ ├── api/[[...route]]/ # Hono API mounted via Next.js +│ ├── components/ # App-level components +│ │ ├── ServerEventsProvider.tsx # SSE connection management +│ │ └── RootErrorBoundary.tsx # Global error handling +│ ├── projects/ # Project routes +│ │ ├── [projectId]/ # Dynamic project routes +│ │ │ ├── components/ # Project-specific components +│ │ │ ├── hooks/ # Project data fetching hooks +│ │ │ ├── services/ # Client-side business logic +│ │ │ ├── sessions/ # Session management +│ │ │ │ └── [sessionId]/ # Individual session pages +│ │ │ │ ├── components/ # Session UI components +│ │ │ │ └── hooks/ # Session-specific hooks +│ │ │ └── store/ # Jotai atoms for filtering +│ │ └── components/ # Project list components +│ └── layout.tsx # Root layout with providers +├── server/ # Backend implementation +│ ├── hono/ # Hono.js configuration +│ │ ├── app.ts # Hono app setup +│ │ └── route.ts # Route definitions +│ └── service/ # Core business logic +│ ├── events/ # Real-time event system +│ │ ├── fileWatcher.ts # File system monitoring +│ │ ├── sseEvent.ts # SSE event formatting +│ │ └── types.ts # Event type definitions +│ ├── project/ # Project operations +│ ├── session/ # Session operations +│ ├── parseJsonl.ts # JSONL parsing logic +│ ├── parseCommandXml.ts # Command detection +│ └── paths.ts # File system paths ├── lib/ -│ ├── conversation-schema/ # Zod schemas for JSONL validation -│ ├── api/ # Type-safe API client -│ └── utils/ # Shared utilities +│ ├── conversation-schema/ # Modular Zod schemas +│ │ ├── content/ # Content type schemas +│ │ ├── entry/ # Entry type schemas +│ │ ├── message/ # Message schemas +│ │ └── tool/ # Tool-specific schemas +│ ├── api/ # Type-safe API client +│ │ ├── client.ts # Hono client setup +│ │ └── queryClient.ts # TanStack Query config +│ ├── sse/ # SSE client utilities +│ └── utils.ts # Shared utilities └── components/ - ├── ui/ # Reusable UI components - └── conversation/ # Conversation-specific components + └── ui/ # Reusable shadcn/ui components ``` ## Development Setup @@ -55,126 +85,278 @@ pnpm install ### Development Commands ```bash -# Start development server (port 3400) -pnpm dev +# Start development server (port 3400 with Turbopack) +pnpm dev # Runs multiple dev processes in parallel # Type checking -pnpm typecheck +pnpm typecheck # TypeScript compilation check -# Linting and formatting -pnpm lint # Check all rules -pnpm fix # Fix all issues +# Code Quality (Biome) +pnpm lint # Run format and lint checks in sequence +pnpm fix # Auto-fix format and lint issues (includes unsafe fixes) -# Testing -pnpm test # Run once -pnpm test:watch # Watch mode +# Testing (Vitest) +pnpm test # Run all tests once +pnpm test:watch # Run tests in watch mode ``` ### Build Process ```bash -pnpm build # Creates standalone Next.js build in .next/standalone/ +pnpm build # Next.js standalone build + asset copying ``` -The build creates a standalone application that includes all dependencies for deployment. +The build process: +1. Creates standalone Next.js build in `.next/standalone/` +2. Copies `public/` assets to standalone directory +3. Copies static assets (`.next/static`) to standalone directory +4. Results in a fully self-contained application ## API Architecture -### Endpoints +### Hono.js Integration + +The backend uses Hono.js mounted via Next.js API routes with a catch-all route at `/api/[[...route]]/route.ts`. This provides: + +- **Type-safe API**: Full TypeScript inference from server to client +- **Zod validation**: Request/response validation throughout the stack +- **Performance**: Lightweight runtime with minimal overhead +- **Streaming**: Native SSE support for real-time features + +### API Endpoints - `GET /api/projects` - List all projects with metadata - `GET /api/projects/:projectId` - Get project details and sessions - `GET /api/projects/:projectId/sessions/:sessionId` - Get conversation data - `GET /api/events/state_changes` - Server-Sent Events for real-time updates -### Data Flow +### Data Flow Architecture -1. **File System → Parser**: Read JSONL files from `~/.claude/projects/` -2. **Parser → Validation**: Validate each line against Zod conversation schemas -3. **API → Frontend**: Type-safe data transfer with TanStack Query -4. **Real-time**: File watcher emits SSE events for live updates +```text +File System → Services → Hono Routes → Next.js API → TanStack Query → React Components + ↓ ↓ ↓ ↓ ↓ ↓ +~/.claude/ parseJsonl route.ts [[...route]] useProject ProjectList +projects/ +schemas +streaming /route.ts +hooks +components +``` + +1. **File System Reading**: Services read JSONL files from `~/.claude/projects/` +2. **Schema Validation**: Each line validated against modular Zod conversation schemas +3. **API Layer**: Hono.js routes provide type-safe endpoints with streaming support +4. **Client Integration**: TanStack Query manages server state with error boundaries +5. **Real-time Updates**: File watcher emits SSE events, automatically updating UI ### Backend Services -#### Core Services (`src/server/service/`) +#### Project Services (`src/server/service/project/`) - **`getProjects()`** - Scans project directories, returns sorted metadata - **`getProject(projectId)`** - Fetches project details and session list -- **`getSession(projectId, sessionId)`** - Parses JSONL conversation files -- **`parseJsonl()`** - Validates JSONL lines against conversation schema +- **`getProjectMeta(projectId)`** - Fast metadata extraction -#### File Watching (`src/server/service/file-watcher.ts`) +#### Session Services (`src/server/service/session/`) -- Singleton service using Node.js `fs.watch()` -- Monitors `~/.claude/projects/` recursively -- Emits `project_changed` and `session_changed` events -- Includes heartbeat mechanism (30s intervals) +- **`getSessions(projectId)`** - List sessions for a project +- **`getSession(projectId, sessionId)`** - Parse JSONL conversation files +- **`getSessionMeta(projectId, sessionId)`** - Extract session metadata + +#### Event System (`src/server/service/events/`) + +- **`fileWatcher.ts`** - FileWatcherService singleton class using Node.js `fs.watch()` +- **`sseEvent.ts`** - Event formatting utilities for SSE +- **`types.ts`** - Event type definitions + +**File Watching Features:** +- Monitors `~/.claude/projects/` recursively with singleton pattern +- Event types: `connected`, `project_changed`, `session_changed`, `heartbeat` +- Heartbeat mechanism (30s intervals) for connection health monitoring +- Automatic cleanup on client disconnection with proper abort handling +- Uses Hono's `streamSSE()` for efficient server-sent event streaming ## Data Validation ### Conversation Schema (`src/lib/conversation-schema/`) -Modular Zod schemas handle different conversation entry types: +The schema system uses a modular Zod architecture for type-safe conversation parsing: -- **Entry Types**: User, Assistant, System, Summary -- **Content Types**: Text, Tool Use, Tool Result, Thinking -- **Validation**: Strict type checking with fallback parsing +#### Schema Organization + +```text +conversation-schema/ +├── index.ts # Main union schema +├── content/ # Content type schemas +│ ├── TextContentSchema.ts +│ ├── ToolUseContentSchema.ts +│ ├── ToolResultContentSchema.ts +│ ├── ThinkingContentSchema.ts +│ └── ImageContentSchema.ts +├── entry/ # Entry type schemas +│ ├── BaseEntrySchema.ts +│ ├── UserEntrySchema.ts +│ ├── AssistantEntrySchema.ts +│ ├── SystemEntrySchema.ts +│ └── SummaryEntrySchema.ts +├── message/ # Message schemas +│ ├── UserMessageSchema.ts +│ └── AssistantMessageSchema.ts +└── tool/ # Tool-specific schemas + ├── CommonToolSchema.ts + ├── StructuredPatchSchema.ts + └── TodoSchema.ts +``` + +#### Key Features + +- **Union Types**: `ConversationSchema` combines all entry types +- **Incremental Parsing**: Graceful handling of malformed JSONL lines +- **Content Validation**: Strict typing for different content formats +- **Tool Support**: Dedicated schemas for Claude Code tools +- **Type Safety**: Full TypeScript inference throughout the stack ### Command Detection -Special XML-like command parsing for enhanced display: +Advanced XML-like command parsing for enhanced conversation display: ```typescript +// src/server/service/parseCommandXml.ts parseCommandXml(content: string) // Extracts command names and arguments ``` +Supports various command formats: +- Slash commands (`/save`, `/edit`) +- Local commands with arguments +- Structured command detection for better UX + ## Frontend Architecture ### Component Hierarchy ```text -RootLayout (providers, error boundaries) -├── ProjectList (grid of project cards) -├── ProjectDetail -│ ├── SessionList (filterable session grid) -│ └── SessionDetail -│ ├── SessionSidebar (navigation) -│ └── ConversationList (message display) +RootLayout (providers, error boundaries, SSE) +├── ServerEventsProvider (SSE connection management) +├── QueryClientProviderWrapper (TanStack Query setup) +├── RootErrorBoundary (global error handling) +└── Pages + ├── ProjectList (grid of project cards) + └── ProjectDetail ([projectId]) + ├── ProjectPage (project overview) + ├── SessionList (filterable session grid) + └── SessionDetail ([sessionId]) + ├── SessionPageContent (main layout) + ├── SessionSidebar (conversation navigation) + ├── ConversationList (message display) + ├── ConversationItem (individual messages) + └── SidechainConversationModal (popup details) ``` -### State Management +### State Management Architecture -- **Server State**: TanStack Query with suspense boundaries -- **Client State**: Jotai atoms for UI state (filters, sidebar state) -- **Real-time**: Server-Sent Events with automatic reconnection +#### Server State (TanStack Query) +- **`useProjects`** - Project listing with caching +- **`useProject`** - Individual project details and sessions +- **`useSession`** - Conversation data fetching +- **Suspense Integration**: Progressive loading with error boundaries +- **Cache Management**: Automatic invalidation on SSE events -### Type Safety +#### Client State (Jotai Atoms) +```text +src/app/projects/[projectId]/store/filterAtoms.ts +├── sessionFilterAtom # Session filtering state +├── searchTermAtom # Search input state +└── sortOrderAtom # Session sorting preference +``` -- **API Types**: Generated from Hono route definitions -- **Schemas**: Zod validation with TypeScript inference -- **Build-time**: Strict TypeScript configuration via `@tsconfig/strictest` +#### Real-time State (Server-Sent Events) +- **`useServerEvents`** - SSE connection hook +- **Auto-reconnection**: Handles connection drops gracefully +- **Event Processing**: `project_changed`, `session_changed`, heartbeat +- **Query Invalidation**: Automatic cache refresh on file changes + +### Type Safety System + +- **API Types**: Full inference from Hono route definitions to React components +- **Schema Validation**: Runtime and compile-time type checking with Zod +- **Build Configuration**: `@tsconfig/strictest` for maximum type safety +- **Error Boundaries**: Typed error handling throughout the component tree + +### Hook Patterns + +#### Data Fetching Hooks +```typescript +// Custom hooks following consistent patterns +useProjects() // → { data, isLoading, error } +useProject(projectId) // → { project, sessions, isLoading } +useSession(projectId, sessionId) // → { session, conversations, isLoading } +``` + +#### Real-time Hooks +```typescript +useServerEvents() // → SSE connection management +useSidechain() // → Modal state management +``` ## Code Conventions -### File Organization +### File Organization Patterns -- **Services**: Business logic in `src/server/service/` -- **Components**: UI components with co-located styles -- **Schemas**: Modular Zod schemas with clear interfaces -- **Hooks**: Custom hooks for data fetching and state management +- **Services**: Business logic organized by domain (`project/`, `session/`, `events/`) +- **Components**: Co-located with hooks, stores, and services in feature directories +- **Schemas**: Modular Zod schemas with clear separation of concerns +- **Hooks**: Custom hooks grouped by functionality and data dependency +- **Types**: TypeScript types inferred from Zod schemas where possible ### Naming Conventions -- **Files**: `kebab-case.ts` -- **Components**: `PascalCase` -- **Functions**: `camelCase` -- **Constants**: `SCREAMING_SNAKE_CASE` +- **Files**: `camelCase.ts` for most files, `PascalCase.tsx` for React components +- **Components**: `PascalCase` (e.g., `SessionPageContent.tsx`) +- **Functions**: `camelCase` (e.g., `getProject`, `parseJsonl`) +- **Constants**: `SCREAMING_SNAKE_CASE` (e.g., `PROJECTS_BASE_PATH`) +- **Hooks**: `use` prefix (e.g., `useProject`, `useServerEvents`) +- **Atoms**: Suffix with `Atom` (e.g., `sessionFilterAtom`) -### Code Style +### Code Style (Biome Configuration) -- **Formatter**: Biome (replaces Prettier) -- **Linter**: Biome (replaces ESLint) -- **Config**: Extends `@tsconfig/strictest` for maximum type safety +**Biome replaces both ESLint and Prettier** with a single, fast tool: + +```json +{ + "formatter": { + "enabled": true, + "indentStyle": "space" // 2-space indentation + }, + "javascript": { + "formatter": { + "quoteStyle": "double" // Double quotes for strings + } + }, + "assist": { + "actions": { + "source": { + "organizeImports": "on" // Auto-organize imports + } + } + } +} +``` + +**Key Style Rules:** +- Double quotes for strings +- 2-space indentation +- Automatic import organization +- Biome recommended linting rules +- TypeScript strict mode via `@tsconfig/strictest` + +### Development Workflow Integration + +```bash +# Format and lint check +pnpm lint + +# Auto-fix all issues (including unsafe fixes) +pnpm fix + +# Type checking +pnpm typecheck +``` ## Testing Strategy