-
Notifications
You must be signed in to change notification settings - Fork 0
explain command
Generates architectural summaries for each module in your codebase using the Groq API. This is the only feature that requires an external API — everything else runs entirely offline.
codebase-vis explain
- Clusters file nodes by Louvain community into batches of ~8 files
- Builds a structured payload for each batch — file names, classes, functions, docstrings, dependency edges
- Sends batches to the Groq API with concurrency and rate limiting
-
Collects summaries and writes
semantic-summary.md -
Updates
graph.jsonwithsemantic_summaryattributes on each node
The explain command uses your own Groq API key. This design choice:
- No usage costs passed to users — you pay Groq directly
- Privacy by default — your codebase never touches our servers
- Model flexibility — use any model Groq supports (Llama, Mixtral, GPT-OSS, etc.)
- No vendor lock-in — Groq's API is OpenAI-compatible, swap providers by changing the endpoint
# On first run, you'll be prompted to enter your key
codebase-vis explain
# Or set via environment variable
GROQ_API_KEY=gsk_xxx codebase-vis explainCredentials are stored in ~/.codebase-vis/config.json.
The token bucket ensures requests never exceed the configured rate, even under retries:
class TokenBucket {
constructor(rpm) {
this.#maxTokens = rpm
this.#tokens = rpm
this.#refillInterval = 60000 / rpm // e.g., 2000ms for 30 RPM
}
async acquire() {
while (true) {
this.#refill()
if (this.#tokens > 0) {
this.#tokens--
return
}
await new Promise(r => setTimeout(r, this.#refillInterval))
}
}
}Tokens refill continuously at 60000 / RPM ms per token. acquire() blocks until a token is available.
Multiple LLM requests run in parallel, but the shared token bucket keeps the total rate under control:
async function mapConcurrent(items, concurrency, fn, onProgress) {
// Spawn N worker async functions
// Each pulls from shared index (idx++) for race-free item assignment
// Results collected in original order via index-based placement
// onProgress called after each completion
}| Flag | Default | Max | Description |
|---|---|---|---|
--rpm |
30 | — | API requests per minute (shared across all workers) |
--concurrency |
2 | 5 | Parallel LLM requests in flight |
At defaults (2 workers, 30 RPM): each worker averages 15 requests per minute, or one every 4 seconds.
async function callLLMWithRetry(apiKey, model, payload, bucket) {
for (let attempt = 0; attempt < 5; attempt++) {
await bucket.acquire() // ← token consumed per attempt
try {
return await callLLM(apiKey, model, payload)
} catch (err) {
if (err.status !== 429 || attempt === 4) throw err
const delay = Math.min(1000 * Math.pow(2, attempt), 32000)
await new Promise(r => setTimeout(r, delay))
}
}
}| Attempt | Backoff |
|---|---|
| 0 | 1 second |
| 1 | 2 seconds |
| 2 | 4 seconds |
| 3 | 8 seconds |
| 4 | 16 seconds (then give up) |
Only HTTP 429 (Rate Limited) triggers a retry. Non-429 errors (auth failures, timeouts) throw immediately. Each retry attempt consumes a token from the bucket.
Failed clusters are saved to codebase-out/.explain-retry.json:
[
{
"index": 3,
"batch": ["src/file1.js", "src/file2.js"],
"payload": { /* extracted AST data */ },
"error": "Rate limited",
"totalClusters": 12
}
]| Flag | Default | Description |
|---|---|---|
--model |
llama-3.1-8b-instant |
Groq model to use |
--concurrency |
2 | Parallel requests (max 5) |
--rpm |
30 | Requests per minute |
--retry |
false |
Retry only previously failed clusters |
--reset |
false |
Reset saved API credentials |
codebase-vis explain # Default settings
codebase-vis explain --model mixtral-8x7b-32768 # Custom model
codebase-vis explain --concurrency 4 --rpm 60 # Higher throughput
codebase-vis explain --retry # Retry failed clusters
codebase-vis explain --reset # Reset API key
GROQ_API_KEY=gsk_xxx codebase-vis explain # One-time key-
semantic-summary.md— readable architectural report -
graph.jsonupdated — each node gets asemantic_summaryfield - On success,
.explain-retry.jsonis deleted