claude-cli-analytics 0.0.1 → 0.0.5
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 +148 -60
- package/bin/cli.cjs +168 -0
- package/bin/sanity.mjs +3 -0
- package/dist/client/assets/{index-CXwfzzf8.js → index-B3X-FepG.js} +29 -22
- package/dist/client/index.html +1 -1
- package/dist/server/analyzer.js +305 -85
- package/dist/server/index.js +7 -5
- package/package.json +2 -2
- package/bin/cli.js +0 -44
package/README.md
CHANGED
|
@@ -4,8 +4,9 @@ Claude CLI 대화 로그를 분석하여 토큰 효율성, 캐시 활용률, 컨
|
|
|
4
4
|
|
|
5
5
|
## ✨ Features
|
|
6
6
|
|
|
7
|
-
- 📊 **Dashboard**:
|
|
8
|
-
- 📝 **Session Detail**: 세션별 대화 타임라인,
|
|
7
|
+
- 📊 **Dashboard**: Anthropic 스킬 평가 프레임워크 기반 지표, 토큰 분포, 트렌드 차트
|
|
8
|
+
- 📝 **Session Detail**: 세션별 대화 타임라인, 도구 사용 내역, 6카테고리 지표 패널
|
|
9
|
+
- 💬 **대화형 도구 표시**: AskUserQuestion 등 대화형 도구의 Q&A 내용을 카드로 표시
|
|
9
10
|
- 🔄 **Real-time Refresh**: 새로고침 버튼으로 최신 데이터 로드
|
|
10
11
|
- 🏆 **Engineering Grade**: S/A/B/C 등급 + SEI (Spec Efficiency Index) 분석
|
|
11
12
|
- 🔍 **Auto-detection**: `.claude/projects` 경로 자동 탐색 — init 불필요
|
|
@@ -32,7 +33,7 @@ npx claude-cli-analytics
|
|
|
32
33
|
### 🛠️ 소스에서 빌드 (기여용)
|
|
33
34
|
|
|
34
35
|
```bash
|
|
35
|
-
git clone https://github.com/
|
|
36
|
+
git clone https://github.com/rootTiket/claude-analytics.git
|
|
36
37
|
cd claude-analytics
|
|
37
38
|
npm install
|
|
38
39
|
npm run build
|
|
@@ -54,9 +55,38 @@ npm run dev
|
|
|
54
55
|
|
|
55
56
|
## 🛠️ Requirements
|
|
56
57
|
|
|
57
|
-
- Node.js
|
|
58
|
+
- Node.js 20+
|
|
58
59
|
- npm 9+
|
|
59
60
|
|
|
61
|
+
## 🚀 사용법
|
|
62
|
+
|
|
63
|
+
### 대시보드 시작
|
|
64
|
+
기본적으로 **백그라운드 모드**로 실행됩니다:
|
|
65
|
+
```bash
|
|
66
|
+
claude-cli-analytics
|
|
67
|
+
```
|
|
68
|
+
브라우저에서 `http://localhost:3001`이 자동으로 열리며, 서버는 백그라운드에서 실행됩니다.
|
|
69
|
+
|
|
70
|
+
### 대시보드 중지
|
|
71
|
+
백그라운드 프로세스를 중지합니다:
|
|
72
|
+
```bash
|
|
73
|
+
claude-cli-analytics exit
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 상태 확인
|
|
77
|
+
대시보드 실행 여부를 확인합니다:
|
|
78
|
+
```bash
|
|
79
|
+
claude-cli-analytics status
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 옵션
|
|
83
|
+
```bash
|
|
84
|
+
claude-cli-analytics --port 8080 # 커스텀 포트로 실행
|
|
85
|
+
claude-cli-analytics --path /foo # 커스텀 프로젝트 디렉토리
|
|
86
|
+
claude-cli-analytics --foreground # 포그라운드 실행 (Ctrl+C로 중지)
|
|
87
|
+
claude-cli-analytics --help # 도움말 표시
|
|
88
|
+
```
|
|
89
|
+
|
|
60
90
|
## 🔍 .claude 경로 자동 탐색
|
|
61
91
|
|
|
62
92
|
**별도의 `init` 과정이 필요 없습니다.** 서버 시작 시 자동으로 Claude Code의 데이터 디렉토리를 탐색합니다.
|
|
@@ -81,91 +111,149 @@ Claude Code는 설치 방법에 관계없이 항상 `~/.claude/projects`에 세
|
|
|
81
111
|
```bash
|
|
82
112
|
# 환경변수로 지정
|
|
83
113
|
CLAUDE_PROJECTS_DIR=/path/to/claude/projects claude-cli-analytics
|
|
114
|
+
```
|
|
84
115
|
|
|
85
|
-
|
|
86
|
-
claude-cli-analytics --path /path/to/claude/projects
|
|
116
|
+
## 📈 분석 지표 (Anthropic Skill Evaluation Framework)
|
|
87
117
|
|
|
88
|
-
|
|
89
|
-
claude-cli-analytics --port 8080
|
|
90
|
-
```
|
|
118
|
+
> Anthropic의 공식 스킬 평가 프레임워크를 기반으로 구성된 지표입니다.
|
|
91
119
|
|
|
92
|
-
|
|
120
|
+
---
|
|
93
121
|
|
|
94
|
-
###
|
|
122
|
+
### 📊 정량적 지표 (Quantitative Metrics)
|
|
95
123
|
|
|
96
|
-
|
|
97
|
-
|------|----------|------|
|
|
98
|
-
| **평균 컨텍스트** | `(input_tokens + cache_read) / 요청수` | 요청당 평균 컨텍스트 크기 |
|
|
99
|
-
| **위험 레벨** | `<20K: 안전, 20-50K: 주의, >50K: 위험` | 컨텍스트 과부하 경고 |
|
|
100
|
-
| **리미트 영향도** | `(총 컨텍스트 / 44,000) × 100%` | Claude Pro 5시간 한도 대비 사용량 |
|
|
124
|
+
#### 1. 컨텍스트 자동 탐색 성공률 (Skill Trigger Rate)
|
|
101
125
|
|
|
102
|
-
|
|
126
|
+
> *Anthropic 기준: 관련 쿼리의 90%에서 스킬이 트리거됨*
|
|
103
127
|
|
|
104
128
|
| 지표 | 계산 방식 | 목표 | 의미 |
|
|
105
129
|
|------|----------|------|------|
|
|
106
|
-
|
|
|
107
|
-
|
|
|
108
|
-
|
|
|
109
|
-
|
|
|
130
|
+
| **캐시 히트율** | `cache_read / (input + cache_read) × 100` | ≥ 70% | 스킬(컨텍스트)이 자동으로 로드된 비율 |
|
|
131
|
+
| **스펙 컨텍스트 활용률** | `spec 파일 읽은 세션 / 전체 세션 × 100` | ≥ 90% | `.claude/` 스펙이 자동 트리거된 비율 |
|
|
132
|
+
| **위험 레벨** | `<20K: 최적, 20-50K: 주의, >50K: 위험` | 최적 | 컨텍스트 과부하 경고 |
|
|
133
|
+
| **리미트 영향도** | `(총 컨텍스트 / 44,000) × 100%` | — | Claude Pro 5시간 한도 대비 사용량 |
|
|
110
134
|
|
|
111
|
-
|
|
135
|
+
**측정 방법**: 테스트 쿼리 10~20개를 실행하여, 자동으로 캐시 히트가 되는 비율과 스펙 컨텍스트가 로드되는 비율을 추적합니다.
|
|
112
136
|
|
|
113
|
-
|
|
114
|
-
- **Efficiency (40%)**: 캐시 히트율 기반
|
|
115
|
-
- **Stability (30%)**: 도구 오류율 기반
|
|
116
|
-
- **Precision (30%)**: Read/Edit 비율 기반
|
|
117
|
-
- **Penalty**: 팬텀 파일 접근 횟수 × 5
|
|
137
|
+
#### 2. 도구 호출 효율성 (Tool Call Efficiency)
|
|
118
138
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
139
|
+
> *Anthropic 기준: X도구 호출로 워크플로우 완료*
|
|
140
|
+
|
|
141
|
+
| 지표 | 계산 방식 | 목표 | 의미 |
|
|
142
|
+
|------|----------|------|------|
|
|
143
|
+
| **Read/Edit 비율** | `Read도구 횟수 / Edit도구 횟수` | ≥ 5:1 | 수정 전 충분한 탐색 여부 |
|
|
144
|
+
| **수정당 토큰** | `총 컨텍스트 / Edit 횟수` | < 50K | 수정 1회당 소비된 토큰 |
|
|
145
|
+
| **중복 읽기율** | `(전체읽기 - 고유파일) / 전체읽기 × 100` | < 20% | 불필요한 반복 읽기 비율 |
|
|
146
|
+
| **반복 수정율** | `(전체수정 - 고유파일) / 전체수정 × 100` | < 20% | 같은 파일 반복 수정 비율 |
|
|
147
|
+
|
|
148
|
+
**측정 방법**: 스킬(스펙 컨텍스트) 활성화 전후 동일 작업을 비교하여 도구 호출 횟수와 총 토큰 소비량을 집계합니다.
|
|
149
|
+
|
|
150
|
+
#### 3. API 실패율 (Failed API Calls per Workflow)
|
|
151
|
+
|
|
152
|
+
> *Anthropic 기준: 워크플로당 실패한 API 호출 0회*
|
|
125
153
|
|
|
126
|
-
|
|
154
|
+
| 지표 | 계산 방식 | 목표 | 의미 |
|
|
155
|
+
|------|----------|------|------|
|
|
156
|
+
| **도구 오류율** | `오류 도구 호출 / 전체 도구 호출 × 100` | 0% | 실패한 도구 호출 비율 |
|
|
157
|
+
| **오류 상세** | 도구별 오류 메시지 및 빈도 집계 | — | 재시도율 및 오류 코드 추적 |
|
|
158
|
+
| **세션 종료 유형** | `clean / forced / unknown` | clean | 비정상 종료 여부 |
|
|
159
|
+
|
|
160
|
+
**측정 방법**: 테스트 실행 중 도구 호출 로그를 모니터링하며, 재시도율 및 오류 코드를 추적합니다.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### 🎯 정성적 지표 (Qualitative Metrics)
|
|
165
|
+
|
|
166
|
+
#### 4. 사용자 개입 빈도 (User Intervention Frequency)
|
|
167
|
+
|
|
168
|
+
> *Anthropic 기준: 사용자가 Claude에게 다음 단계를 묻지 않아도 됨*
|
|
169
|
+
|
|
170
|
+
| 지표 | 계산 방식 | 목표 | 의미 |
|
|
171
|
+
|------|----------|------|------|
|
|
172
|
+
| **Human Turns** | 사용자 메시지(명령 포함) 횟수 | 최소화 | 사용자가 방향 전환/명확화한 횟수 |
|
|
173
|
+
| **Auto Turns** | 자동 실행된 턴 수 | 최대화 | 사용자 개입 없이 진행된 턴 수 |
|
|
174
|
+
| **HT/Edit 비율** | `Human Turns / Edit 횟수` | < 1.0 | 수정당 사용자 개입 빈도 |
|
|
175
|
+
|
|
176
|
+
**측정 방법**: 테스트 중 사용자가 방향을 전환하거나 명확히 설명해야 하는 빈도를 기록합니다.
|
|
177
|
+
|
|
178
|
+
#### 5. 워크플로우 자립 완료율 (Workflow Autonomy)
|
|
179
|
+
|
|
180
|
+
> *Anthropic 기준: 사용자 수정 없이 완료되는 워크플로우*
|
|
181
|
+
|
|
182
|
+
| 지표 | 계산 방식 | 목표 | 의미 |
|
|
183
|
+
|------|----------|------|------|
|
|
184
|
+
| **반복 수정율** | `(전체수정 - 고유파일) / 전체수정 × 100` | < 20% | 재작업 없이 완료된 비율 |
|
|
185
|
+
| **효율성 점수** | 캐시·오류·작업 효율 종합 (100점) | ≥ 80 | 워크플로우 자립 완성도 |
|
|
186
|
+
| **SEI** | `(Accuracy × 100) / log₁₀(Spec Volume + 1)` | — | 스펙 문서의 실효성 |
|
|
187
|
+
|
|
188
|
+
**측정 방법**: 동일 요청을 3~5회 실행하여 구조적 일관성과 품질 측면에서 출력을 비교합니다.
|
|
189
|
+
|
|
190
|
+
#### 6. 세션 간 일관성 (Cross-Session Consistency)
|
|
191
|
+
|
|
192
|
+
> *Anthropic 기준: 세션 간 일관된 결과*
|
|
193
|
+
|
|
194
|
+
| 지표 | 계산 방식 | 목표 | 의미 |
|
|
195
|
+
|------|----------|------|------|
|
|
196
|
+
| **Engineering Grade** | Efficiency(40%) + Stability(30%) + Precision(30%) - Penalty | S급 | 세션별 품질 등급 일관성 |
|
|
197
|
+
| **등급 분포** | S/A/B/C 세션 비율 | S·A ≥ 80% | 전체 세션의 품질 편차 |
|
|
198
|
+
| **스펙 유무 비교** | 스펙 있는 세션 vs 없는 세션 성과 차이 | — | 컨텍스트 효과의 일관성 |
|
|
199
|
+
|
|
200
|
+
**측정 방법**: 신규 사용자가 최소한의 안내만으로 첫 시도에서 작업을 완료할 수 있는지 평가합니다.
|
|
127
201
|
|
|
128
202
|
```
|
|
129
|
-
|
|
203
|
+
🏆 S급 (90+): Elite — 최적화된 워크플로우, 일관된 고품질
|
|
204
|
+
⭐ A급 (80+): Good — 우수한 효율성, 안정적 결과
|
|
205
|
+
✅ B급 (60+): Average — 개선 여지 있음, 세션 간 편차 존재
|
|
206
|
+
⚠️ C급 (40+): Below Average — 최적화 필요, 일관성 부족
|
|
130
207
|
```
|
|
131
208
|
|
|
132
|
-
`.claude/` 컨텍스트 파일 읽기 후 오류율을 측정하여 스펙 문서의 실효성을 평가합니다.
|
|
133
|
-
|
|
134
209
|
## 🔧 API Endpoints
|
|
135
210
|
|
|
136
|
-
| Endpoint | Description |
|
|
137
|
-
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
|
|
|
141
|
-
|
|
|
142
|
-
|
|
|
143
|
-
|
|
|
144
|
-
|
|
|
211
|
+
| Endpoint | Method | Description |
|
|
212
|
+
|----------|--------|-------------|
|
|
213
|
+
| `/api/analytics` | GET | 전체 요약 통계 |
|
|
214
|
+
| `/api/sessions` | GET | 세션 목록 (SEI + Grade 포함) |
|
|
215
|
+
| `/api/sessions/:id` | GET | 세션 상세 (메시지, 토큰, 파일) |
|
|
216
|
+
| `/api/projects` | GET | 프로젝트 목록 |
|
|
217
|
+
| `/api/config` | GET | 현재 설정 + 자동 탐색 결과 |
|
|
218
|
+
| `/api/config` | POST | 프로젝트 경로 설정 저장 |
|
|
219
|
+
| `/api/health` | GET | 서버 상태 확인 |
|
|
220
|
+
| `/api/refresh` | POST | 데이터 새로고침 |
|
|
145
221
|
|
|
146
222
|
## 📁 Project Structure
|
|
147
223
|
|
|
148
224
|
```
|
|
149
225
|
claude-cli-analytics/
|
|
150
|
-
├── src/
|
|
226
|
+
├── src/ # React Frontend
|
|
151
227
|
│ ├── pages/
|
|
152
|
-
│ │ ├── Dashboard.tsx
|
|
153
|
-
│ │
|
|
154
|
-
│
|
|
155
|
-
│
|
|
228
|
+
│ │ ├── Dashboard.tsx # 메인 대시보드
|
|
229
|
+
│ │ ├── SessionDetail.tsx # 세션 상세 페이지
|
|
230
|
+
│ │ └── Setup.tsx # 초기 설정 페이지
|
|
231
|
+
│ ├── components/
|
|
232
|
+
│ │ ├── InfoTooltip.tsx # 정보 툴팁
|
|
233
|
+
│ │ └── badges/
|
|
234
|
+
│ │ ├── GradeBadge.tsx # 등급 배지
|
|
235
|
+
│ │ └── DangerBadge.tsx # 위험도 배지
|
|
236
|
+
│ ├── types/
|
|
237
|
+
│ │ └── index.ts # 프론트엔드 타입 정의
|
|
238
|
+
│ ├── utils/
|
|
239
|
+
│ │ ├── constants.ts # 도구 아이콘 등 상수
|
|
240
|
+
│ │ └── format.ts # 포맷 유틸리티
|
|
241
|
+
│ ├── App.tsx # 라우팅
|
|
242
|
+
│ └── index.css # Tailwind CSS
|
|
156
243
|
├── server/
|
|
157
|
-
│ ├── index.ts
|
|
158
|
-
│ ├── config.ts
|
|
159
|
-
│ ├── analyzer.ts
|
|
160
|
-
│ ├── parser.ts
|
|
161
|
-
│ └── types.ts
|
|
244
|
+
│ ├── index.ts # Express API 서버
|
|
245
|
+
│ ├── config.ts # 설정 + 자동 탐색
|
|
246
|
+
│ ├── analyzer.ts # 세션 분석 로직
|
|
247
|
+
│ ├── parser.ts # JSONL 파서
|
|
248
|
+
│ └── types.ts # 서버 타입 정의
|
|
162
249
|
├── bin/
|
|
163
|
-
│
|
|
250
|
+
│ ├── cli.cjs # CLI 진입점 (--port, --path, --help)
|
|
251
|
+
│ └── sanity.mjs # 설치 검증 스크립트
|
|
164
252
|
├── dist/
|
|
165
|
-
│ ├── client/
|
|
166
|
-
│ └── server/
|
|
253
|
+
│ ├── client/ # 빌드된 프론트엔드
|
|
254
|
+
│ └── server/ # 빌드된 백엔드
|
|
167
255
|
├── package.json
|
|
168
|
-
├── tsconfig.server.json
|
|
256
|
+
├── tsconfig.server.json # 서버 빌드 설정
|
|
169
257
|
└── vite.config.ts
|
|
170
258
|
```
|
|
171
259
|
|
package/bin/cli.cjs
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// ── Claude CLI Analytics — CLI Entry Point (CJS) ──
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const { spawn, execSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
const PID_DIR = path.join(os.homedir(), '.claude-analytics');
|
|
11
|
+
const PID_FILE = path.join(PID_DIR, 'server.pid');
|
|
12
|
+
const LOG_FILE = path.join(PID_DIR, 'server.log');
|
|
13
|
+
const SERVER_SCRIPT = path.resolve(__dirname, '..', 'dist', 'server', 'index.js');
|
|
14
|
+
|
|
15
|
+
const args = process.argv.slice(2);
|
|
16
|
+
const command = args.find(a => !a.startsWith('-'));
|
|
17
|
+
|
|
18
|
+
// ── Help ──
|
|
19
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
20
|
+
console.log(`
|
|
21
|
+
Claude CLI Analytics Dashboard
|
|
22
|
+
|
|
23
|
+
Usage: claude-cli-analytics [command] [options]
|
|
24
|
+
|
|
25
|
+
Commands:
|
|
26
|
+
(default) Start dashboard (background)
|
|
27
|
+
exit, stop Stop the running dashboard
|
|
28
|
+
status Check if dashboard is running
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
--port <number> Server port (default: 3001)
|
|
32
|
+
--path <dir> Claude projects directory
|
|
33
|
+
--foreground, -f Run in foreground (Ctrl+C to stop)
|
|
34
|
+
--help, -h Show this help
|
|
35
|
+
|
|
36
|
+
Examples:
|
|
37
|
+
claude-cli-analytics # background start
|
|
38
|
+
claude-cli-analytics exit # stop
|
|
39
|
+
claude-cli-analytics -f # foreground
|
|
40
|
+
claude-cli-analytics --port 8080 # custom port
|
|
41
|
+
`);
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ── Helpers ──
|
|
46
|
+
function readPid() {
|
|
47
|
+
try {
|
|
48
|
+
if (fs.existsSync(PID_FILE)) {
|
|
49
|
+
return parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim(), 10);
|
|
50
|
+
}
|
|
51
|
+
} catch { /* */ }
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isRunning(pid) {
|
|
56
|
+
try { process.kill(pid, 0); return true; } catch { return false; }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getPort() {
|
|
60
|
+
const i = args.indexOf('--port');
|
|
61
|
+
return (i !== -1 && args[i + 1]) || process.env.PORT || '3001';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function cleanPid() {
|
|
65
|
+
try { fs.unlinkSync(PID_FILE); } catch { /* */ }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ── exit / stop ──
|
|
69
|
+
if (command === 'exit' || command === 'stop') {
|
|
70
|
+
const pid = readPid();
|
|
71
|
+
if (pid && isRunning(pid)) {
|
|
72
|
+
try {
|
|
73
|
+
process.kill(pid, 'SIGTERM');
|
|
74
|
+
cleanPid();
|
|
75
|
+
console.log(` ✅ Dashboard stopped (PID: ${pid})`);
|
|
76
|
+
} catch (e) {
|
|
77
|
+
console.error(` ❌ Failed to stop PID ${pid}: ${e.message}`);
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
cleanPid();
|
|
81
|
+
console.log(' ⚠️ Dashboard is not running');
|
|
82
|
+
}
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ── status ──
|
|
87
|
+
if (command === 'status') {
|
|
88
|
+
const pid = readPid();
|
|
89
|
+
if (pid && isRunning(pid)) {
|
|
90
|
+
console.log(` 🟢 Running (PID: ${pid}) → http://localhost:${getPort()}`);
|
|
91
|
+
} else {
|
|
92
|
+
cleanPid();
|
|
93
|
+
console.log(' ⚪ Dashboard is not running');
|
|
94
|
+
}
|
|
95
|
+
process.exit(0);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ── Start ──
|
|
99
|
+
try {
|
|
100
|
+
const existingPid = readPid();
|
|
101
|
+
if (existingPid && isRunning(existingPid)) {
|
|
102
|
+
console.log(` ⚠️ Already running (PID: ${existingPid}) → http://localhost:${getPort()}`);
|
|
103
|
+
console.log(` Run 'claude-cli-analytics exit' to stop`);
|
|
104
|
+
process.exit(0);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Parse env
|
|
108
|
+
const env = { ...process.env };
|
|
109
|
+
const portIdx = args.indexOf('--port');
|
|
110
|
+
if (portIdx !== -1 && args[portIdx + 1]) env.PORT = args[portIdx + 1];
|
|
111
|
+
const pathIdx = args.indexOf('--path');
|
|
112
|
+
if (pathIdx !== -1 && args[pathIdx + 1]) env.CLAUDE_PROJECTS_DIR = args[pathIdx + 1];
|
|
113
|
+
|
|
114
|
+
const foreground = args.includes('--foreground') || args.includes('-f');
|
|
115
|
+
|
|
116
|
+
if (foreground) {
|
|
117
|
+
// Foreground: import directly (CJS can require() the script, but default export handling might differ)
|
|
118
|
+
// Since `dist/server/index.js` is ESM (due to type: module in package.json), we might need `import()`
|
|
119
|
+
// However, we are in CJS now. Dynamic import works in CJS.
|
|
120
|
+
Object.assign(process.env, env);
|
|
121
|
+
(async () => {
|
|
122
|
+
try {
|
|
123
|
+
await import('../dist/server/index.js');
|
|
124
|
+
} catch (e) {
|
|
125
|
+
console.error('[CLI CRASH]', e);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
})();
|
|
129
|
+
} else {
|
|
130
|
+
// Background
|
|
131
|
+
if (!fs.existsSync(PID_DIR)) fs.mkdirSync(PID_DIR, { recursive: true });
|
|
132
|
+
|
|
133
|
+
// Use append mode for log
|
|
134
|
+
const logFd = fs.openSync(LOG_FILE, 'a');
|
|
135
|
+
const port = env.PORT || '3001';
|
|
136
|
+
|
|
137
|
+
const child = spawn(process.execPath, [SERVER_SCRIPT], {
|
|
138
|
+
detached: true,
|
|
139
|
+
stdio: ['ignore', logFd, logFd],
|
|
140
|
+
env,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const pid = child.pid;
|
|
144
|
+
if (!pid) throw new Error("Failed to spawn process");
|
|
145
|
+
|
|
146
|
+
fs.writeFileSync(PID_FILE, String(pid));
|
|
147
|
+
child.unref();
|
|
148
|
+
|
|
149
|
+
console.log(`
|
|
150
|
+
🔍 Claude Analytics Dashboard
|
|
151
|
+
🌐 http://localhost:${port}
|
|
152
|
+
📋 PID: ${pid}
|
|
153
|
+
|
|
154
|
+
Stop: claude-cli-analytics exit
|
|
155
|
+
Status: claude-cli-analytics status`);
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
const cmd = process.platform === 'darwin' ? 'open'
|
|
159
|
+
: process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
160
|
+
execSync(`${cmd} http://localhost:${port}`, { stdio: 'ignore' });
|
|
161
|
+
} catch { /* */ }
|
|
162
|
+
|
|
163
|
+
process.exit(0);
|
|
164
|
+
}
|
|
165
|
+
} catch (err) {
|
|
166
|
+
console.error('[CLI CRASH]', err);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
package/bin/sanity.mjs
ADDED