claude-code-templates 1.13.2 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,269 +7,74 @@
7
7
 
8
8
  # Claude Code Templates
9
9
 
10
- **CLI tool for configuring and monitoring Claude Code** - Quick setup for any project with framework-specific commands and real-time monitoring dashboard. Open source and runs locally.
10
+ **CLI tool for configuring and monitoring Claude Code** - Quick setup for any project with framework-specific commands and real-time monitoring dashboard.
11
11
 
12
- ## 📋 Quick Start
12
+ ## 🚀 Quick Start
13
13
 
14
14
  ```bash
15
- # Run the tool (no installation required!)
15
+ # Interactive setup (recommended)
16
16
  npx claude-code-templates@latest
17
- ```
18
-
19
- ## Core Features
20
-
21
- ### 📊 Real-time Analytics Dashboard
22
- Monitor and optimize your Claude Code agents with our comprehensive analytics dashboard:
23
- - **Live Session Tracking**: See active conversations and their status in real-time
24
- - **Real-time State Detection**: "Claude Code working...", "User typing...", "Awaiting user input..."
25
- - **Usage Statistics**: Total sessions, tokens, and project activity with interactive charts
26
- - **Conversation History**: Complete session logs with export capabilities (CSV/JSON)
27
- - **Browser Notifications**: Get notified when Claude is waiting for your input
28
- - **Performance Monitoring**: Track Claude Code agent performance and optimization opportunities
29
- - **Web Interface**: Clean, terminal-style dashboard at `http://localhost:3333`
30
-
31
- ### 🔍 Comprehensive Health Check
32
- Complete system validation and configuration verification:
33
- - **System Requirements**: Validate OS, Node.js, memory, and network connectivity
34
- - **Claude Code Setup**: Verify installation, authentication, and permissions
35
- - **Project Configuration**: Check project structure and configuration files
36
- - **Custom Commands**: Validate slash commands and syntax
37
- - **Hooks Configuration**: Verify automation hooks and command availability
38
- - **Interactive Results**: Real-time progress with immediate feedback and recommendations
39
- - **Health Score**: Overall system health percentage with actionable insights
40
-
41
- ### 📋 Smart Project Setup
42
- Intelligent project configuration with framework-specific commands:
43
- - **Auto-Detection**: Automatically detect your project type and suggest optimal configurations
44
- - **Quick Setup**: Framework-specific commands for testing, linting, building, debugging, and deployment
45
- - **Optimized Workflows**: Pre-configured commands tailored to your development stack
46
- - **Best Practices**: Industry-standard configurations and development patterns
47
-
48
- ## What Gets Installed
49
-
50
- ### Core Files
51
- - **`CLAUDE.md`** - Main configuration file with language-specific best practices
52
- - **`.claude/settings.json`** - Automation hooks and Claude Code settings
53
- - **`.claude/commands/`** - Custom commands for common development tasks
54
- - **`.mcp.json`** - Model Context Protocol server configurations
55
-
56
- ## Supported Languages & Frameworks
57
-
58
- | Language | Frameworks | Status | Commands | Hooks | MCP |
59
- |----------|------------|---------|----------|--------|-----|
60
- | **JavaScript/TypeScript** | React, Vue, Angular, Node.js | ✅ Ready | 7+ | 9+ | 4+ |
61
- | **Python** | Django, Flask, FastAPI | ✅ Ready | 5+ | 8+ | 4+ |
62
- | **Common** | Universal | ✅ Ready | 2+ | 1+ | 4+ |
63
- | **Go** | Gin, Echo, Fiber | 🚧 Coming Soon | - | - | - |
64
- | **Rust** | Axum, Warp, Actix | 🚧 Coming Soon | - | - | - |
65
-
66
- ## Usage Examples
67
-
68
- ### Interactive Setup (Recommended)
69
- ```bash
70
- cd my-react-app
71
- npx claude-code-templates
72
- # Choose between Analytics Dashboard, Health Check, or Project Setup
73
- ```
74
17
 
75
- ### Analytics Dashboard
76
- ```bash
77
- # Launch real-time analytics dashboard
78
- npx claude-code-templates --analytics
18
+ # Real-time analytics dashboard
19
+ npx claude-code-templates@latest --analytics
79
20
 
80
- # Launch chats/conversations dashboard (opens directly to conversations)
81
- npx claude-code-templates --chats
82
- npx claude-code-templates --agents
21
+ # System health check
22
+ npx claude-code-templates@latest --health-check
83
23
  ```
84
24
 
85
- ### Health Check
86
- ```bash
87
- # Run comprehensive system validation
88
- npx claude-code-templates --health-check
89
- npx claude-code-templates --health
90
- npx claude-code-templates --check
91
- npx claude-code-templates --verify
92
- ```
25
+ ## Core Features
93
26
 
