repoatlas-cli 0.2.0__tar.gz
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.
- repoatlas_cli-0.2.0/LICENSE +21 -0
- repoatlas_cli-0.2.0/PKG-INFO +297 -0
- repoatlas_cli-0.2.0/README.md +258 -0
- repoatlas_cli-0.2.0/api/__init__.py +0 -0
- repoatlas_cli-0.2.0/api/retriever.py +80 -0
- repoatlas_cli-0.2.0/app/__init__.py +0 -0
- repoatlas_cli-0.2.0/app/config.py +93 -0
- repoatlas_cli-0.2.0/app/providers.py +271 -0
- repoatlas_cli-0.2.0/app/rag.py +108 -0
- repoatlas_cli-0.2.0/cli/__init__.py +6 -0
- repoatlas_cli-0.2.0/cli/main.py +421 -0
- repoatlas_cli-0.2.0/db/__init__.py +1 -0
- repoatlas_cli-0.2.0/db/chroma.py +79 -0
- repoatlas_cli-0.2.0/indexer/__init__.py +0 -0
- repoatlas_cli-0.2.0/indexer/chunker.py +158 -0
- repoatlas_cli-0.2.0/indexer/embedder.py +57 -0
- repoatlas_cli-0.2.0/indexer/ingestion.py +186 -0
- repoatlas_cli-0.2.0/pyproject.toml +75 -0
- repoatlas_cli-0.2.0/repoatlas_cli.egg-info/PKG-INFO +297 -0
- repoatlas_cli-0.2.0/repoatlas_cli.egg-info/SOURCES.txt +25 -0
- repoatlas_cli-0.2.0/repoatlas_cli.egg-info/dependency_links.txt +1 -0
- repoatlas_cli-0.2.0/repoatlas_cli.egg-info/entry_points.txt +3 -0
- repoatlas_cli-0.2.0/repoatlas_cli.egg-info/requires.txt +25 -0
- repoatlas_cli-0.2.0/repoatlas_cli.egg-info/top_level.txt +5 -0
- repoatlas_cli-0.2.0/setup.cfg +4 -0
- repoatlas_cli-0.2.0/tests/test_chunker.py +226 -0
- repoatlas_cli-0.2.0/tests/test_retriever.py +110 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nishant
|
|
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.
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: repoatlas-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Ask natural-language questions about any code repository — powered by local LLMs and ChromaDB. Zero server setup.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Repository, https://github.com/yourusername/repolens
|
|
7
|
+
Keywords: rag,llm,code-search,ollama,chromadb,cli
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: typer>=0.12
|
|
19
|
+
Requires-Dist: rich>=13
|
|
20
|
+
Requires-Dist: httpx>=0.27
|
|
21
|
+
Requires-Dist: chromadb>=0.6
|
|
22
|
+
Requires-Dist: pyyaml>=6
|
|
23
|
+
Provides-Extra: openai
|
|
24
|
+
Requires-Dist: openai>=1.30; extra == "openai"
|
|
25
|
+
Provides-Extra: anthropic
|
|
26
|
+
Requires-Dist: anthropic>=0.28; extra == "anthropic"
|
|
27
|
+
Provides-Extra: groq
|
|
28
|
+
Requires-Dist: groq>=0.9; extra == "groq"
|
|
29
|
+
Provides-Extra: all
|
|
30
|
+
Requires-Dist: openai>=1.30; extra == "all"
|
|
31
|
+
Requires-Dist: anthropic>=0.28; extra == "all"
|
|
32
|
+
Requires-Dist: groq>=0.9; extra == "all"
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
36
|
+
Requires-Dist: ruff; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# RepoAtlas
|
|
41
|
+
|
|
42
|
+
> Ask natural-language questions about any code repository — powered by local LLMs and ChromaDB. Runs fully offline. Zero server setup.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
repoatlas init
|
|
46
|
+
repoatlas index /path/to/myproject
|
|
47
|
+
repoatlas ask "how does authentication work here?"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## What it is
|
|
53
|
+
|
|
54
|
+
RepoAtlas is a CLI tool that turns any code repository into a searchable knowledge base. Point it at a repo, index it once, then ask questions in plain English and get answers grounded in the actual code — not generic guesses.
|
|
55
|
+
|
|
56
|
+
It combines **AST-based chunking**, **vector embeddings**, and a **local LLM** into a standard RAG (Retrieval-Augmented Generation) pipeline — running entirely on your own machine, with no data leaving your network.
|
|
57
|
+
|
|
58
|
+
**No Postgres. No server. No connection strings.** ChromaDB stores everything in a local directory (`~/.repoatlas/chroma_db`) that just works.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Why local-first?
|
|
63
|
+
|
|
64
|
+
- **Privacy / compliance** — banking, defense, legal, and other regulated environments forbid sending proprietary code to cloud AI APIs. RepoAtlas works with zero network access by default.
|
|
65
|
+
- **Air-gapped environments** — cloud-based agents don't work here at all.
|
|
66
|
+
- **No API costs** — the default stack (Ollama + `nomic-embed-text` + `qwen2.5-coder:3b`) is entirely free.
|
|
67
|
+
- Cloud providers (OpenAI, Anthropic, Groq) are available as opt-in backends for users with weaker hardware.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## How it works
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
Repo files
|
|
75
|
+
│
|
|
76
|
+
▼
|
|
77
|
+
[Chunker] AST-based for .py (top-level functions & classes)
|
|
78
|
+
Line-window (50 lines, 10-line overlap) for all other files
|
|
79
|
+
│
|
|
80
|
+
▼
|
|
81
|
+
[Embedder] nomic-embed-text via Ollama → 768-dim vectors
|
|
82
|
+
│
|
|
83
|
+
▼
|
|
84
|
+
[ChromaDB] Local embedded vector store — no server, just a directory
|
|
85
|
+
│
|
|
86
|
+
▼ (at query time)
|
|
87
|
+
[Retriever] Embeds the question, cosine-similarity search → top-k chunks
|
|
88
|
+
│
|
|
89
|
+
▼
|
|
90
|
+
[LLM] Chunks + question → prompt → grounded answer
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Requirements
|
|
96
|
+
|
|
97
|
+
- Python 3.11+
|
|
98
|
+
- [Ollama](https://ollama.com/) (for local mode)
|
|
99
|
+
|
|
100
|
+
That's it. ChromaDB is installed automatically as a Python dependency — no server setup needed.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Installation
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
pip install repoatlas
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
For cloud provider support (optional):
|
|
111
|
+
```bash
|
|
112
|
+
pip install "repoatlas[openai]"
|
|
113
|
+
pip install "repoatlas[anthropic]"
|
|
114
|
+
pip install "repoatlas[groq]"
|
|
115
|
+
pip install "repoatlas[all]" # all cloud providers
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Quickstart
|
|
121
|
+
|
|
122
|
+
### 1. Run setup (first time only)
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
repoatlas init
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
This will:
|
|
129
|
+
- Check that Ollama is installed and running
|
|
130
|
+
- Pull the required models (`nomic-embed-text`, `qwen2.5-coder:3b`)
|
|
131
|
+
- Confirm the ChromaDB storage path
|
|
132
|
+
- Write `~/.repoatlas/config.yaml` so you never have to configure again
|
|
133
|
+
|
|
134
|
+
### 2. Index a repository
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
repoatlas index /path/to/myproject
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 3. Ask questions
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
repoatlas ask "how does authentication work?"
|
|
144
|
+
repoatlas ask "where is the database connection handled?"
|
|
145
|
+
repoatlas ask "how do I add a new API endpoint?"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Usage
|
|
151
|
+
|
|
152
|
+
### `repoatlas init`
|
|
153
|
+
|
|
154
|
+
Interactive first-time setup. Checks Ollama, pulls models, writes config.
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
repoatlas init [--chroma-path PATH] [--chat-model MODEL] [--embed-model MODEL]
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `repoatlas index`
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
repoatlas index <repo_path> [OPTIONS]
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
| Option | Default | Description |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `--reset` | off | Wipe entire ChromaDB collection before indexing |
|
|
169
|
+
| `--chroma-path` | `~/.repoatlas/chroma_db` | ChromaDB storage directory |
|
|
170
|
+
| `--embed-model` | `nomic-embed-text` | Ollama embedding model |
|
|
171
|
+
|
|
172
|
+
### `repoatlas ask`
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
repoatlas ask <question> [OPTIONS]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
| Option | Default | Description |
|
|
179
|
+
|---|---|---|
|
|
180
|
+
| `--repo` | (all repos) | Restrict retrieval to a specific repo path |
|
|
181
|
+
| `--top-k` | 5 | Number of chunks to retrieve (1–20) |
|
|
182
|
+
| `--provider` | `ollama` | `ollama` \| `openai` \| `anthropic` \| `groq` |
|
|
183
|
+
| `--model` | provider default | Chat model override |
|
|
184
|
+
| `--chroma-path` | `~/.repoatlas/chroma_db` | ChromaDB storage directory |
|
|
185
|
+
| `--no-sources` | off | Hide source citations |
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Using cloud providers
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# OpenAI
|
|
193
|
+
export OPENAI_API_KEY=sk-...
|
|
194
|
+
repoatlas ask "explain the auth flow" --provider openai --model gpt-4o
|
|
195
|
+
|
|
196
|
+
# Anthropic
|
|
197
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
198
|
+
repoatlas ask "explain the auth flow" --provider anthropic
|
|
199
|
+
|
|
200
|
+
# Groq (fast inference, free tier available)
|
|
201
|
+
export GROQ_API_KEY=gsk_...
|
|
202
|
+
repoatlas ask "explain the auth flow" --provider groq
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Configuration
|
|
208
|
+
|
|
209
|
+
### Environment variables
|
|
210
|
+
|
|
211
|
+
| Variable | Description |
|
|
212
|
+
|---|---|
|
|
213
|
+
| `REPOATLAS_CHROMA_PATH` | ChromaDB storage path (default: `~/.repoatlas/chroma_db`) |
|
|
214
|
+
| `REPOATLAS_PROVIDER` | Default LLM provider (`ollama`) |
|
|
215
|
+
| `REPOATLAS_MODEL` | Default chat model |
|
|
216
|
+
| `REPOATLAS_EMBED_MODEL` | Embedding model (default: `nomic-embed-text`) |
|
|
217
|
+
| `OLLAMA_BASE_URL` | Ollama server URL (default: `http://localhost:11434`) |
|
|
218
|
+
| `OPENAI_API_KEY` | OpenAI API key |
|
|
219
|
+
| `ANTHROPIC_API_KEY` | Anthropic API key |
|
|
220
|
+
| `GROQ_API_KEY` | Groq API key |
|
|
221
|
+
|
|
222
|
+
### Config file (`~/.repoatlas/config.yaml`)
|
|
223
|
+
|
|
224
|
+
After running `repoatlas init`, settings are persisted here. Environment variables override the config file.
|
|
225
|
+
|
|
226
|
+
```yaml
|
|
227
|
+
chroma_path: ~/.repoatlas/chroma_db
|
|
228
|
+
provider: ollama
|
|
229
|
+
chat_model: qwen2.5-coder:3b
|
|
230
|
+
embed_model: nomic-embed-text
|
|
231
|
+
ollama_base_url: http://localhost:11434
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Multiple repositories
|
|
237
|
+
|
|
238
|
+
RepoAtlas can hold multiple repos in the same ChromaDB — use `--repo` when querying to restrict to one:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
repoatlas index /path/to/project-a
|
|
242
|
+
repoatlas index /path/to/project-b
|
|
243
|
+
|
|
244
|
+
repoatlas ask "how does auth work?" --repo /path/to/project-a
|
|
245
|
+
repoatlas ask "how does auth work?" --repo /path/to/project-b
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Project structure
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
RepoAtlas/
|
|
254
|
+
├── db/
|
|
255
|
+
│ └── chroma.py — ChromaDB client + collection helpers
|
|
256
|
+
├── indexer/
|
|
257
|
+
│ ├── chunker.py — AST chunker (Python) + line-window fallback (all files)
|
|
258
|
+
│ ├── embedder.py — Ollama /api/embeddings wrapper
|
|
259
|
+
│ └── ingestion.py — Repo walker + indexing pipeline
|
|
260
|
+
├── api/
|
|
261
|
+
│ └── retriever.py — ChromaDB cosine-similarity retrieval
|
|
262
|
+
├── app/
|
|
263
|
+
│ ├── providers.py — Pluggable LLM backends (Ollama / OpenAI / Anthropic / Groq)
|
|
264
|
+
│ └── rag.py — RAG orchestration (retrieve → prompt → generate)
|
|
265
|
+
├── cli/
|
|
266
|
+
│ └── main.py — Typer CLI (init, index, ask)
|
|
267
|
+
└── tests/
|
|
268
|
+
├── test_chunker.py — Unit tests for chunking logic
|
|
269
|
+
└── test_retriever.py — Integration tests for retrieval
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Running tests
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
# Unit tests (no Ollama required)
|
|
278
|
+
pytest tests/test_chunker.py -v
|
|
279
|
+
|
|
280
|
+
# Integration tests (requires Ollama running)
|
|
281
|
+
pytest tests/ -v
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Roadmap
|
|
287
|
+
|
|
288
|
+
- [ ] Tree-sitter chunking for JS / Go / Rust / Java
|
|
289
|
+
- [ ] `repoatlas search` — raw chunk retrieval without LLM
|
|
290
|
+
- [ ] `repoatlas watch` — incremental re-indexing on file change
|
|
291
|
+
- [ ] Web UI
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## License
|
|
296
|
+
|
|
297
|
+
MIT — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# RepoAtlas
|
|
2
|
+
|
|
3
|
+
> Ask natural-language questions about any code repository — powered by local LLMs and ChromaDB. Runs fully offline. Zero server setup.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
repoatlas init
|
|
7
|
+
repoatlas index /path/to/myproject
|
|
8
|
+
repoatlas ask "how does authentication work here?"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What it is
|
|
14
|
+
|
|
15
|
+
RepoAtlas is a CLI tool that turns any code repository into a searchable knowledge base. Point it at a repo, index it once, then ask questions in plain English and get answers grounded in the actual code — not generic guesses.
|
|
16
|
+
|
|
17
|
+
It combines **AST-based chunking**, **vector embeddings**, and a **local LLM** into a standard RAG (Retrieval-Augmented Generation) pipeline — running entirely on your own machine, with no data leaving your network.
|
|
18
|
+
|
|
19
|
+
**No Postgres. No server. No connection strings.** ChromaDB stores everything in a local directory (`~/.repoatlas/chroma_db`) that just works.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Why local-first?
|
|
24
|
+
|
|
25
|
+
- **Privacy / compliance** — banking, defense, legal, and other regulated environments forbid sending proprietary code to cloud AI APIs. RepoAtlas works with zero network access by default.
|
|
26
|
+
- **Air-gapped environments** — cloud-based agents don't work here at all.
|
|
27
|
+
- **No API costs** — the default stack (Ollama + `nomic-embed-text` + `qwen2.5-coder:3b`) is entirely free.
|
|
28
|
+
- Cloud providers (OpenAI, Anthropic, Groq) are available as opt-in backends for users with weaker hardware.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## How it works
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Repo files
|
|
36
|
+
│
|
|
37
|
+
▼
|
|
38
|
+
[Chunker] AST-based for .py (top-level functions & classes)
|
|
39
|
+
Line-window (50 lines, 10-line overlap) for all other files
|
|
40
|
+
│
|
|
41
|
+
▼
|
|
42
|
+
[Embedder] nomic-embed-text via Ollama → 768-dim vectors
|
|
43
|
+
│
|
|
44
|
+
▼
|
|
45
|
+
[ChromaDB] Local embedded vector store — no server, just a directory
|
|
46
|
+
│
|
|
47
|
+
▼ (at query time)
|
|
48
|
+
[Retriever] Embeds the question, cosine-similarity search → top-k chunks
|
|
49
|
+
│
|
|
50
|
+
▼
|
|
51
|
+
[LLM] Chunks + question → prompt → grounded answer
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Requirements
|
|
57
|
+
|
|
58
|
+
- Python 3.11+
|
|
59
|
+
- [Ollama](https://ollama.com/) (for local mode)
|
|
60
|
+
|
|
61
|
+
That's it. ChromaDB is installed automatically as a Python dependency — no server setup needed.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install repoatlas
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
For cloud provider support (optional):
|
|
72
|
+
```bash
|
|
73
|
+
pip install "repoatlas[openai]"
|
|
74
|
+
pip install "repoatlas[anthropic]"
|
|
75
|
+
pip install "repoatlas[groq]"
|
|
76
|
+
pip install "repoatlas[all]" # all cloud providers
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Quickstart
|
|
82
|
+
|
|
83
|
+
### 1. Run setup (first time only)
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
repoatlas init
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
This will:
|
|
90
|
+
- Check that Ollama is installed and running
|
|
91
|
+
- Pull the required models (`nomic-embed-text`, `qwen2.5-coder:3b`)
|
|
92
|
+
- Confirm the ChromaDB storage path
|
|
93
|
+
- Write `~/.repoatlas/config.yaml` so you never have to configure again
|
|
94
|
+
|
|
95
|
+
### 2. Index a repository
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
repoatlas index /path/to/myproject
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 3. Ask questions
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
repoatlas ask "how does authentication work?"
|
|
105
|
+
repoatlas ask "where is the database connection handled?"
|
|
106
|
+
repoatlas ask "how do I add a new API endpoint?"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Usage
|
|
112
|
+
|
|
113
|
+
### `repoatlas init`
|
|
114
|
+
|
|
115
|
+
Interactive first-time setup. Checks Ollama, pulls models, writes config.
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
repoatlas init [--chroma-path PATH] [--chat-model MODEL] [--embed-model MODEL]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### `repoatlas index`
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
repoatlas index <repo_path> [OPTIONS]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
| Option | Default | Description |
|
|
128
|
+
|---|---|---|
|
|
129
|
+
| `--reset` | off | Wipe entire ChromaDB collection before indexing |
|
|
130
|
+
| `--chroma-path` | `~/.repoatlas/chroma_db` | ChromaDB storage directory |
|
|
131
|
+
| `--embed-model` | `nomic-embed-text` | Ollama embedding model |
|
|
132
|
+
|
|
133
|
+
### `repoatlas ask`
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
repoatlas ask <question> [OPTIONS]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
| Option | Default | Description |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| `--repo` | (all repos) | Restrict retrieval to a specific repo path |
|
|
142
|
+
| `--top-k` | 5 | Number of chunks to retrieve (1–20) |
|
|
143
|
+
| `--provider` | `ollama` | `ollama` \| `openai` \| `anthropic` \| `groq` |
|
|
144
|
+
| `--model` | provider default | Chat model override |
|
|
145
|
+
| `--chroma-path` | `~/.repoatlas/chroma_db` | ChromaDB storage directory |
|
|
146
|
+
| `--no-sources` | off | Hide source citations |
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Using cloud providers
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# OpenAI
|
|
154
|
+
export OPENAI_API_KEY=sk-...
|
|
155
|
+
repoatlas ask "explain the auth flow" --provider openai --model gpt-4o
|
|
156
|
+
|
|
157
|
+
# Anthropic
|
|
158
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
159
|
+
repoatlas ask "explain the auth flow" --provider anthropic
|
|
160
|
+
|
|
161
|
+
# Groq (fast inference, free tier available)
|
|
162
|
+
export GROQ_API_KEY=gsk_...
|
|
163
|
+
repoatlas ask "explain the auth flow" --provider groq
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Configuration
|
|
169
|
+
|
|
170
|
+
### Environment variables
|
|
171
|
+
|
|
172
|
+
| Variable | Description |
|
|
173
|
+
|---|---|
|
|
174
|
+
| `REPOATLAS_CHROMA_PATH` | ChromaDB storage path (default: `~/.repoatlas/chroma_db`) |
|
|
175
|
+
| `REPOATLAS_PROVIDER` | Default LLM provider (`ollama`) |
|
|
176
|
+
| `REPOATLAS_MODEL` | Default chat model |
|
|
177
|
+
| `REPOATLAS_EMBED_MODEL` | Embedding model (default: `nomic-embed-text`) |
|
|
178
|
+
| `OLLAMA_BASE_URL` | Ollama server URL (default: `http://localhost:11434`) |
|
|
179
|
+
| `OPENAI_API_KEY` | OpenAI API key |
|
|
180
|
+
| `ANTHROPIC_API_KEY` | Anthropic API key |
|
|
181
|
+
| `GROQ_API_KEY` | Groq API key |
|
|
182
|
+
|
|
183
|
+
### Config file (`~/.repoatlas/config.yaml`)
|
|
184
|
+
|
|
185
|
+
After running `repoatlas init`, settings are persisted here. Environment variables override the config file.
|
|
186
|
+
|
|
187
|
+
```yaml
|
|
188
|
+
chroma_path: ~/.repoatlas/chroma_db
|
|
189
|
+
provider: ollama
|
|
190
|
+
chat_model: qwen2.5-coder:3b
|
|
191
|
+
embed_model: nomic-embed-text
|
|
192
|
+
ollama_base_url: http://localhost:11434
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Multiple repositories
|
|
198
|
+
|
|
199
|
+
RepoAtlas can hold multiple repos in the same ChromaDB — use `--repo` when querying to restrict to one:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
repoatlas index /path/to/project-a
|
|
203
|
+
repoatlas index /path/to/project-b
|
|
204
|
+
|
|
205
|
+
repoatlas ask "how does auth work?" --repo /path/to/project-a
|
|
206
|
+
repoatlas ask "how does auth work?" --repo /path/to/project-b
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Project structure
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
RepoAtlas/
|
|
215
|
+
├── db/
|
|
216
|
+
│ └── chroma.py — ChromaDB client + collection helpers
|
|
217
|
+
├── indexer/
|
|
218
|
+
│ ├── chunker.py — AST chunker (Python) + line-window fallback (all files)
|
|
219
|
+
│ ├── embedder.py — Ollama /api/embeddings wrapper
|
|
220
|
+
│ └── ingestion.py — Repo walker + indexing pipeline
|
|
221
|
+
├── api/
|
|
222
|
+
│ └── retriever.py — ChromaDB cosine-similarity retrieval
|
|
223
|
+
├── app/
|
|
224
|
+
│ ├── providers.py — Pluggable LLM backends (Ollama / OpenAI / Anthropic / Groq)
|
|
225
|
+
│ └── rag.py — RAG orchestration (retrieve → prompt → generate)
|
|
226
|
+
├── cli/
|
|
227
|
+
│ └── main.py — Typer CLI (init, index, ask)
|
|
228
|
+
└── tests/
|
|
229
|
+
├── test_chunker.py — Unit tests for chunking logic
|
|
230
|
+
└── test_retriever.py — Integration tests for retrieval
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Running tests
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
# Unit tests (no Ollama required)
|
|
239
|
+
pytest tests/test_chunker.py -v
|
|
240
|
+
|
|
241
|
+
# Integration tests (requires Ollama running)
|
|
242
|
+
pytest tests/ -v
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Roadmap
|
|
248
|
+
|
|
249
|
+
- [ ] Tree-sitter chunking for JS / Go / Rust / Java
|
|
250
|
+
- [ ] `repoatlas search` — raw chunk retrieval without LLM
|
|
251
|
+
- [ ] `repoatlas watch` — incremental re-indexing on file change
|
|
252
|
+
- [ ] Web UI
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## License
|
|
257
|
+
|
|
258
|
+
MIT — see [LICENSE](LICENSE)
|
|
File without changes
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Vector retrieval — embeds a question and finds the most similar code chunks
|
|
3
|
+
using ChromaDB cosine similarity. No SQL, no server.
|
|
4
|
+
"""
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
import chromadb
|
|
8
|
+
|
|
9
|
+
from indexer.embedder import get_embedding
|
|
10
|
+
|
|
11
|
+
# --------------------------------------------------------------------------- #
|
|
12
|
+
# Retrieval
|
|
13
|
+
# --------------------------------------------------------------------------- #
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def retrieve(
|
|
17
|
+
question: str,
|
|
18
|
+
collection: chromadb.Collection,
|
|
19
|
+
repo_path: Optional[str] = None,
|
|
20
|
+
top_k: int = 5,
|
|
21
|
+
embed_model: Optional[str] = None,
|
|
22
|
+
) -> list[dict]:
|
|
23
|
+
"""
|
|
24
|
+
Embed *question* and return the *top_k* most similar chunks.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
question : str — natural-language question from the user
|
|
29
|
+
collection : chromadb.Collection — the RepoAtlas chunks collection
|
|
30
|
+
repo_path : str, optional — restrict results to a specific indexed repo
|
|
31
|
+
top_k : int — number of chunks to return (default 5)
|
|
32
|
+
embed_model: str, optional — override the Ollama embedding model
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
list of dicts, each with keys:
|
|
37
|
+
repo_path, file_path, chunk_type, name,
|
|
38
|
+
start_line, end_line, code, similarity
|
|
39
|
+
"""
|
|
40
|
+
kwargs = {"model": embed_model} if embed_model else {}
|
|
41
|
+
q_embedding = get_embedding(question, **kwargs)
|
|
42
|
+
|
|
43
|
+
query_kwargs: dict = {
|
|
44
|
+
"query_embeddings": [q_embedding],
|
|
45
|
+
"n_results": top_k,
|
|
46
|
+
"include": ["documents", "metadatas", "distances"],
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if repo_path:
|
|
50
|
+
query_kwargs["where"] = {"repo_path": repo_path}
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
results = collection.query(**query_kwargs)
|
|
54
|
+
except Exception as exc:
|
|
55
|
+
# ChromaDB raises if collection is empty or top_k > collection size
|
|
56
|
+
msg = str(exc).lower()
|
|
57
|
+
if any(k in msg for k in ("no elements", "cannot query", "index not found", "greater than")):
|
|
58
|
+
return []
|
|
59
|
+
raise
|
|
60
|
+
|
|
61
|
+
docs = results.get("documents", [[]])[0]
|
|
62
|
+
metas = results.get("metadatas", [[]])[0]
|
|
63
|
+
dists = results.get("distances", [[]])[0]
|
|
64
|
+
|
|
65
|
+
chunks = []
|
|
66
|
+
for doc, meta, dist in zip(docs, metas, dists):
|
|
67
|
+
# cosine space: distance ∈ [0, 2], but in practice [0, 1] for normalised
|
|
68
|
+
# vectors. similarity = 1 − distance gives a clean 0–1 score.
|
|
69
|
+
chunks.append({
|
|
70
|
+
"repo_path": meta.get("repo_path", ""),
|
|
71
|
+
"file_path": meta.get("file_path", ""),
|
|
72
|
+
"chunk_type": meta.get("chunk_type", ""),
|
|
73
|
+
"name": meta.get("name", ""),
|
|
74
|
+
"start_line": meta.get("start_line", 0),
|
|
75
|
+
"end_line": meta.get("end_line", 0),
|
|
76
|
+
"code": doc,
|
|
77
|
+
"similarity": round(1.0 - dist, 4),
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
return chunks
|
|
File without changes
|