@code-insights/cli 1.0.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/LICENSE +21 -0
- package/README.md +287 -0
- package/dist/commands/connect.d.ts +8 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +33 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +176 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/insights.d.ts +13 -0
- package/dist/commands/insights.d.ts.map +1 -0
- package/dist/commands/insights.js +87 -0
- package/dist/commands/insights.js.map +1 -0
- package/dist/commands/install-hook.d.ts +9 -0
- package/dist/commands/install-hook.d.ts.map +1 -0
- package/dist/commands/install-hook.js +98 -0
- package/dist/commands/install-hook.js.map +1 -0
- package/dist/commands/link.d.ts +8 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +39 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/reset.d.ts +3 -0
- package/dist/commands/reset.d.ts.map +1 -0
- package/dist/commands/reset.js +95 -0
- package/dist/commands/reset.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +107 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +13 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +205 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/firebase/client.d.ts +35 -0
- package/dist/firebase/client.d.ts.map +1 -0
- package/dist/firebase/client.js +317 -0
- package/dist/firebase/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/insights.d.ts +7 -0
- package/dist/parser/insights.d.ts.map +1 -0
- package/dist/parser/insights.js +271 -0
- package/dist/parser/insights.js.map +1 -0
- package/dist/parser/jsonl.d.ts +6 -0
- package/dist/parser/jsonl.d.ts.map +1 -0
- package/dist/parser/jsonl.js +305 -0
- package/dist/parser/jsonl.js.map +1 -0
- package/dist/parser/titles.d.ts +14 -0
- package/dist/parser/titles.d.ts.map +1 -0
- package/dist/parser/titles.js +258 -0
- package/dist/parser/titles.js.map +1 -0
- package/dist/types.d.ts +216 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/config.d.ts +46 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +106 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/device.d.ts +32 -0
- package/dist/utils/device.d.ts.map +1 -0
- package/dist/utils/device.js +132 -0
- package/dist/utils/device.js.map +1 -0
- package/dist/utils/firebase-json.d.ts +87 -0
- package/dist/utils/firebase-json.d.ts.map +1 -0
- package/dist/utils/firebase-json.js +206 -0
- package/dist/utils/firebase-json.js.map +1 -0
- package/dist/utils/pricing.d.ts +29 -0
- package/dist/utils/pricing.d.ts.map +1 -0
- package/dist/utils/pricing.js +66 -0
- package/dist/utils/pricing.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Srikanth Rao M
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Code Insights CLI
|
|
2
|
+
|
|
3
|
+
Command-line tool that parses Claude Code session history and syncs it to your own Firebase Firestore.
|
|
4
|
+
|
|
5
|
+
Full documentation: [docs.code-insights.app](https://docs.code-insights.app)
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- **Node.js** 18 or later
|
|
10
|
+
- **pnpm** >= 9 (`npm install -g pnpm` if needed)
|
|
11
|
+
- A **Firebase project** with Firestore enabled (see [Quick Start](../README.md#quick-start))
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# From the repo root
|
|
17
|
+
cd cli
|
|
18
|
+
pnpm install
|
|
19
|
+
pnpm build
|
|
20
|
+
npm link # Makes `code-insights` available globally
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
After linking, verify it works:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
code-insights --version
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Commands
|
|
30
|
+
|
|
31
|
+
### `code-insights init`
|
|
32
|
+
|
|
33
|
+
Configure Code Insights with your Firebase credentials.
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Quick setup ā import directly from JSON files (recommended)
|
|
37
|
+
code-insights init \
|
|
38
|
+
--from-json ~/Downloads/serviceAccountKey.json \
|
|
39
|
+
--web-config ~/Downloads/firebase-web-config.json
|
|
40
|
+
|
|
41
|
+
# Interactive setup ā prompts for each value
|
|
42
|
+
code-insights init
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Flags:**
|
|
46
|
+
- `--from-json <path>` ā Path to the Firebase service account JSON (downloaded from Firebase Console > Project Settings > Service Accounts)
|
|
47
|
+
- `--web-config <path>` ā Path to the Firebase web SDK config JSON (saved from Firebase Console > Project Settings > General > Your Apps)
|
|
48
|
+
|
|
49
|
+
You can use one flag, both, or neither. Any values not provided via flags will be collected interactively.
|
|
50
|
+
|
|
51
|
+
Configuration is stored in `~/.code-insights/config.json`. Web config is stored separately in `~/.code-insights/web-config.json`.
|
|
52
|
+
|
|
53
|
+
### `code-insights connect`
|
|
54
|
+
|
|
55
|
+
Generate a URL to connect the web dashboard to your Firebase.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
code-insights connect
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Flags:**
|
|
62
|
+
- `--no-qr` ā Skip QR code output (prints URL only)
|
|
63
|
+
|
|
64
|
+
The URL includes your Firebase web config base64-encoded as a query parameter. Open it in a browser to connect the dashboard to your Firestore ā no manual configuration needed.
|
|
65
|
+
|
|
66
|
+
### `code-insights sync`
|
|
67
|
+
|
|
68
|
+
Sync Claude Code sessions to Firestore.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Sync new/modified sessions
|
|
72
|
+
code-insights sync
|
|
73
|
+
|
|
74
|
+
# Force re-sync all sessions
|
|
75
|
+
code-insights sync --force
|
|
76
|
+
|
|
77
|
+
# Preview what would be synced
|
|
78
|
+
code-insights sync --dry-run
|
|
79
|
+
|
|
80
|
+
# Sync specific project only
|
|
81
|
+
code-insights sync --project "my-project"
|
|
82
|
+
|
|
83
|
+
# Quiet mode (for hooks)
|
|
84
|
+
code-insights sync --quiet
|
|
85
|
+
|
|
86
|
+
# Regenerate titles for all sessions
|
|
87
|
+
code-insights sync --regenerate-titles
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### `code-insights status`
|
|
91
|
+
|
|
92
|
+
Show sync status and statistics.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
code-insights status
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Displays:
|
|
99
|
+
- Configuration status
|
|
100
|
+
- Total sessions synced
|
|
101
|
+
- Projects tracked
|
|
102
|
+
- Last sync time
|
|
103
|
+
|
|
104
|
+
### `code-insights reset`
|
|
105
|
+
|
|
106
|
+
Delete all data from Firestore and reset local sync state.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Interactive (asks for confirmation)
|
|
110
|
+
code-insights reset
|
|
111
|
+
|
|
112
|
+
# Skip confirmation
|
|
113
|
+
code-insights reset --confirm
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### `code-insights install-hook`
|
|
117
|
+
|
|
118
|
+
Install a Claude Code hook for automatic sync after each session.
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
code-insights install-hook
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### `code-insights uninstall-hook`
|
|
125
|
+
|
|
126
|
+
Remove the automatic sync hook.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
code-insights uninstall-hook
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## How It Works
|
|
133
|
+
|
|
134
|
+
### Session Parsing
|
|
135
|
+
|
|
136
|
+
The CLI reads JSONL files from `~/.claude/projects/` which contain:
|
|
137
|
+
- User and assistant messages
|
|
138
|
+
- Tool calls (Edit, Write, Bash, etc.)
|
|
139
|
+
- Timestamps and metadata
|
|
140
|
+
|
|
141
|
+
Each session is parsed to extract:
|
|
142
|
+
- Project name and path
|
|
143
|
+
- Start/end times and duration
|
|
144
|
+
- Message counts
|
|
145
|
+
- Tool call statistics
|
|
146
|
+
- Git branch (if available)
|
|
147
|
+
- Claude version
|
|
148
|
+
- Token usage, estimated costs, and model information (when available)
|
|
149
|
+
|
|
150
|
+
### Incremental Sync
|
|
151
|
+
|
|
152
|
+
Sync state is tracked in `~/.code-insights/sync-state.json`:
|
|
153
|
+
- File modification times are recorded
|
|
154
|
+
- Only new or modified files are processed
|
|
155
|
+
- Use `--force` to bypass and re-sync everything
|
|
156
|
+
|
|
157
|
+
### Multi-Device Support
|
|
158
|
+
|
|
159
|
+
Project IDs are generated from git remote URLs when available:
|
|
160
|
+
- Same repo on different machines ā same project ID
|
|
161
|
+
- Non-git projects fall back to path-based hash
|
|
162
|
+
- Each session records device metadata (hostname, platform)
|
|
163
|
+
|
|
164
|
+
### Title Generation
|
|
165
|
+
|
|
166
|
+
Sessions are automatically titled based on:
|
|
167
|
+
1. Claude's own title (if present in session)
|
|
168
|
+
2. First user message (cleaned up)
|
|
169
|
+
3. Session character detection (deep focus, bug hunt, etc.)
|
|
170
|
+
4. Fallback to timestamp
|
|
171
|
+
|
|
172
|
+
## Project Structure
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
cli/
|
|
176
|
+
āāā src/
|
|
177
|
+
ā āāā commands/
|
|
178
|
+
ā ā āāā init.ts # Interactive Firebase configuration
|
|
179
|
+
ā ā āāā sync.ts # Main sync logic
|
|
180
|
+
ā ā āāā connect.ts # Generate dashboard connection URL
|
|
181
|
+
ā ā āāā status.ts # Status display
|
|
182
|
+
ā ā āāā reset.ts # Clear all data
|
|
183
|
+
ā ā āāā install-hook.ts # Hook management
|
|
184
|
+
ā āāā firebase/
|
|
185
|
+
ā ā āāā client.ts # Firestore operations
|
|
186
|
+
ā āāā parser/
|
|
187
|
+
ā ā āāā jsonl.ts # JSONL file parsing
|
|
188
|
+
ā ā āāā titles.ts # Title generation
|
|
189
|
+
ā āāā utils/
|
|
190
|
+
ā ā āāā config.ts # Config management
|
|
191
|
+
ā ā āāā device.ts # Device identification
|
|
192
|
+
ā ā āāā firebase-json.ts # Firebase JSON validation & URL generation
|
|
193
|
+
ā āāā types.ts # TypeScript types
|
|
194
|
+
ā āāā index.ts # CLI entry point
|
|
195
|
+
āāā dist/ # Compiled output
|
|
196
|
+
āāā package.json
|
|
197
|
+
āāā tsconfig.json
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Development
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
pnpm dev # Watch mode ā recompiles on save
|
|
204
|
+
pnpm build # One-time compile
|
|
205
|
+
pnpm lint # Run ESLint
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The CLI is written in TypeScript with ES Modules and compiled to `dist/`. After `npm link`, changes rebuild automatically in watch mode.
|
|
209
|
+
|
|
210
|
+
See [CONTRIBUTING.md](../CONTRIBUTING.md) for the full development workflow, code style, and PR guidelines.
|
|
211
|
+
|
|
212
|
+
## Firestore Collections
|
|
213
|
+
|
|
214
|
+
The CLI writes to these collections:
|
|
215
|
+
|
|
216
|
+
### `projects`
|
|
217
|
+
```typescript
|
|
218
|
+
{
|
|
219
|
+
id: string; // Hash of git remote URL or path
|
|
220
|
+
name: string; // Project directory name
|
|
221
|
+
path: string; // Full path on syncing device
|
|
222
|
+
gitRemoteUrl: string | null;
|
|
223
|
+
projectIdSource: 'git-remote' | 'path-hash';
|
|
224
|
+
sessionCount: number;
|
|
225
|
+
lastActivity: Timestamp;
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### `sessions`
|
|
230
|
+
```typescript
|
|
231
|
+
{
|
|
232
|
+
id: string; // From JSONL filename
|
|
233
|
+
projectId: string;
|
|
234
|
+
projectName: string;
|
|
235
|
+
projectPath: string;
|
|
236
|
+
gitRemoteUrl: string | null;
|
|
237
|
+
summary: string | null;
|
|
238
|
+
generatedTitle: string | null;
|
|
239
|
+
titleSource: 'claude' | 'user_message' | 'insight' | 'character' | 'fallback' | null;
|
|
240
|
+
sessionCharacter: 'deep_focus' | 'bug_hunt' | 'feature_build' | 'exploration' | 'refactor' | 'learning' | 'quick_task' | null;
|
|
241
|
+
startedAt: Timestamp;
|
|
242
|
+
endedAt: Timestamp;
|
|
243
|
+
messageCount: number;
|
|
244
|
+
userMessageCount: number;
|
|
245
|
+
assistantMessageCount: number;
|
|
246
|
+
toolCallCount: number;
|
|
247
|
+
gitBranch: string | null;
|
|
248
|
+
claudeVersion: string | null;
|
|
249
|
+
deviceId: string;
|
|
250
|
+
deviceHostname: string;
|
|
251
|
+
devicePlatform: string;
|
|
252
|
+
syncedAt: Timestamp; // Server timestamp
|
|
253
|
+
// Usage stats (present when token data is available)
|
|
254
|
+
totalInputTokens?: number;
|
|
255
|
+
totalOutputTokens?: number;
|
|
256
|
+
cacheCreationTokens?: number;
|
|
257
|
+
cacheReadTokens?: number;
|
|
258
|
+
estimatedCostUsd?: number;
|
|
259
|
+
modelsUsed?: string[];
|
|
260
|
+
primaryModel?: string;
|
|
261
|
+
usageSource?: 'jsonl';
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### `messages`
|
|
266
|
+
```typescript
|
|
267
|
+
{
|
|
268
|
+
id: string;
|
|
269
|
+
sessionId: string;
|
|
270
|
+
type: 'user' | 'assistant' | 'system';
|
|
271
|
+
content: string; // Max 10,000 chars (truncated)
|
|
272
|
+
thinking: string | null; // Extracted thinking content (max 5,000 chars)
|
|
273
|
+
toolCalls: Array<{ id: string; name: string; input: string }>; // Input max 1,000 chars
|
|
274
|
+
toolResults: Array<{ toolUseId: string; output: string }>; // Output max 2,000 chars
|
|
275
|
+
timestamp: Timestamp;
|
|
276
|
+
parentId: string | null;
|
|
277
|
+
// Per-message usage (assistant messages only)
|
|
278
|
+
usage?: {
|
|
279
|
+
inputTokens: number;
|
|
280
|
+
outputTokens: number;
|
|
281
|
+
cacheCreationTokens: number;
|
|
282
|
+
cacheReadTokens: number;
|
|
283
|
+
model: string;
|
|
284
|
+
estimatedCostUsd: number;
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B3E"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { isConfigured, loadWebConfig, hasWebConfig } from '../utils/config.js';
|
|
3
|
+
import { generateDashboardUrl, validateWebConfig } from '../utils/firebase-json.js';
|
|
4
|
+
/**
|
|
5
|
+
* Generate and display the dashboard connection URL
|
|
6
|
+
*/
|
|
7
|
+
export async function connectCommand(options) {
|
|
8
|
+
if (!isConfigured()) {
|
|
9
|
+
console.log(chalk.red('\nā Code Insights is not configured.'));
|
|
10
|
+
console.log(chalk.gray('Run "code-insights init" first.\n'));
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (!hasWebConfig()) {
|
|
14
|
+
console.log(chalk.yellow('\nā No web config found.'));
|
|
15
|
+
console.log(chalk.gray('\nRe-run "code-insights init" to add your web config.'));
|
|
16
|
+
console.log(chalk.gray('Or visit the dashboard and configure Firebase manually:'));
|
|
17
|
+
console.log(chalk.white(' https://code-insights.app\n'));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const webConfigData = loadWebConfig();
|
|
21
|
+
if (!webConfigData || !validateWebConfig(webConfigData)) {
|
|
22
|
+
console.log(chalk.red('\nā Invalid web config stored.'));
|
|
23
|
+
console.log(chalk.gray('Run "code-insights init" to reconfigure.\n'));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const webConfig = webConfigData;
|
|
27
|
+
const url = generateDashboardUrl(webConfig);
|
|
28
|
+
console.log(chalk.cyan('\nš Dashboard Connection URL\n'));
|
|
29
|
+
console.log(chalk.white('Open this URL to connect the dashboard to your Firebase:'));
|
|
30
|
+
console.log(chalk.bold.underline(url));
|
|
31
|
+
console.log('');
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAOpF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAuB;IAC1D,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAC7D,OAAO;IACT,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC,CAAC;QACjF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC,CAAC;QACnF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC,CAAC;QAC1D,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAG,aAAa,EAAE,CAAC;IACtC,IAAI,CAAC,aAAa,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,EAAE,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC,CAAC;QACtE,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,aAAkC,CAAC;IACrD,MAAM,GAAG,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAE5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC,CAAC;IACrF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA4LrE"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { saveConfig, saveWebConfig, getConfigDir, isConfigured } from '../utils/config.js';
|
|
4
|
+
import { readJsonFileWithError, readFirebaseConfigFile, validateServiceAccountJson, validateWebConfig, extractServiceAccountConfig, looksLikeWebConfig, looksLikeServiceAccount, } from '../utils/firebase-json.js';
|
|
5
|
+
const DEFAULT_DASHBOARD_URL = 'https://code-insights.app';
|
|
6
|
+
/**
|
|
7
|
+
* Initialize Code Insights configuration
|
|
8
|
+
*/
|
|
9
|
+
export async function initCommand(options) {
|
|
10
|
+
console.log(chalk.cyan('\nš§ Code Insights Setup\n'));
|
|
11
|
+
if (isConfigured()) {
|
|
12
|
+
const { overwrite } = await inquirer.prompt([
|
|
13
|
+
{
|
|
14
|
+
type: 'confirm',
|
|
15
|
+
name: 'overwrite',
|
|
16
|
+
message: 'Configuration already exists. Overwrite?',
|
|
17
|
+
default: false,
|
|
18
|
+
},
|
|
19
|
+
]);
|
|
20
|
+
if (!overwrite) {
|
|
21
|
+
console.log(chalk.yellow('Setup cancelled.'));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// --- Step 1: Service Account ---
|
|
26
|
+
let firebaseConfig;
|
|
27
|
+
if (options.fromJson) {
|
|
28
|
+
// Read from JSON file
|
|
29
|
+
const result = readJsonFileWithError(options.fromJson);
|
|
30
|
+
if (!result.success) {
|
|
31
|
+
console.log(chalk.red(`\nā ${result.message}`));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
// Cross-type detection: did they pass a web config by mistake?
|
|
35
|
+
if (looksLikeWebConfig(result.data) && !looksLikeServiceAccount(result.data)) {
|
|
36
|
+
console.log(chalk.red('\nā This looks like a web config file, not a service account.'));
|
|
37
|
+
console.log(chalk.gray('Use --web-config for the web SDK config file.'));
|
|
38
|
+
console.log(chalk.gray('Use --from-json for the service account key (downloaded from Firebase).\n'));
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
if (!validateServiceAccountJson(result.data)) {
|
|
42
|
+
console.log(chalk.red('\nā Invalid service account JSON.'));
|
|
43
|
+
console.log(chalk.gray('Expected a file with: type, project_id, private_key, client_email'));
|
|
44
|
+
console.log(chalk.gray('Download it from: Firebase Console > Project Settings > Service Accounts\n'));
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
firebaseConfig = extractServiceAccountConfig(result.data);
|
|
48
|
+
console.log(chalk.green(`ā Service account loaded from ${options.fromJson}`));
|
|
49
|
+
console.log(chalk.gray(` Project: ${firebaseConfig.projectId}`));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Interactive prompts
|
|
53
|
+
console.log(chalk.bold('š Step 1: Service Account\n'));
|
|
54
|
+
console.log(chalk.gray('You\'ll need your Firebase service account key JSON file.'));
|
|
55
|
+
console.log(chalk.gray('Download from: Firebase Console > Project Settings > Service Accounts\n'));
|
|
56
|
+
console.log(chalk.gray(chalk.bold('Tip:') + ' Use --from-json <path> to skip these prompts:\n'));
|
|
57
|
+
console.log(chalk.gray(' code-insights init --from-json ~/Downloads/serviceAccountKey.json\n'));
|
|
58
|
+
const answers = await inquirer.prompt([
|
|
59
|
+
{
|
|
60
|
+
type: 'input',
|
|
61
|
+
name: 'projectId',
|
|
62
|
+
message: 'Firebase Project ID:',
|
|
63
|
+
validate: (input) => input.length > 0 || 'Project ID is required',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
type: 'input',
|
|
67
|
+
name: 'clientEmail',
|
|
68
|
+
message: 'Service Account Email (client_email from JSON):',
|
|
69
|
+
validate: (input) => input.includes('@') || 'Please enter a valid service account email',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: 'password',
|
|
73
|
+
name: 'privateKey',
|
|
74
|
+
message: 'Private Key (private_key from JSON, including BEGIN/END):',
|
|
75
|
+
validate: (input) => input.includes('PRIVATE KEY') || 'Please paste the complete private key',
|
|
76
|
+
},
|
|
77
|
+
]);
|
|
78
|
+
firebaseConfig = {
|
|
79
|
+
projectId: answers.projectId,
|
|
80
|
+
clientEmail: answers.clientEmail,
|
|
81
|
+
privateKey: answers.privateKey,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// --- Step 2: Web Config ---
|
|
85
|
+
let webConfig;
|
|
86
|
+
if (options.webConfig) {
|
|
87
|
+
// Read from file ā supports both JSON and Firebase JS snippet format
|
|
88
|
+
const result = readFirebaseConfigFile(options.webConfig);
|
|
89
|
+
if (!result.success) {
|
|
90
|
+
console.log(chalk.red(`\nā ${result.message}`));
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
// Cross-type detection: did they pass a service account by mistake?
|
|
94
|
+
if (looksLikeServiceAccount(result.data) && !looksLikeWebConfig(result.data)) {
|
|
95
|
+
console.log(chalk.red('\nā This looks like a service account file, not a web config.'));
|
|
96
|
+
console.log(chalk.gray('Use --from-json for the service account key.'));
|
|
97
|
+
console.log(chalk.gray('Use --web-config for the web SDK config.\n'));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
if (!validateWebConfig(result.data)) {
|
|
101
|
+
console.log(chalk.red('\nā Invalid web config.'));
|
|
102
|
+
console.log(chalk.gray('Expected: apiKey, authDomain, projectId, storageBucket, messagingSenderId, appId'));
|
|
103
|
+
console.log(chalk.gray('Get it from: Firebase Console > Project Settings > General > Your Apps'));
|
|
104
|
+
console.log(chalk.gray('You can paste the JavaScript snippet directly into a file ā no need to convert to JSON.\n'));
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
webConfig = result.data;
|
|
108
|
+
console.log(chalk.green(`ā Web config loaded from ${options.webConfig}`));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// Interactive prompts
|
|
112
|
+
console.log(chalk.bold('\nš Step 2: Web Dashboard Config\n'));
|
|
113
|
+
console.log(chalk.gray('Get these from: Firebase Console > Project Settings > General > Your Apps\n'));
|
|
114
|
+
console.log(chalk.gray(chalk.bold('Tip:') + ' Save the config as a JSON file and use --web-config <path> to skip these prompts.\n'));
|
|
115
|
+
const answers = await inquirer.prompt([
|
|
116
|
+
{
|
|
117
|
+
type: 'input',
|
|
118
|
+
name: 'apiKey',
|
|
119
|
+
message: 'API Key (apiKey):',
|
|
120
|
+
validate: (input) => input.length > 0 || 'API Key is required',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
type: 'input',
|
|
124
|
+
name: 'authDomain',
|
|
125
|
+
message: 'Auth Domain (authDomain):',
|
|
126
|
+
default: `${firebaseConfig.projectId}.firebaseapp.com`,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'input',
|
|
130
|
+
name: 'storageBucket',
|
|
131
|
+
message: 'Storage Bucket (storageBucket):',
|
|
132
|
+
default: `${firebaseConfig.projectId}.appspot.com`,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: 'input',
|
|
136
|
+
name: 'messagingSenderId',
|
|
137
|
+
message: 'Messaging Sender ID (messagingSenderId):',
|
|
138
|
+
validate: (input) => input.length > 0 || 'Messaging Sender ID is required',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: 'input',
|
|
142
|
+
name: 'appId',
|
|
143
|
+
message: 'App ID (appId):',
|
|
144
|
+
validate: (input) => input.length > 0 || 'App ID is required',
|
|
145
|
+
},
|
|
146
|
+
]);
|
|
147
|
+
webConfig = {
|
|
148
|
+
apiKey: answers.apiKey,
|
|
149
|
+
authDomain: answers.authDomain,
|
|
150
|
+
projectId: firebaseConfig.projectId,
|
|
151
|
+
storageBucket: answers.storageBucket,
|
|
152
|
+
messagingSenderId: answers.messagingSenderId,
|
|
153
|
+
appId: answers.appId,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// --- Save config ---
|
|
157
|
+
const config = {
|
|
158
|
+
firebase: firebaseConfig,
|
|
159
|
+
webConfig,
|
|
160
|
+
sync: {
|
|
161
|
+
claudeDir: '~/.claude/projects',
|
|
162
|
+
excludeProjects: [],
|
|
163
|
+
},
|
|
164
|
+
dashboardUrl: DEFAULT_DASHBOARD_URL,
|
|
165
|
+
};
|
|
166
|
+
saveConfig(config);
|
|
167
|
+
saveWebConfig(webConfig);
|
|
168
|
+
console.log(chalk.green('\nā
Configuration saved!'));
|
|
169
|
+
console.log(chalk.gray(`Config location: ${getConfigDir()}/config.json`));
|
|
170
|
+
console.log(chalk.cyan('\nš Setup complete! Next steps:\n'));
|
|
171
|
+
console.log(chalk.white(' 1. Sync your sessions:'));
|
|
172
|
+
console.log(chalk.gray(' code-insights sync\n'));
|
|
173
|
+
console.log(chalk.white(' 2. Connect the dashboard:'));
|
|
174
|
+
console.log(chalk.gray(' code-insights connect\n'));
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InsightType } from '../types.js';
|
|
2
|
+
interface InsightsOptions {
|
|
3
|
+
type?: InsightType;
|
|
4
|
+
project?: string;
|
|
5
|
+
today?: boolean;
|
|
6
|
+
limit?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Display recent insights from Firestore
|
|
10
|
+
*/
|
|
11
|
+
export declare function insightsCommand(options?: InsightsOptions): Promise<void>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=insights.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insights.d.ts","sourceRoot":"","sources":["../../src/commands/insights.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAW,WAAW,EAAE,MAAM,aAAa,CAAC;AAExD,UAAU,eAAe;IACvB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8ElF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { format } from 'date-fns';
|
|
3
|
+
import { loadConfig, isConfigured } from '../utils/config.js';
|
|
4
|
+
import { initializeFirebase, getRecentInsights } from '../firebase/client.js';
|
|
5
|
+
/**
|
|
6
|
+
* Display recent insights from Firestore
|
|
7
|
+
*/
|
|
8
|
+
export async function insightsCommand(options = {}) {
|
|
9
|
+
// Check if configured
|
|
10
|
+
if (!isConfigured()) {
|
|
11
|
+
console.log(chalk.red('Not configured. Run `claudeinsight init` first.'));
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
// Load config and initialize Firebase
|
|
15
|
+
const config = loadConfig();
|
|
16
|
+
if (!config) {
|
|
17
|
+
console.log(chalk.red('Configuration error.'));
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
initializeFirebase(config);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.log(chalk.red('Failed to connect to Firebase.'));
|
|
25
|
+
console.error(error instanceof Error ? error.message : 'Unknown error');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const limit = options.limit || 20;
|
|
29
|
+
// Fetch insights
|
|
30
|
+
const insights = await getRecentInsights(limit, {
|
|
31
|
+
type: options.type,
|
|
32
|
+
project: options.project,
|
|
33
|
+
todayOnly: options.today,
|
|
34
|
+
});
|
|
35
|
+
if (insights.length === 0) {
|
|
36
|
+
console.log(chalk.yellow('\nNo insights found.'));
|
|
37
|
+
if (options.today) {
|
|
38
|
+
console.log(chalk.gray('Try running without --today to see older insights.'));
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
console.log(chalk.cyan(`\nš Recent Insights (${insights.length})\n`));
|
|
43
|
+
// Group by type
|
|
44
|
+
const summaries = insights.filter((i) => i.type === 'summary');
|
|
45
|
+
const decisions = insights.filter((i) => i.type === 'decision');
|
|
46
|
+
const learnings = insights.filter((i) => i.type === 'learning');
|
|
47
|
+
const techniques = insights.filter((i) => i.type === 'technique');
|
|
48
|
+
if (summaries.length > 0) {
|
|
49
|
+
console.log(chalk.bold.magenta('š Summaries'));
|
|
50
|
+
for (const insight of summaries) {
|
|
51
|
+
printInsight(insight);
|
|
52
|
+
}
|
|
53
|
+
console.log();
|
|
54
|
+
}
|
|
55
|
+
if (decisions.length > 0) {
|
|
56
|
+
console.log(chalk.bold.blue('šÆ Decisions'));
|
|
57
|
+
for (const insight of decisions) {
|
|
58
|
+
printInsight(insight);
|
|
59
|
+
}
|
|
60
|
+
console.log();
|
|
61
|
+
}
|
|
62
|
+
if (learnings.length > 0) {
|
|
63
|
+
console.log(chalk.bold.green('š” Learnings'));
|
|
64
|
+
for (const insight of learnings) {
|
|
65
|
+
printInsight(insight);
|
|
66
|
+
}
|
|
67
|
+
console.log();
|
|
68
|
+
}
|
|
69
|
+
if (techniques.length > 0) {
|
|
70
|
+
console.log(chalk.bold.yellow('š§ Techniques'));
|
|
71
|
+
for (const insight of techniques) {
|
|
72
|
+
printInsight(insight);
|
|
73
|
+
}
|
|
74
|
+
console.log();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function printInsight(insight) {
|
|
78
|
+
const date = insight.timestamp
|
|
79
|
+
? format(new Date(insight.timestamp), 'MMM d')
|
|
80
|
+
: 'Unknown';
|
|
81
|
+
console.log(chalk.white(` ⢠${insight.title}`));
|
|
82
|
+
console.log(chalk.gray(` ${insight.projectName} | ${date}`));
|
|
83
|
+
if (insight.content && insight.content.length < 100) {
|
|
84
|
+
console.log(chalk.gray(` ${insight.content}`));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=insights.js.map
|