94
- ### Framework-Specific Quick Setup
95
- ```bash
96
- # React + TypeScript project
97
- npx claude-code-templates --language javascript-typescript --framework react --yes
27
+ - **📋 Smart Project Setup** - Auto-detect and configure any project with framework-specific commands
28
+ - **📊 Real-time Analytics** - Monitor Claude Code sessions with live state detection and performance metrics
29
+ - **🔍 Health Check** - Comprehensive system validation with actionable recommendations
30
+ - **🧩 Individual Components** - Install specialized agents, commands, and MCPs individually
98
31
 
99
- # Python + Django project
100
- npx claude-code-templates --language python --framework django --yes
101
- ```
102
-
103
- ### Analysis Tools
104
- ```bash
105
- # Analyze existing commands
106
- npx claude-code-templates --commands-stats
32
+ ## 🎯 What You Get
107
33
 
108
- # Analyze automation hooks
109
- npx claude-code-templates --hooks-stats
110
-
111
- # Analyze MCP server configurations
112
- npx claude-code-templates --mcps-stats
113
- ```
114
-
115
- ### Alternative Commands
116
- All these commands work exactly the same way:
117
-
118
- ```bash
119
- npx claude-code-templates # ✅ Recommended (package name)
120
- npx cct # ⚡ Super short (3 letters)
121
- npx claude-setup # Setup-style command
122
- npx create-claude-config # Create-style command
123
- ```
34
+ | Component | Description | Example |
35
+ |-----------|-------------|---------|
36
+ | **CLAUDE.md** | Project-specific Claude Code configuration | Framework best practices, coding standards |
37
+ | **Commands** | Custom slash commands for development tasks | `/generate-tests`, `/check-file`, `/optimize-bundle` |
38
+ | **Agents** | AI specialists for specific domains | API security audit, React performance, database optimization |
39
+ | **MCPs** | External service integrations | GitHub, databases, development tools |
40
+ | **Analytics** | Real-time monitoring dashboard | Live session tracking, usage statistics, exports |
124
41
 
125
- ## CLI Options
42
+ ## 🛠️ Supported Technologies
126
43
 
127
- | Option | Description | Example |
128
- |--------|-------------|---------|
129
- | `-l, --language` | Specify programming language | `--language python` |
130
- | `-f, --framework` | Specify framework | `--framework react` |
131
- | `-d, --directory` | Target directory | `--directory /path/to/project` |
132
- | `-y, --yes` | Skip prompts and use defaults | `--yes` |
133
- | `--dry-run` | Show what would be installed | `--dry-run` |
134
- | `--analytics` | Launch real-time analytics dashboard | `--analytics` |
135
- | `--chats` | Launch chats/conversations dashboard | `--chats` |
136
- | `--agents` | Launch agents dashboard (alias for chats) | `--agents` |
137
- | `--health-check` | Run comprehensive system validation | `--health-check` |
138
- | `--health` | Run system health check (alias) | `--health` |
139
- | `--check` | Run system validation (alias) | `--check` |
140
- | `--verify` | Verify system configuration (alias) | `--verify` |
141
- | `--commands-stats` | Analyze existing commands | `--commands-stats` |
142
- | `--hooks-stats` | Analyze automation hooks | `--hooks-stats` |
143
- | `--mcps-stats` | Analyze MCP server configurations | `--mcps-stats` |
144
- | `--help` | Show help information | `--help` |
44
+ | Language | Frameworks | Status |
45
+ |----------|------------|---------|
46
+ | **JavaScript/TypeScript** | React, Vue, Angular, Node.js | Ready |
47
+ | **Python** | Django, Flask, FastAPI | Ready |
48
+ | **Common** | Universal configurations | Ready |
49
+ | **Go** | Gin, Echo, Fiber | 🚧 Coming Soon |
50
+ | **Rust** | Axum, Warp, Actix | 🚧 Coming Soon |
145
51
 
146
- ## 🏗️ Modular Architecture
52
+ ## 📖 Documentation
147
53
 
