Metadata-Version: 2.4
Name: gritter
Version: 0.1.0
Summary: Query any codebase with natural language using RAG
License: MIT
Keywords: cli,code-search,llm,rag,retrieval
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Requires-Dist: anthropic>=0.30
Requires-Dist: chromadb>=0.5
Requires-Dist: einops>=0.7
Requires-Dist: openai>=1.0
Requires-Dist: pydantic-settings>=2.3
Requires-Dist: rank-bm25>=0.2
Requires-Dist: rich>=13
Requires-Dist: sentence-transformers>=3
Requires-Dist: tiktoken>=0.7
Requires-Dist: tomli-w>=1
Requires-Dist: tree-sitter-python>=0.23
Requires-Dist: tree-sitter-rust>=0.23
Requires-Dist: tree-sitter-typescript>=0.23
Requires-Dist: tree-sitter>=0.23
Requires-Dist: typer[all]>=0.12
Requires-Dist: voyageai>=0.3
Provides-Extra: dev
Requires-Dist: pytest-mock>=3; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# gritter

Query any codebase with natural language. Gritter indexes your code using AST-aware chunking and hybrid retrieval (dense + BM25 with reciprocal rank fusion), then answers questions with cited file and line number references.

```
$ gritter index ./my-project
Indexing /home/user/my-project as my-project
✓ Index my-project ready — 142 files, 1,847 chunks, languages: python, typescript, rust

$ gritter ask "How does authentication work?"
Token validation happens in src/auth/jwt.py:L15-45 via the validate_token function,
which decodes the JWT and checks expiry using the SECRET_KEY from environment config
(src/config.py:L8).

Sources:
  • src/auth/jwt.py:L15-45
  • src/config.py:L8
```

---

## Installation

```bash
pip install gritter
```

### API keys

Gritter reads API keys from environment variables — never written to config files.

| Provider | Variable |
|---|---|
| Anthropic (default LLM) | `ANTHROPIC_API_KEY` |
| Voyage (default embeddings) | `VOYAGE_API_KEY` |
| OpenAI | `OPENAI_API_KEY` |

---

## Quick start

```bash
# Index a codebase
gritter index /path/to/repo

# Ask a single question
gritter ask "Where is the database connection configured?"

# Interactive multi-turn chat
gritter chat

# Check index status
gritter status

# Use a different embedding provider (no API key needed)
GRITTER_EMBEDDING__PROVIDER=local gritter index /path/to/repo
```

---

## Commands

| Command | Description |
|---|---|
| `gritter index <path>` | Index a local directory |
| `gritter ask "<question>"` | Single query — streams answer, prints Sources |
| `gritter chat` | Interactive REPL for multi-turn queries |
| `gritter status [name]` | Show index stats (files, chunks, languages, provider) |
| `gritter config set <key> <value>` | Write a config value to `~/.config/gritter/config.toml` |
| `gritter config show` | Print current effective configuration |

---

## Configuration

Config is loaded in priority order: CLI flags → environment variables → `.gritterrc` (project root) → `~/.config/gritter/config.toml` → defaults.

```bash
# Switch to OpenAI embeddings
gritter config set embedding.provider openai

# Switch to local embeddings (no API key)
gritter config set embedding.provider local

# Use Ollama for LLM (no API key)
gritter config set llm.provider ollama
gritter config set llm.model llama3

# Adjust retrieval
gritter config set retrieval.top_k 10
```

Environment variable override format: `GRITTER_<SECTION>__<KEY>` (double underscore for nesting).

```bash
GRITTER_LLM__PROVIDER=openai gritter ask "..."
```

### Key config fields

| Key | Default | Description |
|---|---|---|
| `embedding.provider` | `voyage` | `voyage` \| `openai` \| `local` |
| `embedding.model` | (provider default) | Model name override |
| `llm.provider` | `claude` | `claude` \| `openai` \| `ollama` |
| `llm.model` | (provider default) | Model name override |
| `index.chunk_min_tokens` | `50` | Merge chunks smaller than this |
| `index.chunk_max_tokens` | `512` | Split chunks larger than this |
| `retrieval.top_k` | `5` | Number of results returned |
| `retrieval.candidate_k` | `20` | Candidates fed into RRF from each retriever |

---

## Language support

AST-based chunking (tree-sitter) for **Python**, **TypeScript/JavaScript**, and **Rust** — extracts functions, classes, and methods as individual chunks with correct line boundaries.

All other languages use a heuristic chunker: blank-line-separated blocks respecting indentation depth, with token-limit splitting as a fallback.

---

## Architecture

Three independent pipelines sharing a common data model:

- **Indexing**: file discovery → language detection → AST/heuristic chunking → embedding → ChromaDB + BM25 storage
- **Retrieval**: embed query → dense search (ChromaDB cosine) + sparse search (BM25) → reciprocal rank fusion → top-k
- **Generation**: retrieval results → prompt construction → LLM streaming → citation parsing

The CLI layer is a thin orchestrator — no business logic.

---

## Multiple indexes

Multiple repos can coexist. Use `--name` to distinguish them:

```bash
gritter index ~/work/backend --name backend
gritter index ~/work/frontend --name frontend

gritter ask "How are API routes defined?" --name backend
gritter chat --name frontend
```

---

## Development

```bash
git clone https://github.com/yourname/gritter
cd gritter
pip install -e ".[dev]"
pytest
```

End-to-end tests (requires API keys):
```bash
GRITTER_RUN_E2E_TESTS=1 pytest tests/test_e2e.py -v
```
