quackstack 1.0.24 → 1.0.25
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 +165 -105
- package/dist/commands/ingest.js +5 -3
- package/dist/lib/git-history.js +9 -7
- package/dist/repl.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,23 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
QuackStack is an interactive CLI tool that indexes your codebase using local AI embeddings and lets you ask questions about it conversationally. Perfect for understanding unfamiliar code, onboarding to new projects, or giving your AI coding assistant persistent context.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
Check out the QuackStack Live demo [here](https://courageous-spaniel.clueso.site/share/4f5e6395-8ad8-4d18-8e81-f736a6581a25)!
|
|
9
|
-
## ✨ Features
|
|
7
|
+
[Live Demo](https://courageous-spaniel.clueso.site/share/4f5e6395-8ad8-4d18-8e81-f736a6581a25) | [Documentation](https://quackstack.siddharththakkar.xyz/docs) | [Frontend](https://github.com/woustachemax/quack-web)
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
* 🧠 **Smart code parsing** - Automatically extracts functions and classes
|
|
13
|
-
* 💬 **Interactive REPL** - Ask questions conversationally, stays open until Ctrl+C
|
|
14
|
-
* 🔒 **100% Local embeddings** - No API calls for vector generation, your code stays private
|
|
15
|
-
* 🤖 **AI-powered answers** - Uses OpenAI, Claude, Gemini, DeepSeek, or Mistral for conversational responses
|
|
16
|
-
* 🎯 **Universal AI tool support** - Auto-generate context for Cursor, Windsurf, Cline, Continue, and Aider
|
|
17
|
-
* 📦 **Local database** - Your code stays on your infrastructure
|
|
18
|
-
* 🌍 **Multi-language** - Supports JS/TS, Python, Go, Rust, Java, C/C++, C#, Ruby, PHP, Swift, Kotlin, and more
|
|
9
|
+
## Features
|
|
19
10
|
|
|
11
|
+
* **Zero-config** - Just run `quack` in any project directory
|
|
12
|
+
* **Smart code parsing** - Automatically extracts functions and classes
|
|
13
|
+
* **Interactive REPL** - Ask questions conversationally, stays open until Ctrl+C
|
|
14
|
+
* **100% Local embeddings** - No API calls for vector generation, your code stays private
|
|
15
|
+
* **AI-powered answers** - Uses OpenAI, Claude, Gemini, DeepSeek, Grok, or Mistral for conversational responses
|
|
16
|
+
* **Git history integration** - Track authorship, commit history, and code ownership
|
|
17
|
+
* **Universal AI tool support** - Auto-generate context for Cursor, Windsurf, Cline, Continue, and Aider
|
|
18
|
+
* **Local database** - Your code stays on your infrastructure
|
|
19
|
+
* **Multi-language** - Supports JS/TS, Python, Go, Rust, Java, C/C++, C#, Ruby, PHP, Swift, Kotlin, and more
|
|
20
20
|
|
|
21
|
-
##
|
|
22
|
-
Check out the Frontend Repo [here](https://github.com/woustachemax/quack-web)
|
|
23
|
-
## 📦 Installation
|
|
21
|
+
## Installation
|
|
24
22
|
|
|
25
23
|
### Global Install (Recommended)
|
|
26
24
|
|
|
@@ -39,7 +37,7 @@ pnpm install
|
|
|
39
37
|
pnpm build
|
|
40
38
|
```
|
|
41
39
|
|
|
42
|
-
##
|
|
40
|
+
## Setup
|
|
43
41
|
|
|
44
42
|
### 1. Create `.env` in your project root
|
|
45
43
|
|
|
@@ -50,7 +48,7 @@ QUACKSTACK_DATABASE_URL=postgresql://user:pass@host:port/dbname
|
|
|
50
48
|
# REQUIRED: Choose ONE AI provider for conversational answers
|
|
51
49
|
# (Embeddings are computed locally - no API calls!)
|
|
52
50
|
|
|
53
|
-
# Option 1: OpenAI
|
|
51
|
+
# Option 1: OpenAI
|
|
54
52
|
QUACKSTACK_OPENAI_KEY=sk-...
|
|
55
53
|
|
|
56
54
|
# Option 2: Anthropic Claude
|
|
@@ -59,10 +57,13 @@ QUACKSTACK_ANTHROPIC_KEY=sk-ant-...
|
|
|
59
57
|
# Option 3: Google Gemini (has free tier!)
|
|
60
58
|
QUACKSTACK_GEMINI_KEY=AIza...
|
|
61
59
|
|
|
62
|
-
# Option 4:
|
|
60
|
+
# Option 4: xAI Grok
|
|
61
|
+
QUACKSTACK_GROK_KEY=xai-...
|
|
62
|
+
|
|
63
|
+
# Option 5: DeepSeek (cheapest option)
|
|
63
64
|
QUACKSTACK_DEEPSEEK_KEY=sk-...
|
|
64
65
|
|
|
65
|
-
# Option
|
|
66
|
+
# Option 6: Mistral AI
|
|
66
67
|
QUACKSTACK_MISTRAL_KEY=...
|
|
67
68
|
```
|
|
68
69
|
|
|
@@ -73,14 +74,13 @@ npx prisma generate
|
|
|
73
74
|
npx prisma db push
|
|
74
75
|
```
|
|
75
76
|
|
|
76
|
-
##
|
|
77
|
+
## Usage
|
|
77
78
|
|
|
78
79
|
### Interactive Mode (Default)
|
|
79
80
|
|
|
80
81
|
```bash
|
|
81
82
|
quack
|
|
82
|
-
|
|
83
|
-
# Answer appears with context
|
|
83
|
+
# Ask questions about your codebase
|
|
84
84
|
# Press Ctrl+C to exit
|
|
85
85
|
```
|
|
86
86
|
|
|
@@ -95,8 +95,31 @@ quack --context
|
|
|
95
95
|
# - Cline (.clinerules)
|
|
96
96
|
# - Continue (.continue/context.md)
|
|
97
97
|
# - Aider (.aider.conf.yml)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Generate AGENTS.md Configuration
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
quack --agent
|
|
104
|
+
|
|
105
|
+
# Creates agent.md with codebase context
|
|
106
|
+
# for AI agent frameworks
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Generate README
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
quack --readme
|
|
113
|
+
|
|
114
|
+
# Auto-generates README.md from your codebase
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Generate Documentation
|
|
98
118
|
|
|
99
|
-
|
|
119
|
+
```bash
|
|
120
|
+
quack --docs
|
|
121
|
+
|
|
122
|
+
# Creates CODEBASE.md with architecture overview
|
|
100
123
|
```
|
|
101
124
|
|
|
102
125
|
### Watch Mode (Auto-update Context)
|
|
@@ -105,8 +128,21 @@ quack --context
|
|
|
105
128
|
quack --watch
|
|
106
129
|
|
|
107
130
|
# Watches for file changes
|
|
108
|
-
# Auto-regenerates
|
|
109
|
-
|
|
131
|
+
# Auto-regenerates context files
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Git History Commands
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# View contributor statistics
|
|
138
|
+
quack authors
|
|
139
|
+
|
|
140
|
+
# View recently modified files
|
|
141
|
+
quack recent
|
|
142
|
+
quack recent --days 30
|
|
143
|
+
|
|
144
|
+
# View repository information
|
|
145
|
+
quack git-info
|
|
110
146
|
```
|
|
111
147
|
|
|
112
148
|
### Force Reindex
|
|
@@ -117,17 +153,27 @@ quack --reindex
|
|
|
117
153
|
# Clears old index and re-scans entire codebase
|
|
118
154
|
```
|
|
119
155
|
|
|
120
|
-
|
|
156
|
+
### List Available AI Models
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
quack --list-models
|
|
160
|
+
|
|
161
|
+
# Shows all configured providers and available models
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Example Session
|
|
121
165
|
|
|
122
166
|
```bash
|
|
123
167
|
$ quack
|
|
124
|
-
Welcome to QuackStack!
|
|
125
|
-
|
|
126
|
-
|
|
168
|
+
Welcome to QuackStack!
|
|
169
|
+
|
|
170
|
+
Using: OpenAI - gpt-4o
|
|
171
|
+
Press Ctrl+C to exit
|
|
127
172
|
|
|
128
|
-
|
|
173
|
+
Indexing your codebase...
|
|
174
|
+
Indexing complete
|
|
129
175
|
|
|
130
|
-
|
|
176
|
+
quack > how does the search function work?
|
|
131
177
|
|
|
132
178
|
The search function uses local embeddings to convert your query into a vector,
|
|
133
179
|
compares it against stored code embeddings using cosine similarity, ranks results,
|
|
@@ -135,141 +181,153 @@ and feeds the top matches to the AI for a conversational answer.
|
|
|
135
181
|
|
|
136
182
|
Implementation is in src/commands/search.ts
|
|
137
183
|
|
|
138
|
-
|
|
184
|
+
Want more details? (y/n) > n
|
|
139
185
|
|
|
140
|
-
|
|
186
|
+
quack > who wrote the authentication system?
|
|
141
187
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const snippets = await client.codeSnippet.findMany({
|
|
145
|
-
where: { projectName },
|
|
146
|
-
});
|
|
147
|
-
// ... cosine similarity ranking ...
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
🐥 Quack! How can I help? > where are embeddings generated?
|
|
151
|
-
|
|
152
|
-
Embeddings are generated locally using the local-embeddings module.
|
|
153
|
-
No API calls are made for vector generation, keeping your code private.
|
|
154
|
-
|
|
155
|
-
💡 Want more details? (y/n) > n
|
|
188
|
+
The authentication system was primarily written by Siddharth Thakkar, with the
|
|
189
|
+
main implementation in app/api/auth/[...nextauth]/options.ts (last modified 187 days ago).
|
|
156
190
|
|
|
157
|
-
|
|
158
|
-
|
|
191
|
+
quack > ^C
|
|
192
|
+
Happy coding!
|
|
159
193
|
```
|
|
160
194
|
|
|
161
|
-
##
|
|
195
|
+
## How It Works
|
|
162
196
|
|
|
163
197
|
1. **Scanning** - Finds all code files (ignoring `node_modules`, `.git`, etc.)
|
|
164
|
-
2. **Parsing** - Uses AST parsing to extract functions/classes
|
|
198
|
+
2. **Parsing** - Uses AST parsing to extract functions/classes
|
|
165
199
|
3. **Chunking** - Breaks code into logical chunks
|
|
166
|
-
4. **Local Embedding** - Generates vector embeddings
|
|
167
|
-
5. **
|
|
168
|
-
6. **
|
|
169
|
-
|
|
170
|
-
## 🎯 Use Cases
|
|
171
|
-
|
|
172
|
-
- **Context switching** - Quickly understand projects you haven't touched in months
|
|
173
|
-
- **Onboarding** - New team members can ask questions instead of reading docs
|
|
174
|
-
- **Code archaeology** - Find implementations without grepping
|
|
175
|
-
- **AI coding assistants** - Give Cursor/Windsurf/Cline/Continue/Aider persistent codebase context
|
|
176
|
-
- **Documentation** - Auto-generate explanations of how things work
|
|
177
|
-
- **Privacy-focused** - All embeddings generated locally, no code sent to embedding APIs
|
|
200
|
+
4. **Local Embedding** - Generates vector embeddings locally (no API calls)
|
|
201
|
+
5. **Git Enrichment** - Extracts commit history, authorship, and ownership data
|
|
202
|
+
6. **Storage** - Saves to your PostgreSQL database
|
|
203
|
+
7. **Search** - Semantic search using cosine similarity + AI-powered conversational answers
|
|
178
204
|
|
|
179
|
-
##
|
|
205
|
+
## Commands Reference
|
|
180
206
|
|
|
181
207
|
| Command | Description |
|
|
182
208
|
|---------|-------------|
|
|
183
|
-
| `quack` | Start interactive REPL
|
|
184
|
-
| `quack --context` | Generate context files for
|
|
209
|
+
| `quack` | Start interactive REPL |
|
|
210
|
+
| `quack --context` | Generate context files for all AI coding tools |
|
|
211
|
+
| `quack --agent` | Generate AGENTS.md configuration |
|
|
212
|
+
| `quack --readme` | Generate README.md from codebase |
|
|
213
|
+
| `quack --docs` | Generate CODEBASE.md documentation |
|
|
185
214
|
| `quack --watch` | Watch mode - auto-update context on file changes |
|
|
186
215
|
| `quack --reindex` | Force reindex the entire codebase |
|
|
187
|
-
| `quack --
|
|
216
|
+
| `quack --list-models` | Show available AI providers and models |
|
|
217
|
+
| `quack authors` | View contributor statistics |
|
|
218
|
+
| `quack recent [--days N]` | View recently modified files |
|
|
219
|
+
| `quack git-info` | View repository information |
|
|
188
220
|
|
|
189
|
-
##
|
|
221
|
+
## Supported AI Providers
|
|
190
222
|
|
|
191
223
|
| Provider | Used For | Cost | Privacy | Setup |
|
|
192
224
|
|----------|----------|------|---------|-------|
|
|
193
|
-
| **Local** | Embeddings | FREE |
|
|
225
|
+
| **Local** | Embeddings | FREE | 100% Private | Built-in |
|
|
194
226
|
| OpenAI | Chat answers | $$ | Query only | [Get key](https://platform.openai.com/api-keys) |
|
|
195
227
|
| Anthropic | Chat answers | $$$ | Query only | [Get key](https://console.anthropic.com/) |
|
|
196
228
|
| Gemini | Chat answers | FREE | Query only | [Get key](https://aistudio.google.com/app/apikey) |
|
|
229
|
+
| xAI Grok | Chat answers | $$ | Query only | [Get key](https://x.ai/) |
|
|
197
230
|
| DeepSeek | Chat answers | $ | Query only | [Get key](https://platform.deepseek.com/) |
|
|
198
231
|
| Mistral | Chat answers | $$ | Query only | [Get key](https://console.mistral.ai/) |
|
|
199
232
|
|
|
200
|
-
**Privacy Note:** QuackStack generates embeddings
|
|
233
|
+
**Privacy Note:** QuackStack generates embeddings locally on your machine. Only your natural language queries and retrieved code context are sent to the AI provider for generating conversational answers. Your entire codebase is never sent to any API.
|
|
201
234
|
|
|
202
|
-
##
|
|
235
|
+
## Database Schema
|
|
203
236
|
|
|
204
237
|
```prisma
|
|
205
238
|
model codeSnippet {
|
|
206
|
-
id
|
|
207
|
-
content
|
|
208
|
-
embedding
|
|
209
|
-
filePath
|
|
210
|
-
projectName
|
|
211
|
-
language
|
|
212
|
-
functionName
|
|
213
|
-
lineStart
|
|
214
|
-
lineEnd
|
|
215
|
-
|
|
216
|
-
|
|
239
|
+
id Int @id @default(autoincrement())
|
|
240
|
+
content String
|
|
241
|
+
embedding Json
|
|
242
|
+
filePath String
|
|
243
|
+
projectName String
|
|
244
|
+
language String?
|
|
245
|
+
functionName String?
|
|
246
|
+
lineStart Int?
|
|
247
|
+
lineEnd Int?
|
|
248
|
+
|
|
249
|
+
lastCommitHash String?
|
|
250
|
+
lastCommitAuthor String?
|
|
251
|
+
lastCommitEmail String?
|
|
252
|
+
lastCommitDate DateTime?
|
|
253
|
+
lastCommitMessage String?
|
|
254
|
+
totalCommits Int? @default(0)
|
|
255
|
+
primaryAuthor String?
|
|
256
|
+
primaryAuthorEmail String?
|
|
257
|
+
fileOwnerCommits Int? @default(0)
|
|
258
|
+
|
|
259
|
+
createdAt DateTime @default(now())
|
|
260
|
+
updatedAt DateTime @updatedAt
|
|
217
261
|
|
|
218
262
|
@@index([projectName])
|
|
263
|
+
@@index([lastCommitDate])
|
|
264
|
+
@@index([primaryAuthor])
|
|
219
265
|
}
|
|
220
|
-
```
|
|
221
266
|
|
|
222
|
-
|
|
267
|
+
model gitAuthor {
|
|
268
|
+
id Int @id @default(autoincrement())
|
|
269
|
+
projectName String
|
|
270
|
+
author String
|
|
271
|
+
email String
|
|
272
|
+
totalCommits Int @default(0)
|
|
273
|
+
linesAdded Int @default(0)
|
|
274
|
+
linesRemoved Int @default(0)
|
|
275
|
+
recentActivity DateTime?
|
|
276
|
+
filesOwned String[]
|
|
277
|
+
|
|
278
|
+
createdAt DateTime @default(now())
|
|
279
|
+
updatedAt DateTime @updatedAt
|
|
280
|
+
|
|
281
|
+
@@unique([projectName, email])
|
|
282
|
+
@@index([projectName])
|
|
283
|
+
@@index([recentActivity])
|
|
284
|
+
}
|
|
285
|
+
```
|
|
223
286
|
|
|
224
|
-
##
|
|
287
|
+
## Supported Languages
|
|
225
288
|
|
|
226
289
|
JavaScript, TypeScript, Python, Go, Rust, Java, C, C++, C#, Ruby, PHP, Swift, Kotlin, Scala, R, Vue, Svelte
|
|
227
290
|
|
|
228
|
-
##
|
|
291
|
+
## Use Cases
|
|
292
|
+
|
|
293
|
+
- **Context switching** - Quickly understand projects you haven't touched in months
|
|
294
|
+
- **Onboarding** - New team members can ask questions instead of reading docs
|
|
295
|
+
- **Code archaeology** - Find implementations without grepping
|
|
296
|
+
- **Code ownership** - Identify who wrote and maintains specific parts of the codebase
|
|
297
|
+
- **AI coding assistants** - Give Cursor/Windsurf/Cline/Continue/Aider persistent codebase context
|
|
298
|
+
- **Documentation** - Auto-generate explanations of how things work
|
|
299
|
+
- **Privacy-focused** - All embeddings generated locally, no code sent to embedding APIs
|
|
300
|
+
|
|
301
|
+
## Development
|
|
229
302
|
|
|
230
303
|
```bash
|
|
231
304
|
git clone https://github.com/woustachemax/quackstack.git
|
|
232
305
|
cd quackstack
|
|
233
306
|
pnpm install
|
|
234
|
-
|
|
235
307
|
pnpm build
|
|
236
308
|
|
|
237
309
|
# Run locally
|
|
238
310
|
node dist/cli.cjs
|
|
239
|
-
node dist/cli.cjs --context
|
|
240
|
-
node dist/cli.cjs --watch
|
|
241
311
|
```
|
|
242
312
|
|
|
243
|
-
##
|
|
244
|
-
|
|
245
|
-
- [x] Local embeddings (no API calls!)
|
|
246
|
-
- [x] Support for all major AI coding assistants
|
|
247
|
-
- [ ] VS Code extension
|
|
248
|
-
- [ ] Official Cursor plugin
|
|
249
|
-
- [ ] Export Q&A sessions as markdown docs
|
|
250
|
-
- [ ] Add filtering by file type, date range, author
|
|
251
|
-
- [ ] Support for code diffs and change tracking
|
|
252
|
-
- [ ] Team collaboration features
|
|
253
|
-
- [ ] Self-hosted web UI
|
|
254
|
-
|
|
255
|
-
## 🤝 Contributing
|
|
313
|
+
## Contributing
|
|
256
314
|
|
|
257
315
|
Contributions welcome! Feel free to:
|
|
258
316
|
- Report bugs via [GitHub Issues](https://github.com/woustachemax/quackstack/issues)
|
|
259
317
|
- Submit feature requests
|
|
260
318
|
- Open pull requests
|
|
261
319
|
|
|
262
|
-
##
|
|
320
|
+
## License
|
|
263
321
|
|
|
264
322
|
MIT
|
|
265
323
|
|
|
266
|
-
##
|
|
324
|
+
## Pro Tips
|
|
267
325
|
|
|
268
326
|
**Privacy First**: Embeddings are generated locally - your code never leaves your machine during indexing.
|
|
269
327
|
|
|
270
328
|
**Gemini Free Tier**: Start with Google Gemini for chat responses - it's free and works great for most use cases.
|
|
271
329
|
|
|
272
|
-
**Universal Context**: Run `quack --context` once to generate context files for
|
|
330
|
+
**Universal Context**: Run `quack --context` once to generate context files for all major AI coding tools at once.
|
|
273
331
|
|
|
274
332
|
**Background Watcher**: Run `quack --watch &` in the background to keep context always fresh across all your AI tools.
|
|
275
333
|
|
|
@@ -277,4 +335,6 @@ MIT
|
|
|
277
335
|
|
|
278
336
|
**Large Codebases**: First index might take a few minutes. After that, only changed files are re-indexed.
|
|
279
337
|
|
|
280
|
-
**
|
|
338
|
+
**Git Integration**: QuackStack automatically enriches your codebase with git history - no setup required. Track authorship, view recent changes, and understand code ownership.
|
|
339
|
+
|
|
340
|
+
**No Vendor Lock-in**: Unlike other tools, QuackStack works with Cursor, Windsurf, Cline, Continue, and Aider - choose your favorite!
|
package/dist/commands/ingest.js
CHANGED
|
@@ -4,8 +4,9 @@ import { scanDir } from "../lib/scanner.js";
|
|
|
4
4
|
import { chunkCode } from "../lib/chunker.js";
|
|
5
5
|
import { saveToDB, saveAuthorToDB } from "../lib/database.js";
|
|
6
6
|
import { localEmbeddings } from "../lib/local-embeddings.js";
|
|
7
|
-
import { gitHistory } from "../lib/git-history.js";
|
|
7
|
+
import { gitHistory, initGitHistory } from "../lib/git-history.js";
|
|
8
8
|
export async function ingest(rootDir, projectName, silent = false, includeGitHistory = true) {
|
|
9
|
+
initGitHistory(rootDir);
|
|
9
10
|
if (!silent)
|
|
10
11
|
console.log("Starting ingestion...");
|
|
11
12
|
const files = await scanDir(rootDir);
|
|
@@ -86,8 +87,9 @@ export async function ingest(rootDir, projectName, silent = false, includeGitHis
|
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
if (isGitRepo && includeGitHistory && !silent) {
|
|
89
|
-
console.log("Computing author statistics...");
|
|
90
|
+
console.log("📈 Computing author statistics...");
|
|
90
91
|
const authorStats = gitHistory.getAuthorStats();
|
|
92
|
+
console.log(`Found ${authorStats.length} authors`);
|
|
91
93
|
for (const stats of authorStats) {
|
|
92
94
|
const ownedFiles = [];
|
|
93
95
|
fileGitData.forEach((history, filePath) => {
|
|
@@ -107,7 +109,7 @@ export async function ingest(rootDir, projectName, silent = false, includeGitHis
|
|
|
107
109
|
});
|
|
108
110
|
}
|
|
109
111
|
if (!silent)
|
|
110
|
-
console.log(
|
|
112
|
+
console.log(`✅ Stored stats for ${authorStats.length} contributors`);
|
|
111
113
|
}
|
|
112
114
|
if (!silent) {
|
|
113
115
|
console.log(`Done! Processed ${processedCount} chunks from ${files.length} files.`);
|
package/dist/lib/git-history.js
CHANGED
|
@@ -29,7 +29,6 @@ export class GitHistory {
|
|
|
29
29
|
return null;
|
|
30
30
|
try {
|
|
31
31
|
const relativePath = path.relative(this.repoRoot, filePath);
|
|
32
|
-
// Get commit history for file
|
|
33
32
|
const logOutput = execSync(`git log --follow --format="%H|%an|%ae|%aI|%s" -n ${limit} -- "${relativePath}"`, {
|
|
34
33
|
cwd: this.repoRoot,
|
|
35
34
|
encoding: "utf-8",
|
|
@@ -48,7 +47,6 @@ export class GitHistory {
|
|
|
48
47
|
filesChanged: [relativePath],
|
|
49
48
|
};
|
|
50
49
|
});
|
|
51
|
-
// Get author statistics
|
|
52
50
|
const authorMap = new Map();
|
|
53
51
|
commits.forEach(commit => {
|
|
54
52
|
const key = commit.email;
|
|
@@ -162,7 +160,6 @@ export class GitHistory {
|
|
|
162
160
|
if (!this.isGitRepo)
|
|
163
161
|
return [];
|
|
164
162
|
try {
|
|
165
|
-
// Get basic author stats
|
|
166
163
|
const authorOutput = execSync(`git shortlog -sne --all`, {
|
|
167
164
|
cwd: this.repoRoot,
|
|
168
165
|
encoding: "utf-8",
|
|
@@ -184,7 +181,6 @@ export class GitHistory {
|
|
|
184
181
|
});
|
|
185
182
|
}
|
|
186
183
|
});
|
|
187
|
-
// Get recent activity for each author
|
|
188
184
|
authorMap.forEach((stats, email) => {
|
|
189
185
|
try {
|
|
190
186
|
const lastCommit = execSync(`git log --author="${email}" -1 --format="%aI"`, {
|
|
@@ -202,13 +198,16 @@ export class GitHistory {
|
|
|
202
198
|
stdio: ["pipe", "pipe", "pipe"],
|
|
203
199
|
}).trim();
|
|
204
200
|
lineStats.split("\n").forEach(line => {
|
|
205
|
-
|
|
201
|
+
if (!line.trim())
|
|
202
|
+
return;
|
|
203
|
+
const parts = line.split("\t");
|
|
204
|
+
const added = parseInt(parts[0]) || 0;
|
|
205
|
+
const removed = parseInt(parts[1]) || 0;
|
|
206
206
|
stats.linesAdded += added;
|
|
207
207
|
stats.linesRemoved += removed;
|
|
208
208
|
});
|
|
209
209
|
}
|
|
210
210
|
catch {
|
|
211
|
-
// Ignore errors for individual authors
|
|
212
211
|
}
|
|
213
212
|
});
|
|
214
213
|
return Array.from(authorMap.values())
|
|
@@ -309,4 +308,7 @@ export class GitHistory {
|
|
|
309
308
|
return this.repoRoot;
|
|
310
309
|
}
|
|
311
310
|
}
|
|
312
|
-
export
|
|
311
|
+
export let gitHistory = new GitHistory();
|
|
312
|
+
export function initGitHistory(projectPath) {
|
|
313
|
+
gitHistory = new GitHistory(projectPath);
|
|
314
|
+
}
|
package/dist/repl.js
CHANGED
|
@@ -76,7 +76,7 @@ export async function startREPL(forceReindex = false, provider, model) {
|
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
78
|
console.log(chalk.gray("🔍 Indexing your codebase..."));
|
|
79
|
-
await ingest(process.cwd(), PROJECT_NAME,
|
|
79
|
+
await ingest(process.cwd(), PROJECT_NAME, false);
|
|
80
80
|
console.log(chalk.green("Indexing complete\n"));
|
|
81
81
|
}
|
|
82
82
|
const rl = readline.createInterface({
|