148
- The analytics dashboard is built with a modern, scalable modular architecture designed for performance and maintainability.
54
+ **[📚 Complete Documentation](https://aitmpl.com/docu/)** - Comprehensive guides, examples, and API reference
149
55
 
150
- ### Backend Architecture
151
-
152
- #### Core Modules
153
- - **`StateCalculator`** - Advanced conversation state detection with real-time analysis
154
- - **`ProcessDetector`** - Running process detection and conversation linking
155
- - **`ConversationAnalyzer`** - Message parsing, token counting, and conversation analysis
156
- - **`FileWatcher`** - Real-time file system monitoring with efficient change detection
157
- - **`DataCache`** - Multi-level caching system with smart invalidation strategies
158
-
159
- #### Data Layer
160
- - **`DataCache`** - Intelligent caching with file content, parsed data, and computation result caching
161
- - **Performance Monitoring** - Request tracking, memory monitoring, and system health metrics
162
-
163
- #### Notification System
164
- - **`WebSocketServer`** - Real-time WebSocket communication with client management
165
- - **`NotificationManager`** - Event-driven notification system with subscription management
166
- - **Real-time Updates** - Live conversation state changes and data refresh notifications
167
-
168
- #### Performance & Monitoring
169
- - **`PerformanceMonitor`** - Comprehensive performance tracking and system health monitoring
170
- - **Express Middleware** - Request timing, error tracking, and API performance metrics
171
- - **WebSocket Monitoring** - Connection tracking, message metrics, and client health monitoring
172
-
173
- ### Frontend Architecture
174
-
175
- #### Modular Components
176
- - **`Dashboard`** - Main orchestration component with state management integration
177
- - **`ConversationTable`** - Interactive conversation display with real-time status updates
178
- - **`Charts`** - Dynamic data visualization with Chart.js integration
179
- - **`StateService`** - Reactive state management with subscriber patterns
180
- - **`DataService`** - API communication with intelligent caching and real-time integration
181
- - **`WebSocketService`** - Real-time communication with automatic reconnection
182
-
183
- #### Real-time Features
184
- - **Live State Detection** - Real-time conversation status: "Claude working...", "User typing...", "Awaiting input..."
185
- - **Auto-refresh** - Smart polling with WebSocket fallback for seamless data updates
186
- - **Browser Notifications** - Desktop notifications for important state changes
187
- - **Responsive Design** - Mobile-friendly interface with real-time data synchronization
188
-
189
- ### Performance Optimizations
190
-
191
- #### Caching Strategy
192
- - **File Content Cache** - Reduces disk I/O with timestamp-based invalidation
193
- - **Parsed Data Cache** - Stores analyzed conversation data with dependency tracking
194
- - **API Response Cache** - Client-side caching with TTL and smart refresh
195
- - **Computation Cache** - Caches expensive calculations with automatic invalidation
196
-
197
- #### Real-time Efficiency
198
- - **WebSocket Integration** - Eliminates polling overhead for live updates
199
- - **Smart Refresh** - Only updates changed data with differential loading
200
- - **Process Detection** - Efficient system process monitoring without performance impact
201
- - **Memory Management** - Automatic cleanup of old metrics and cached data
202
-
203
- ### Testing Framework
204
-
205
- #### Comprehensive Test Suite
206
- - **Unit Tests** - Individual module testing with 80%+ coverage requirement
207
- - **Integration Tests** - End-to-end system testing with real data scenarios
208
- - **Performance Tests** - Load testing and performance regression detection
209
- - **WebSocket Tests** - Real-time communication testing with mock clients
210
-
211
- #### Test Coverage
212
- - **Backend Modules**: StateCalculator, DataCache, WebSocketServer, PerformanceMonitor
213
- - **Frontend Services**: DataService, StateService, WebSocketService
214
- - **Integration Testing**: Complete analytics system with real conversation data
215
- - **Performance Testing**: Concurrent operations, memory usage, and response times
216
-
217
- ### Development Benefits
218
-
219
- #### Scalability
220
- - **Modular Design** - Easy to extend with new features and integrations
221
- - **Dependency Injection** - Loose coupling for flexible testing and development
222
- - **Event-driven Architecture** - Scalable notification system for future enhancements
223
-
224
- #### Maintainability
225
- - **Separation of Concerns** - Clear boundaries between data, business logic, and presentation
226
- - **Comprehensive Logging** - Detailed performance and error tracking for debugging
227
- - **Type Safety** - Consistent error handling and data validation throughout
228
-
229
- #### Performance
230
- - **Multi-level Caching** - Optimized data access patterns with intelligent invalidation
231
- - **Real-time Updates** - WebSocket-based communication eliminates polling overhead
232
- - **Memory Optimization** - Automatic cleanup and configurable memory thresholds
233
- - **Request Monitoring** - Complete visibility into system performance and bottlenecks
234
-
235
- ## Safety Features
236
-
237
- - **Automatic Backups**: Existing files are backed up before changes
238
- - **Confirmation Required**: Always asks before making changes (unless `--yes` flag)
239
- - **Dry Run Mode**: Preview installation with `--dry-run`
240
- - **Cancel Anytime**: Press Ctrl+C or answer 'No' to cancel
241
-
242
- ## What Makes This Special?
243
-
244
- ### Before (Manual Setup)
245
- - Hours of configuration research
246
- - Manual CLAUDE.md creation
247
- - Framework-specific command setup
248
- - Automation hook configuration
249
- - MCP server integration
250
-
251
- ### After (With Templates)
252
- ```bash
253
- npx claude-code-templates --language javascript-typescript --framework react --yes
254
- # ✅ Done in 30 seconds!
255
- ```
56
+ Quick links:
57
+ - [Getting Started](https://aitmpl.com/docu/docs/intro) - Installation and first steps
58
+ - [Project Setup](https://aitmpl.com/docu/docs/project-setup/interactive-setup) - Configure your projects
59
+ - [Analytics Dashboard](https://aitmpl.com/docu/docs/analytics/overview) - Real-time monitoring
60
+ - [Individual Components](https://aitmpl.com/docu/docs/components/overview) - Agents, Commands, MCPs
61
+ - [CLI Options](https://aitmpl.com/docu/docs/cli-options) - All available commands
256
62
 
257
63
  ## 🤝 Contributing
258
64
 
259
- We welcome contributions from the open source community!
260
-
261
- **See our [GitHub repository](https://github.com/davila7/claude-code-templates) for detailed guidelines**
65
+ We welcome contributions! Browse available templates and components at **[aitmpl.com](https://aitmpl.com)**, then check our [contributing guidelines](https://github.com/davila7/claude-code-templates/blob/main/CONTRIBUTING.md).
262
66
 
263
67
  ## 📄 License
264
68
 
265
- This project is licensed under the MIT License.
69
+ MIT License - see the [LICENSE](LICENSE) file for details.
266
70
 
267
- ## 📞 Support
71
+ ## 🔗 Links
268
72
 
269
- - **🐛 Issues**: [Report bugs or request features](https://github.com/davila7/claude-code-templates/issues)
270
- - **💬 Discussions**: [Join community discussions](https://github.com/davila7/claude-code-templates/discussions)
271
- - **📖 Documentation**: [Claude Code Official Docs](https://docs.anthropic.com/en/docs/claude-code)
73
+ - **🌐 Browse Components**: [aitmpl.com](https://aitmpl.com)
74
+ - **📚 Documentation**: [aitmpl.com/docu](https://aitmpl.com/docu)
75
+ - **🐛 Issues**: [GitHub Issues](https://github.com/davila7/claude-code-templates/issues)
76
+ - **💬 Discussions**: [GitHub Discussions](https://github.com/davila7/claude-code-templates/discussions)
272
77
 
273
78
  ---
274
79
 
275
- **⭐ Found this useful? Give us a star on [GitHub](https://github.com/davila7/claude-code-templates) to support the project!**
80
+ **⭐ Found this useful? Give us a star to support the project!**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-templates",
3
- "version": "1.13.2",
3
+ "version": "1.14.0",
4
4
  "description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -16,6 +16,9 @@ class AgentsPage {
16
16
  };
17
17
  this.isInitialized = false;
18
18
 
19
+ // Initialize header component
20
+ this.headerComponent = null;
21
+
19
22
  // Pagination state for conversations
20
23
  this.pagination = {
21
24
  currentPage: 0,
@@ -586,22 +589,8 @@ class AgentsPage {
586
589
  async render() {
587
590
  this.container.innerHTML = `
588
591
  <div class="agents-page">
589
- <!-- Page Header -->
590
- <div class="page-header conversations-header">
591
- <div class="header-content">
592
- <div class="header-left">
593
- <div class="status-header">
594
- <span class="session-timer-status-dot active"></span>
595
- <h1 class="page-title">
596
- Claude Code web UI
597
- </h1>
598
- </div>
599
- <div class="page-subtitle">
600
- Monitor and analyze Claude Code agent interactions in real-time
601
- </div>
602
- </div>
603
- </div>
604
- </div>
592
+ <!-- Page Header (will be replaced by HeaderComponent) -->
593
+ <div id="agents-header-container"></div>
605
594
 
606
595
  <!-- Filters Section -->
607
596
  <div class="conversations-filters">
@@ -784,6 +773,28 @@ class AgentsPage {
784
773
 
785
774
  this.bindEvents();
786
775
  this.setupInfiniteScroll();
776
+ this.initializeHeaderComponent();
777
+ }
778
+
779
+ /**
780
+ * Initialize the header component
781
+ */
782
+ initializeHeaderComponent() {
783
+ const headerContainer = this.container.querySelector('#agents-header-container');
784
+ if (headerContainer && typeof HeaderComponent !== 'undefined') {
785
+ this.headerComponent = new HeaderComponent(headerContainer, {
786
+ title: 'Claude Code Chats',
787
+ subtitle: 'Monitor and analyze Claude Code agent interactions in real-time',
788
+ version: 'v1.13.2', // Fallback version
789
+ showVersionBadge: true,
790
+ showLastUpdate: true,
791
+ showThemeSwitch: true,
792
+ showGitHubLink: true,
793
+ dataService: this.dataService // Pass DataService for dynamic version loading
794
+ });
795
+
796
+ this.headerComponent.render();
797
+ }
787
798
  }
788
799
 
789
800
  /**
@@ -4716,6 +4727,12 @@ class AgentsPage {
4716
4727
  * Destroy agents page
4717
4728
  */
4718
4729
  destroy() {
4730
+ // Cleanup header component
4731
+ if (this.headerComponent) {
4732
+ this.headerComponent.destroy();
4733
+ this.headerComponent = null;
4734
+ }
4735
+
4719
4736
  // Cleanup components
4720
4737
  Object.values(this.components).forEach(component => {
4721
4738
  if (component.destroy) {
@@ -13,6 +13,9 @@ class DashboardPage {
13
13
  this.refreshInterval = null;
14
14
  this.isInitialized = false;
15
15
 
16
+ // Initialize header component
17
+ this.headerComponent = null;
18
+
16
19
  // Subscribe to state changes
17
20
  this.unsubscribe = this.stateService.subscribe(this.handleStateChange.bind(this));
18
21
  }
@@ -118,42 +121,8 @@ class DashboardPage {
118
121
  async render() {
119
122
  this.container.innerHTML = `
120
123
  <div class="dashboard-page">
121
- <!-- Page Header -->
122
- <div class="page-header">
123
- <div class="header-content">
124
- <div class="header-left">
125
- <div class="status-header">
126
- <span class="session-timer-status-dot active" id="session-status-dot"></span>
127
- <h1 class="page-title">
128
- Claude Code Analytics Dashboard
129
- <span class="version-badge">v1.10.1</span>
130
- </h1>
131
- </div>
132
- <div class="page-subtitle">
133
- Real-time monitoring and analytics for Claude Code sessions
134
- </div>
135
- <div class="last-update-header">
136
- <span class="last-update-label">last update:</span>
137
- <span id="last-update-header-text">Never</span>
138
- </div>
139
- </div>
140
- <div class="header-right">
141
- <div class="theme-switch-container" title="Toggle light/dark theme">
142
- <div class="theme-switch" id="header-theme-switch">
143
- <div class="theme-switch-track">
144
- <div class="theme-switch-thumb" id="header-theme-switch-thumb">
145
- <span class="theme-switch-icon">🌙</span>
146
- </div>
147
- </div>
148
- </div>
149
- </div>
150
- <a href="https://github.com/davila7/claude-code-templates" target="_blank" class="github-link" title="Star on GitHub">
151
- <span class="github-icon">⭐</span>
152
- Star on GitHub
153
- </a>
154
- </div>
155
- </div>
156
- </div>
124
+ <!-- Page Header (will be replaced by HeaderComponent) -->
125
+ <div id="dashboard-header-container"></div>
157
126
 
158
127
  <!-- Action Buttons -->
159
128
  <div class="action-buttons-container">
@@ -394,7 +363,28 @@ class DashboardPage {
394
363
  `;
395
364
 
396
365
  this.bindEvents();
397
- this.initializeTheme();
366
+ this.initializeHeaderComponent();
367
+ }
368
+
369
+ /**
370
+ * Initialize the header component
371
+ */
372
+ initializeHeaderComponent() {
373
+ const headerContainer = this.container.querySelector('#dashboard-header-container');
374
+ if (headerContainer && typeof HeaderComponent !== 'undefined') {
375
+ this.headerComponent = new HeaderComponent(headerContainer, {
376
+ title: 'Claude Code Analytics Dashboard',
377
+ subtitle: 'Real-time monitoring and analytics for Claude Code sessions',
378
+ version: 'v1.13.2', // Fallback version
379
+ showVersionBadge: true,
380
+ showLastUpdate: true,
381
+ showThemeSwitch: true,
382
+ showGitHubLink: true,
383
+ dataService: this.dataService // Pass DataService for dynamic version loading
384
+ });
385
+
386
+ this.headerComponent.render();
387
+ }
398
388
  }
399
389
 
400
390
  /**
@@ -884,11 +874,6 @@ class DashboardPage {
884
874
  retryBtn.addEventListener('click', () => this.loadInitialData());
885
875
  }
886
876
 
887
- // Theme toggle (header)
888
- const headerThemeSwitch = this.container.querySelector('#header-theme-switch');
889
- if (headerThemeSwitch) {
890
- headerThemeSwitch.addEventListener('click', () => this.toggleTheme());
891
- }
892
877
  }
893
878
 
894
879
  /**
@@ -2105,74 +2090,13 @@ class DashboardPage {
2105
2090
  }
2106
2091
  }
2107
2092
 
2108
- /**
2109
- * Initialize theme from localStorage
2110
- */
2111
- initializeTheme() {
2112
- const savedTheme = localStorage.getItem('claude-analytics-theme') || 'dark';
2113
- const body = document.body;
2114
- const headerThumb = this.container.querySelector('#header-theme-switch-thumb');
2115
- const headerIcon = headerThumb?.querySelector('.theme-switch-icon');
2116
-
2117
- body.setAttribute('data-theme', savedTheme);
2118
- if (headerThumb && headerIcon) {
2119
- if (savedTheme === 'light') {
2120
- headerThumb.classList.add('light');
2121
- headerIcon.textContent = '☀️';
2122
- } else {
2123
- headerThumb.classList.remove('light');
2124
- headerIcon.textContent = '🌙';
2125
- }
2126
- }
2127
- }
2128
-
2129
- /**
2130
- * Toggle theme between light and dark
2131
- */
2132
- toggleTheme() {
2133
- const body = document.body;
2134
- const headerThumb = this.container.querySelector('#header-theme-switch-thumb');
2135
- const headerIcon = headerThumb?.querySelector('.theme-switch-icon');
2136
-
2137
- // Also sync with global theme switch
2138
- const globalThumb = document.getElementById('themeSwitchThumb');
2139
- const globalIcon = globalThumb?.querySelector('.theme-switch-icon');
2140
-
2141
- const isLight = body.getAttribute('data-theme') === 'light';
2142
- const newTheme = isLight ? 'dark' : 'light';
2143
-
2144
- body.setAttribute('data-theme', newTheme);
2145
-
2146
- // Update header theme switch
2147
- if (headerThumb && headerIcon) {
2148
- headerThumb.classList.toggle('light', newTheme === 'light');
2149
- headerIcon.textContent = newTheme === 'light' ? '☀️' : '🌙';
2150
- }
2151
-
2152
- // Sync with global theme switch
2153
- if (globalThumb && globalIcon) {
2154
- globalThumb.classList.toggle('light', newTheme === 'light');
2155
- globalIcon.textContent = newTheme === 'light' ? '☀️' : '🌙';
2156
- }
2157
-
2158
- localStorage.setItem('claude-analytics-theme', newTheme);
2159
- }
2160
2093
 
2161
2094
  /**
2162
2095
  * Update last update time
2163
2096
  */
2164
2097
  updateLastUpdateTime() {
2165
- const currentTime = new Date().toLocaleTimeString();
2166
-
2167
- // Update both locations
2168
- const lastUpdateText = this.container.querySelector('#last-update-text');
2169
- const lastUpdateHeaderText = this.container.querySelector('#last-update-header-text');
2170
-
2171
- if (lastUpdateText) {
2172
- lastUpdateText.textContent = currentTime;
2173
- }
2174
- if (lastUpdateHeaderText) {
2175
- lastUpdateHeaderText.textContent = currentTime;
2098
+ if (this.headerComponent) {
2099
+ this.headerComponent.updateLastUpdateTime();
2176
2100
  }
2177
2101
  }
2178
2102
 
@@ -2252,6 +2176,12 @@ class DashboardPage {
2252
2176
  destroy() {
2253
2177
  this.stopPeriodicRefresh();
2254
2178
 
2179
+ // Cleanup header component
2180
+ if (this.headerComponent) {
2181
+ this.headerComponent.destroy();
2182
+ this.headerComponent = null;
2183
+ }
2184
+
2255
2185
  // Cleanup Chart.js instances specifically
2256
2186
  if (this.components.tokenChart) {
2257
2187
  this.components.tokenChart.destroy();
@@ -0,0 +1,307 @@
1
+ /**
2
+ * HeaderComponent - Unified header for all analytics pages
3
+ * Provides consistent branding, navigation, and controls across the application
4
+ */
5
+ class HeaderComponent {
6
+ constructor(container, options = {}) {
7
+ this.container = container;
8
+ this.options = {
9
+ title: options.title || 'Claude Code Analytics Dashboard',
10
+ subtitle: options.subtitle || 'Real-time monitoring and analytics for Claude Code sessions',
11
+ showVersionBadge: options.showVersionBadge !== false,
12
+ showLastUpdate: options.showLastUpdate !== false,
13
+ showThemeSwitch: options.showThemeSwitch !== false,
14
+ showGitHubLink: options.showGitHubLink !== false,
15
+ version: options.version || 'v1.13.2', // Default fallback
16
+ customActions: options.customActions || [],
17
+ dataService: options.dataService || null, // DataService for dynamic version loading
18
+ ...options
19
+ };
20
+
21
+ this.lastUpdateTime = null;
22
+ this.updateInterval = null;
23
+ this.actualVersion = this.options.version; // Will be updated dynamically
24
+ }
25
+
26
+ /**
27
+ * Render the header component
28
+ */
29
+ render() {
30
+ const headerHTML = `
31
+ <div class="page-header">
32
+ <div class="header-content">
33
+ <div class="header-left">
34
+ <div class="status-header">
35
+ <span class="session-timer-status-dot active" id="session-status-dot"></span>
36
+ <h1 class="page-title">
37
+ ${this.options.title}
38
+ ${this.options.showVersionBadge ? `<span class="version-badge" id="version-badge">${this.actualVersion}</span>` : ''}
39
+ </h1>
40
+ </div>
41
+ <div class="page-subtitle">
42
+ ${this.options.subtitle}
43
+ </div>
44
+ ${this.options.showLastUpdate ? `
45
+ <div class="last-update-header">
46
+ <span class="last-update-label">last update:</span>
47
+ <span id="last-update-header-text">Never</span>
48
+ </div>
49
+ ` : ''}
50
+ </div>
51
+ <div class="header-right">
52
+ ${this.options.showThemeSwitch ? `
53
+ <div class="theme-switch-container" title="Toggle light/dark theme">
54
+ <div class="theme-switch" id="header-theme-switch">
55
+ <div class="theme-switch-track">
56
+ <div class="theme-switch-thumb" id="header-theme-switch-thumb">
57
+ <span class="theme-switch-icon">🌙</span>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ ` : ''}
63
+ ${this.options.showGitHubLink ? `
64
+ <a href="https://github.com/davila7/claude-code-templates" target="_blank" class="github-link" title="Star on GitHub">
65
+ <span class="github-icon">⭐</span>
66
+ Star on GitHub
67
+ </a>
68
+ ` : ''}
69
+ ${this.renderCustomActions()}
70
+ </div>
71
+ </div>
72
+ </div>
73
+ `;
74
+
75
+ this.container.innerHTML = headerHTML;
76
+ this.bindEvents();
77
+ this.initializeTheme();
78
+
79
+ if (this.options.showLastUpdate) {
80
+ this.updateLastUpdateTime();
81
+ this.startUpdateInterval();
82
+ }
83
+
84
+ // Load version dynamically if DataService is available
85
+ if (this.options.dataService) {
86
+ this.loadVersion();
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Render custom actions in header
92
+ */
93
+ renderCustomActions() {
94
+ if (!this.options.customActions || this.options.customActions.length === 0) {
95
+ return '';
96
+ }
97
+
98
+ return this.options.customActions.map(action => `
99
+ <button class="header-action-btn" id="${action.id}" title="${action.title || action.label}">
100
+ ${action.icon ? `<span class="btn-icon">${action.icon}</span>` : ''}
101
+ ${action.label}
102
+ </button>
103
+ `).join('');
104
+ }
105
+
106
+ /**
107
+ * Bind event listeners
108
+ */
109
+ bindEvents() {
110
+ // Theme toggle
111
+ if (this.options.showThemeSwitch) {
112
+ const themeSwitch = this.container.querySelector('#header-theme-switch');
113
+ if (themeSwitch) {
114
+ themeSwitch.addEventListener('click', () => this.toggleTheme());
115
+ }
116
+ }
117
+
118
+ // Custom action handlers
119
+ this.options.customActions.forEach(action => {
120
+ const btn = this.container.querySelector(`#${action.id}`);
121
+ if (btn && action.handler) {
122
+ btn.addEventListener('click', action.handler);
123
+ }
124
+ });
125
+ }
126
+
127
+ /**
128
+ * Initialize theme from localStorage
129
+ */
130
+ initializeTheme() {
131
+ if (!this.options.showThemeSwitch) return;
132
+
133
+ const savedTheme = localStorage.getItem('claude-analytics-theme') || 'dark';
134
+ const body = document.body;
135
+ const headerThumb = this.container.querySelector('#header-theme-switch-thumb');
136
+ const headerIcon = headerThumb?.querySelector('.theme-switch-icon');
137
+
138
+ body.setAttribute('data-theme', savedTheme);
139
+ if (headerThumb && headerIcon) {
140
+ if (savedTheme === 'light') {
141
+ headerThumb.classList.add('light');
142
+ headerIcon.textContent = '☀️';
143
+ } else {
144
+ headerThumb.classList.remove('light');
145
+ headerIcon.textContent = '🌙';
146
+ }
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Toggle theme between light and dark
152
+ */
153
+ toggleTheme() {
154
+ const body = document.body;
155
+ const headerThumb = this.container.querySelector('#header-theme-switch-thumb');
156
+ const headerIcon = headerThumb?.querySelector('.theme-switch-icon');
157
+
158
+ // Also sync with global theme switch if exists
159
+ const globalThumb = document.getElementById('themeSwitchThumb');
160
+ const globalIcon = globalThumb?.querySelector('.theme-switch-icon');
161
+
162
+ const isLight = body.getAttribute('data-theme') === 'light';
163
+ const newTheme = isLight ? 'dark' : 'light';
164
+
165
+ body.setAttribute('data-theme', newTheme);
166
+
167
+ // Update header theme switch
168
+ if (headerThumb && headerIcon) {
169
+ headerThumb.classList.toggle('light', newTheme === 'light');
170
+ headerIcon.textContent = newTheme === 'light' ? '☀️' : '🌙';
171
+ }
172
+
173
+ // Sync with global theme switch
174
+ if (globalThumb && globalIcon) {
175
+ globalThumb.classList.toggle('light', newTheme === 'light');
176
+ globalIcon.textContent = newTheme === 'light' ? '☀️' : '🌙';
177
+ }
178
+
179
+ localStorage.setItem('claude-analytics-theme', newTheme);
180
+ }
181
+
182
+ /**
183
+ * Update last update time
184
+ */
185
+ updateLastUpdateTime() {
186
+ if (!this.options.showLastUpdate) return;
187
+
188
+ const currentTime = new Date().toLocaleTimeString();
189
+ const lastUpdateText = this.container.querySelector('#last-update-header-text');
190
+
191
+ if (lastUpdateText) {
192
+ lastUpdateText.textContent = currentTime;
193
+ }
194
+
195
+ this.lastUpdateTime = currentTime;
196
+ }
197
+
198
+ /**
199
+ * Start periodic update of timestamp
200
+ */
201
+ startUpdateInterval() {
202
+ if (this.updateInterval) {
203
+ clearInterval(this.updateInterval);
204
+ }
205
+
206
+ // Update every 30 seconds
207
+ this.updateInterval = setInterval(() => {
208
+ this.updateLastUpdateTime();
209
+ }, 30000);
210
+ }
211
+
212
+ /**
213
+ * Stop update interval
214
+ */
215
+ stopUpdateInterval() {
216
+ if (this.updateInterval) {
217
+ clearInterval(this.updateInterval);
218
+ this.updateInterval = null;
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Load version dynamically from backend
224
+ */
225
+ async loadVersion() {
226
+ if (!this.options.dataService) return;
227
+
228
+ try {
229
+ const versionData = await this.options.dataService.getVersion();
230
+ if (versionData && versionData.version) {
231
+ this.actualVersion = `v${versionData.version}`;
232
+ this.updateVersionBadge();
233
+ }
234
+ } catch (error) {
235
+ console.error('Error loading version:', error);
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Update version badge in the DOM
241
+ */
242
+ updateVersionBadge() {
243
+ const versionBadge = this.container.querySelector('#version-badge');
244
+ if (versionBadge) {
245
+ versionBadge.textContent = this.actualVersion;
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Update header title
251
+ * @param {string} title - New title
252
+ */
253
+ updateTitle(title) {
254
+ this.options.title = title;
255
+ const titleElement = this.container.querySelector('.page-title');
256
+ if (titleElement) {
257
+ titleElement.innerHTML = `
258
+ ${title}
259
+ ${this.options.showVersionBadge ? `<span class="version-badge" id="version-badge">${this.actualVersion}</span>` : ''}
260
+ `;
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Update header subtitle
266
+ * @param {string} subtitle - New subtitle
267
+ */
268
+ updateSubtitle(subtitle) {
269
+ this.options.subtitle = subtitle;
270
+ const subtitleElement = this.container.querySelector('.page-subtitle');
271
+ if (subtitleElement) {
272
+ subtitleElement.textContent = subtitle;
273
+ }
274
+ }
275
+
276
+ /**
277
+ * Update status dot state
278
+ * @param {boolean} active - Whether status should be active
279
+ */
280
+ updateStatusDot(active) {
281
+ const statusDot = this.container.querySelector('#session-status-dot');
282
+ if (statusDot) {
283
+ statusDot.classList.toggle('active', active);
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Get current theme
289
+ * @returns {string} Current theme ('light' or 'dark')
290
+ */
291
+ getCurrentTheme() {
292
+ return document.body.getAttribute('data-theme') || 'dark';
293
+ }
294
+
295
+ /**
296
+ * Destroy header component
297
+ */
298
+ destroy() {
299
+ this.stopUpdateInterval();
300
+ this.container.innerHTML = '';
301
+ }
302
+ }
303
+
304
+ // Export for module use
305
+ if (typeof module !== 'undefined' && module.exports) {
306
+ module.exports = HeaderComponent;
307
+ }
@@ -12,6 +12,7 @@
12
12
  <script src="services/StateService.js"></script>
13
13
 
14
14
  <!-- Component Scripts -->
15
+ <script src="components/HeaderComponent.js"></script>
15
16
  <script src="components/Charts.js"></script>
16
17
  <!-- Dashboard.js removed - deprecated architecture -->
17
18
  <script src="components/SessionTimer.js"></script>
@@ -2644,6 +2645,7 @@
2644
2645
  flex: 1;
2645
2646
  display: flex;
2646
2647
  flex-direction: column;
2648
+ margin-left: 56px;
2647
2649
  transition: margin-left 0.3s ease;
2648
2650
  }
2649
2651
 
@@ -2662,7 +2664,9 @@
2662
2664
  display: flex;
2663
2665
  flex-direction: column;
2664
2666
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
2665
- position: relative;
2667
+ position: fixed;
2668
+ top: 0;
2669
+ left: 0;
2666
2670
  z-index: 1000;
2667
2671
  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
2668
2672
  overflow: visible;
@@ -2673,6 +2677,10 @@
2673
2677
  background: var(--bg-secondary);
2674
2678
  border-right: 1px solid var(--text-accent);
2675
2679
  box-shadow: 4px 0 16px rgba(213, 116, 85, 0.1);
2680
+ position: fixed;
2681
+ top: 0;
2682
+ left: 0;
2683
+ height: 100vh;
2676
2684
  }
2677
2685
 
2678
2686
  .sidebar-header {
@@ -4616,32 +4624,7 @@
4616
4624
  margin: 0 auto;
4617
4625
  }
4618
4626
 
4619
- /* App Layout Styles (App.js + Sidebar.js) */
4620
- .app {
4621
- display: flex;
4622
- min-height: 100vh;
4623
- background: var(--bg-primary);
4624
- }
4625
-
4626
- .app-sidebar {
4627
- width: 60px;
4628
- background: var(--bg-secondary);
4629
- border-right: 1px solid var(--border-primary);
4630
- transition: width 0.3s ease;
4631
- }
4632
-
4633
- .app-main {
4634
- flex: 1;
4635
- display: flex;
4636
- flex-direction: column;
4637
- min-width: 0;
4638
- }
4639
-
4640
- .app-content {
4641
- flex: 1;
4642
- padding: 20px;
4643
- overflow-y: auto;
4644
- }
4627
+ /* App Layout Styles (App.js + Sidebar.js) - Duplicates removed, using definitions above */
4645
4628
 
4646
4629
  /* Metrics Section */
4647
4630
  .metrics-section {
@@ -409,6 +409,19 @@ class DataService {
409
409
  this.setupWebSocketIntegration();
410
410
  }
411
411
 
412
+ /**
413
+ * Get application version from backend
414
+ * @returns {Promise<Object>} Version information
415
+ */
416
+ async getVersion() {
417
+ try {
418
+ return await this.cachedFetch('/api/version', 300000); // Cache for 5 minutes
419
+ } catch (error) {
420
+ console.error('Error fetching version:', error);
421
+ return { version: '1.13.2', name: 'claude-code-templates' }; // Fallback
422
+ }
423
+ }
424
+
412
425
  /**
413
426
  * Get cache statistics
414
427
  * @returns {Object} Cache statistics
@@ -394,58 +394,62 @@ class HealthChecker {
394
394
  }
395
395
 
396
396
  checkAuthentication() {
397
+ const homeDir = os.homedir();
398
+
399
+ // Check for Claude Code OAuth authentication in ~/.claude.json
400
+ const claudeJsonPath = path.join(homeDir, '.claude.json');
401
+
397
402
  try {
398
- // Try to run claude command to check authentication status
399
- const output = execSync('claude auth status 2>&1', {
400
- encoding: 'utf8',
401
- stdio: 'pipe',
402
- timeout: 5000
403
- });
403
+ if (fs.existsSync(claudeJsonPath)) {
404
+ const claudeConfig = JSON.parse(fs.readFileSync(claudeJsonPath, 'utf8'));
405
+
406
+ // Check for OAuth authentication
407
+ if (claudeConfig.oauthAccount && claudeConfig.oauthAccount.accountUuid) {
408
+ const email = claudeConfig.oauthAccount.emailAddress || 'OAuth user';
409
+ return {
410
+ status: 'pass',
411
+ message: `Authenticated via OAuth (${email})`
412
+ };
413
+ }
414
+
415
+ // Check for API key authentication
416
+ if (claudeConfig.apiKey) {
417
+ return {
418
+ status: 'pass',
419
+ message: 'Authenticated via API key'
420
+ };
421
+ }
422
+ }
404
423
 
405
- if (output.includes('authenticated') || output.includes('logged in') || output.includes('active')) {
424
+ // Check for environment variable API key
425
+ if (process.env.ANTHROPIC_API_KEY) {
406
426
  return {
407
427
  status: 'pass',
408
- message: 'Authenticated and active'
428
+ message: 'Authenticated via ANTHROPIC_API_KEY environment variable'
409
429
  };
410
430
  }
411
431
 
412
- // If command runs but no clear authentication status
413
- return {
414
- status: 'warn',
415
- message: 'Authentication status unclear'
416
- };
417
-
418
- } catch (error) {
419
- // Try alternative method - check for session/config files
420
- const homeDir = os.homedir();
421
- const possibleAuthPaths = [
422
- path.join(homeDir, '.claude', 'session'),
423
- path.join(homeDir, '.claude', 'config'),
424
- path.join(homeDir, '.config', 'claude', 'session'),
425
- path.join(homeDir, '.config', 'claude', 'config'),
426
- path.join(homeDir, '.anthropic', 'session'),
427
- path.join(homeDir, '.anthropic', 'config')
428
- ];
429
-
430
- for (const authPath of possibleAuthPaths) {
431
- if (fs.existsSync(authPath)) {
432
- try {
433
- const stats = fs.statSync(authPath);
434
- // Check if file was modified recently (within last 30 days)
435
- const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
436
- if (stats.mtime > thirtyDaysAgo) {
437
- return {
438
- status: 'pass',
439
- message: 'Authentication session found'
440
- };
441
- }
442
- } catch (statError) {
443
- // Continue to next path
444
- }
445
- }
432
+ // Try to check if we can make a simple claude command
433
+ try {
434
+ execSync('claude --version', {
435
+ encoding: 'utf8',
436
+ stdio: 'pipe',
437
+ timeout: 3000
438
+ });
439
+
440
+ return {
441
+ status: 'warn',
442
+ message: 'Claude CLI available but authentication not configured'
443
+ };
444
+ } catch (cliError) {
445
+ return {
446
+ status: 'fail',
447
+ message: 'Claude CLI not available or not authenticated'
448
+ };
446
449
  }
447
450
 
448
- // Try to check if we can make a simple claude command
451
+ } catch (error) {
452
+ // If we can't read the config file, check if CLI is at least installed
449
453
  try {
450
454
  execSync('claude --version', {
451
455
  encoding: 'utf8',
@@ -460,7 +464,7 @@ class HealthChecker {
460
464
  } catch (cliError) {
461
465
  return {
462
466
  status: 'fail',
463
- message: 'Claude CLI not available or not authenticated'
467
+ message: 'Claude CLI not available or authentication check failed'
464
468
  };
465
469
  }
466
470
  }