context-router-cli 0.2.0__py3-none-any.whl
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.
- cli/__init__.py +3 -0
- cli/commands/__init__.py +3 -0
- cli/commands/benchmark.py +153 -0
- cli/commands/decisions.py +169 -0
- cli/commands/explain.py +46 -0
- cli/commands/graph.py +338 -0
- cli/commands/index.py +148 -0
- cli/commands/init.py +79 -0
- cli/commands/mcp.py +30 -0
- cli/commands/memory.py +145 -0
- cli/commands/pack.py +110 -0
- cli/commands/watch.py +126 -0
- cli/commands/workspace.py +294 -0
- cli/main.py +47 -0
- context_router_cli-0.2.0.dist-info/METADATA +632 -0
- context_router_cli-0.2.0.dist-info/RECORD +18 -0
- context_router_cli-0.2.0.dist-info/WHEEL +4 -0
- context_router_cli-0.2.0.dist-info/entry_points.txt +2 -0
cli/main.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""context-router CLI — main entrypoint.
|
|
2
|
+
|
|
3
|
+
All commands are registered here. Business logic lives in the command
|
|
4
|
+
modules under cli/commands/ and in the core/storage packages — never here.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import typer
|
|
10
|
+
|
|
11
|
+
from cli.commands.benchmark import benchmark_app
|
|
12
|
+
from cli.commands.graph import graph_app
|
|
13
|
+
from cli.commands.decisions import decisions_app
|
|
14
|
+
from cli.commands.workspace import workspace_app
|
|
15
|
+
from cli.commands.explain import explain_app
|
|
16
|
+
from cli.commands.index import index_app
|
|
17
|
+
from cli.commands.init import init_app
|
|
18
|
+
from cli.commands.mcp import mcp_app
|
|
19
|
+
from cli.commands.memory import memory_app
|
|
20
|
+
from cli.commands.pack import pack_app
|
|
21
|
+
from cli.commands.watch import watch_app
|
|
22
|
+
|
|
23
|
+
app = typer.Typer(
|
|
24
|
+
name="context-router",
|
|
25
|
+
help=(
|
|
26
|
+
"Local-first context selector for AI coding agents.\n\n"
|
|
27
|
+
"Selects the minimum useful context across code structure, "
|
|
28
|
+
"runtime evidence, and project memory for review, debug, "
|
|
29
|
+
"implement, and handover tasks."
|
|
30
|
+
),
|
|
31
|
+
no_args_is_help=True,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
app.add_typer(init_app, name="init")
|
|
35
|
+
app.add_typer(index_app, name="index")
|
|
36
|
+
app.add_typer(watch_app, name="watch")
|
|
37
|
+
app.add_typer(pack_app, name="pack")
|
|
38
|
+
app.add_typer(explain_app, name="explain")
|
|
39
|
+
app.add_typer(memory_app, name="memory")
|
|
40
|
+
app.add_typer(decisions_app, name="decisions")
|
|
41
|
+
app.add_typer(benchmark_app, name="benchmark")
|
|
42
|
+
app.add_typer(workspace_app, name="workspace")
|
|
43
|
+
app.add_typer(mcp_app, name="mcp")
|
|
44
|
+
app.add_typer(graph_app, name="graph")
|
|
45
|
+
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
app()
|
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: context-router-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Local-first CLI and MCP server for AI coding context — minimum useful context, maximum agent performance
|
|
5
|
+
Project-URL: Homepage, https://github.com/mohankrishnaalavala/context-router
|
|
6
|
+
Project-URL: Bug Tracker, https://github.com/mohankrishnaalavala/context-router/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/mohankrishnaalavala/context-router/blob/main/CHANGELOG.md
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: ai,code-analysis,context,developer-tools,llm,mcp
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: >=3.12
|
|
17
|
+
Requires-Dist: context-router-adapters-claude
|
|
18
|
+
Requires-Dist: context-router-adapters-codex
|
|
19
|
+
Requires-Dist: context-router-adapters-copilot
|
|
20
|
+
Requires-Dist: context-router-benchmark
|
|
21
|
+
Requires-Dist: context-router-contracts
|
|
22
|
+
Requires-Dist: context-router-core
|
|
23
|
+
Requires-Dist: context-router-graph-index
|
|
24
|
+
Requires-Dist: context-router-language-python
|
|
25
|
+
Requires-Dist: context-router-language-typescript
|
|
26
|
+
Requires-Dist: context-router-language-yaml
|
|
27
|
+
Requires-Dist: context-router-memory
|
|
28
|
+
Requires-Dist: context-router-ranking
|
|
29
|
+
Requires-Dist: context-router-runtime
|
|
30
|
+
Requires-Dist: context-router-storage-sqlite
|
|
31
|
+
Requires-Dist: context-router-workspace
|
|
32
|
+
Requires-Dist: typer>=0.12
|
|
33
|
+
Provides-Extra: semantic
|
|
34
|
+
Requires-Dist: sentence-transformers>=2.2; extra == 'semantic'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# context-router
|
|
38
|
+
|
|
39
|
+
A local-first CLI and MCP server that selects the **minimum useful context** across code structure, runtime evidence, and project memory for AI coding agents — reducing token consumption on review, debug, implement, and handover tasks.
|
|
40
|
+
|
|
41
|
+
## Why
|
|
42
|
+
|
|
43
|
+
AI coding agents work best with focused, relevant context rather than entire codebases. context-router:
|
|
44
|
+
|
|
45
|
+
- Indexes your repo's symbols, dependency edges, call graphs, and test coverage into a local SQLite database
|
|
46
|
+
- Ranks candidates by structural relevance, query similarity, and community membership for your task mode
|
|
47
|
+
- Enforces a configurable token budget so your agent prompt stays lean (64.7% average reduction)
|
|
48
|
+
- Explains every selection decision in one human-readable sentence
|
|
49
|
+
- Supports multi-repo workspaces with cross-repo confidence boosting
|
|
50
|
+
- Works as a CLI, MCP server, or Python library — no API key required
|
|
51
|
+
|
|
52
|
+
## Feature Overview
|
|
53
|
+
|
|
54
|
+
| Feature | Detail |
|
|
55
|
+
|---|---|
|
|
56
|
+
| **Language support** | Python (full), TypeScript/JS (full), YAML (k8s/Helm/GHA), Java, .NET (stubs) |
|
|
57
|
+
| **Edge types** | `imports`, `calls` (function-level), `tested_by`, community links |
|
|
58
|
+
| **Task modes** | `review`, `implement`, `debug`, `handover` |
|
|
59
|
+
| **Ranking** | Confidence scoring, query keyword boost, optional semantic boost (sentence-transformers) |
|
|
60
|
+
| **Token budget** | Hard cap with per-source-type guarantee; dynamic scaling for small repos |
|
|
61
|
+
| **Memory** | Persistent session observations + architectural decision records (FTS search) |
|
|
62
|
+
| **Multi-repo** | Workspace YAML, cross-repo link detection, unified ranked pack |
|
|
63
|
+
| **Graph viz** | Interactive D3.js HTML — color by kind or community cluster |
|
|
64
|
+
| **MCP server** | 8 tools over stdio JSON-RPC 2.0, compatible with Claude Code, Cursor, Windsurf |
|
|
65
|
+
| **Agent adapters** | Claude system prompt, Copilot instructions, Codex task prompt |
|
|
66
|
+
| **Benchmarks** | 20-task suite, 3 baselines, Markdown report |
|
|
67
|
+
|
|
68
|
+
## Requirements
|
|
69
|
+
|
|
70
|
+
- Python 3.12+
|
|
71
|
+
- [uv](https://docs.astral.sh/uv/) package manager
|
|
72
|
+
|
|
73
|
+
## Install
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
git clone https://github.com/mohankrishnaalavala/context-router
|
|
77
|
+
cd context-router
|
|
78
|
+
uv sync --all-packages
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
> **PyPI install (coming soon):** `pip install context-router`
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Quickstart
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# 1. Initialize a project (creates .context-router/ with config + SQLite DB)
|
|
89
|
+
uv run context-router init
|
|
90
|
+
|
|
91
|
+
# 2. Index the repository — extracts symbols, call edges, test links, communities
|
|
92
|
+
uv run context-router index
|
|
93
|
+
|
|
94
|
+
# 3. Generate a context pack for a code review
|
|
95
|
+
uv run context-router pack --mode review
|
|
96
|
+
|
|
97
|
+
# 4. Implement a feature — query-aware ranking surfaces the right files
|
|
98
|
+
uv run context-router pack --mode implement --query "add pagination to the users endpoint"
|
|
99
|
+
|
|
100
|
+
# 5. Debug a failure — parse an error file and rank by blast radius
|
|
101
|
+
uv run context-router pack --mode debug --error-file pytest-output.xml
|
|
102
|
+
|
|
103
|
+
# 6. Explain what was selected and why
|
|
104
|
+
uv run context-router explain last-pack
|
|
105
|
+
|
|
106
|
+
# 7. Visualize the symbol graph
|
|
107
|
+
uv run context-router graph --open
|
|
108
|
+
|
|
109
|
+
# 8. Get machine-readable JSON for scripts or agent prompts
|
|
110
|
+
uv run context-router pack --mode review --json
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Commands Reference
|
|
116
|
+
|
|
117
|
+
| Command | Purpose |
|
|
118
|
+
|---|---|
|
|
119
|
+
| [`init`](#init) | Initialize `.context-router/` config and database |
|
|
120
|
+
| [`index`](#index) | Scan and index all source files |
|
|
121
|
+
| [`watch`](#watch) | Incrementally re-index on file save |
|
|
122
|
+
| [`pack`](#pack) | Generate a ranked context pack |
|
|
123
|
+
| [`explain`](#explain) | Explain the last pack's selections |
|
|
124
|
+
| [`memory`](#memory) | Add/search session observations |
|
|
125
|
+
| [`decisions`](#decisions) | Add/search architectural decision records |
|
|
126
|
+
| [`graph`](#graph) | Generate interactive HTML graph visualization |
|
|
127
|
+
| [`workspace`](#workspace) | Multi-repo workspace management |
|
|
128
|
+
| [`benchmark`](#benchmark) | Run 20-task benchmark suite |
|
|
129
|
+
| [`mcp`](#mcp) | Start the MCP server (for Claude Code, Cursor, Windsurf) |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### `init`
|
|
134
|
+
|
|
135
|
+
Initialize a project. Creates `.context-router/config.yaml` and `.context-router/context-router.db`.
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
context-router init [--project-root PATH] [--json]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
### `index`
|
|
144
|
+
|
|
145
|
+
Scan and index the repository.
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
context-router index [--project-root PATH] [--repo REPO_NAME]
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Walks all source files, runs language analyzers (discovered via `context_router.language_analyzers` entry points), and writes to the local DB:
|
|
152
|
+
|
|
153
|
+
- **Symbols** — functions, classes, interfaces, k8s resources, GitHub Actions jobs
|
|
154
|
+
- **Import edges** — which files import which modules
|
|
155
|
+
- **Call edges** — which functions call which functions (Python, TypeScript)
|
|
156
|
+
- **TESTED_BY edges** — links `test_foo` → `foo` by name convention
|
|
157
|
+
- **Community IDs** — Union-Find clustering of connected symbols
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
uv run context-router index
|
|
161
|
+
# Indexed 286 files — 1765 symbols, 3174 edges (2.82s)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### `watch`
|
|
167
|
+
|
|
168
|
+
Watch for file changes and incrementally re-index.
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
context-router watch [--project-root PATH]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### `pack`
|
|
177
|
+
|
|
178
|
+
Generate a ranked context pack for a task.
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
context-router pack --mode MODE [--query TEXT] [--project-root PATH] [--json]
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Modes:**
|
|
185
|
+
|
|
186
|
+
| Mode | Ranking priority | Best for |
|
|
187
|
+
|---|---|---|
|
|
188
|
+
| `review` | changed files → blast radius → impacted tests → config | PR review, diff analysis |
|
|
189
|
+
| `implement` | entrypoints → contracts → extension points → patterns | Building new features |
|
|
190
|
+
| `debug` | runtime signal match → failing tests → changed files → call chain | Fixing errors, CI failures |
|
|
191
|
+
| `handover` | recent changes → memory observations → decisions → blast radius | Onboarding, sprint docs |
|
|
192
|
+
|
|
193
|
+
**Token budget** (default: 8 000 tokens) is read from `.context-router/config.yaml`. Items are dropped lowest-confidence first, but at least one item per source category is always preserved.
|
|
194
|
+
|
|
195
|
+
The pack is saved to `.context-router/last-pack.json` for later inspection.
|
|
196
|
+
|
|
197
|
+
**Examples:**
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# Review mode — surfaces changed files and their dependencies
|
|
201
|
+
uv run context-router pack --mode review
|
|
202
|
+
|
|
203
|
+
# Implement with query — boosts items matching "rate limiting"
|
|
204
|
+
uv run context-router pack --mode implement --query "add rate limiting to API endpoints"
|
|
205
|
+
|
|
206
|
+
# Debug with error file — parse pytest/JUnit XML to find root cause
|
|
207
|
+
uv run context-router pack --mode debug --error-file test-results.xml
|
|
208
|
+
|
|
209
|
+
# JSON output for piping into agent prompts
|
|
210
|
+
uv run context-router pack --mode review --json | jq '.selected_items[].title'
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
### `explain`
|
|
216
|
+
|
|
217
|
+
Explain the last generated context pack.
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
context-router explain last-pack [--json]
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
[changed_file] build_pack (orchestrator.py) — Modified in current diff
|
|
225
|
+
[blast_radius] ContextRanker (ranker.py) — Depends on a changed file
|
|
226
|
+
[impacted_test] test_ranker.py — Tests code affected by this change
|
|
227
|
+
[contract] ContextItem (models.py) — Data contract or interface definition
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
### `memory`
|
|
233
|
+
|
|
234
|
+
Persist and search session observations. Stored in the local SQLite DB with FTS5 full-text search.
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
context-router memory add --from-session SESSION.json
|
|
238
|
+
context-router memory search QUERY
|
|
239
|
+
context-router memory stale
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
`stale` lists observations whose referenced files no longer exist in the index.
|
|
243
|
+
|
|
244
|
+
**Examples:**
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
# Search for past observations about authentication
|
|
248
|
+
uv run context-router memory search "auth token"
|
|
249
|
+
|
|
250
|
+
# Find observations referencing files that were deleted
|
|
251
|
+
uv run context-router memory stale
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
### `decisions`
|
|
257
|
+
|
|
258
|
+
Manage architectural decision records (ADRs). Persisted with FTS5 search across title, context, and decision fields.
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
context-router decisions add TITLE [--decision TEXT] [--context TEXT] [--consequences TEXT] [--tags TAGS] [--status STATUS]
|
|
262
|
+
context-router decisions search QUERY
|
|
263
|
+
context-router decisions list
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
`--status` accepts: `proposed` | `accepted` | `deprecated` | `superseded`
|
|
267
|
+
|
|
268
|
+
**Examples:**
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Record a new ADR
|
|
272
|
+
uv run context-router decisions add "Use SQLite for local storage" \
|
|
273
|
+
--decision "SQLite + FTS5 chosen over PostgreSQL" \
|
|
274
|
+
--context "Need offline-capable storage" \
|
|
275
|
+
--status accepted
|
|
276
|
+
|
|
277
|
+
# Search decisions by keyword
|
|
278
|
+
uv run context-router decisions search "database"
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
### `graph`
|
|
284
|
+
|
|
285
|
+
Generate a self-contained interactive HTML graph visualization of the indexed symbol graph.
|
|
286
|
+
|
|
287
|
+
```
|
|
288
|
+
context-router graph [--project-root PATH] [--output PATH] [--open] [--json]
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
- Nodes are **colored by kind** (function=green, class=blue, interface=teal, k8s=orange) or by **community cluster** (toggle in the UI)
|
|
292
|
+
- Node **size** reflects degree (more connections = larger)
|
|
293
|
+
- **Click** any node for a details panel (file, kind, community, signature)
|
|
294
|
+
- **Search/filter** by symbol name
|
|
295
|
+
- **Zoom/pan** with scroll and drag
|
|
296
|
+
- `--open` launches your default browser immediately
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# Generate and open in browser
|
|
300
|
+
uv run context-router graph --open
|
|
301
|
+
|
|
302
|
+
# Save to a path for sharing or docs
|
|
303
|
+
uv run context-router graph --output ./docs/graph.html
|
|
304
|
+
|
|
305
|
+
# Raw JSON for programmatic use
|
|
306
|
+
uv run context-router graph --json
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
### `workspace`
|
|
312
|
+
|
|
313
|
+
Manage multi-repo workspaces with cross-repo context packs.
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
context-router workspace init [--root PATH] [--name NAME]
|
|
317
|
+
context-router workspace repo add NAME PATH [--root PATH]
|
|
318
|
+
context-router workspace repo list [--root PATH] [--json]
|
|
319
|
+
context-router workspace link add FROM TO [--root PATH]
|
|
320
|
+
context-router workspace pack --mode MODE [--query TEXT] [--root PATH] [--json]
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**How it works:**
|
|
324
|
+
|
|
325
|
+
1. `workspace init` creates `workspace.yaml` at the root
|
|
326
|
+
2. `repo add` registers each repo and captures its git branch/SHA
|
|
327
|
+
3. `link add` declares a dependency between repos (boosts cross-repo confidence)
|
|
328
|
+
4. `pack` runs `Orchestrator` per repo, merges candidates labelled with `[repo-name]`, and re-ranks within a unified token budget
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
# Set up a two-repo workspace
|
|
332
|
+
uv run context-router workspace init
|
|
333
|
+
uv run context-router workspace repo add api ./services/api
|
|
334
|
+
uv run context-router workspace repo add frontend ./services/frontend
|
|
335
|
+
uv run context-router workspace link add frontend api
|
|
336
|
+
uv run context-router workspace pack --mode review
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
### `benchmark`
|
|
342
|
+
|
|
343
|
+
Run the built-in 20-task suite and measure token reduction vs naive/keyword baselines.
|
|
344
|
+
|
|
345
|
+
```
|
|
346
|
+
context-router benchmark run [--project-root PATH] [--output PATH] [--json]
|
|
347
|
+
context-router benchmark report [--project-root PATH] [--input PATH] [--json]
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
See [BENCHMARK_RESULTS.md](BENCHMARK_RESULTS.md) for real numbers on the context-router codebase (**64.7% average token reduction, 131 ms average latency**).
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
### `mcp`
|
|
355
|
+
|
|
356
|
+
Start the context-router MCP server over stdio JSON-RPC 2.0, exposing all tools to any MCP-compatible AI coding agent.
|
|
357
|
+
|
|
358
|
+
```
|
|
359
|
+
context-router mcp
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**Available MCP tools:**
|
|
363
|
+
|
|
364
|
+
| Tool | What it does |
|
|
365
|
+
|---|---|
|
|
366
|
+
| `build_index` | Full re-index of the repository |
|
|
367
|
+
| `update_index` | Incremental re-index for changed files |
|
|
368
|
+
| `get_context_pack` | Ranked pack for review / implement / debug / handover |
|
|
369
|
+
| `get_debug_pack` | Debug pack with optional error-file (pytest/JUnit XML) parsing |
|
|
370
|
+
| `explain_selection` | Why each item was selected + token count stats |
|
|
371
|
+
| `generate_handover` | Handover pack combining changes + memory + decisions |
|
|
372
|
+
| `search_memory` | Full-text search of session observations |
|
|
373
|
+
| `get_decisions` | Search or list architectural decision records |
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## MCP Setup Guide
|
|
378
|
+
|
|
379
|
+
### Claude Code
|
|
380
|
+
|
|
381
|
+
Add to `.mcp.json` in your project root (or `~/.claude/mcp.json` for global config):
|
|
382
|
+
|
|
383
|
+
```json
|
|
384
|
+
{
|
|
385
|
+
"mcpServers": {
|
|
386
|
+
"context-router": {
|
|
387
|
+
"command": "uv",
|
|
388
|
+
"args": ["run", "--directory", "/path/to/your/project", "context-router", "mcp"]
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Then in Claude Code:
|
|
395
|
+
```
|
|
396
|
+
/mcp
|
|
397
|
+
```
|
|
398
|
+
You'll see `context-router` listed. Use it with:
|
|
399
|
+
```
|
|
400
|
+
Use context-router to get a context pack for reviewing my recent changes
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Cursor
|
|
404
|
+
|
|
405
|
+
Add to `.cursor/mcp.json`:
|
|
406
|
+
|
|
407
|
+
```json
|
|
408
|
+
{
|
|
409
|
+
"mcpServers": {
|
|
410
|
+
"context-router": {
|
|
411
|
+
"command": "uv",
|
|
412
|
+
"args": ["run", "context-router", "mcp"],
|
|
413
|
+
"cwd": "${workspaceFolder}"
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Restart Cursor. The tools appear in the Cursor agent panel under MCP.
|
|
420
|
+
|
|
421
|
+
### Windsurf
|
|
422
|
+
|
|
423
|
+
Add to `.windsurf/mcp_config.json`:
|
|
424
|
+
|
|
425
|
+
```json
|
|
426
|
+
{
|
|
427
|
+
"servers": {
|
|
428
|
+
"context-router": {
|
|
429
|
+
"command": "uv run context-router mcp",
|
|
430
|
+
"transport": "stdio"
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Using MCP Tools in Practice
|
|
437
|
+
|
|
438
|
+
Once connected, your agent can call tools directly:
|
|
439
|
+
|
|
440
|
+
```
|
|
441
|
+
# Get context for a code review (agent calls get_context_pack)
|
|
442
|
+
"Review the auth changes in my PR. Use context-router to find all affected code."
|
|
443
|
+
|
|
444
|
+
# Debug a failing test (agent calls get_debug_pack)
|
|
445
|
+
"My tests are failing with AttributeError. Use context-router to find the root cause."
|
|
446
|
+
|
|
447
|
+
# Handover documentation (agent calls generate_handover)
|
|
448
|
+
"Generate a handover document for what I worked on this sprint."
|
|
449
|
+
|
|
450
|
+
# Search past decisions (agent calls get_decisions)
|
|
451
|
+
"What architectural decisions were made about the database layer?"
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Programmatic Use (Python SDK)
|
|
455
|
+
|
|
456
|
+
```python
|
|
457
|
+
from core.orchestrator import Orchestrator
|
|
458
|
+
|
|
459
|
+
# Get a context pack
|
|
460
|
+
pack = Orchestrator(project_root="/path/to/repo").build_pack(
|
|
461
|
+
mode="implement",
|
|
462
|
+
query="add rate limiting to the API"
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
print(f"Selected {len(pack.selected_items)} items, {pack.total_tokens} tokens")
|
|
466
|
+
for item in pack.selected_items:
|
|
467
|
+
print(f" [{item.source_type}] {item.title} — {item.reason}")
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
```python
|
|
471
|
+
# With semantic ranking (requires: pip install sentence-transformers)
|
|
472
|
+
from ranking.ranker import ContextRanker
|
|
473
|
+
|
|
474
|
+
ranker = ContextRanker(token_budget=8000, use_embeddings=True)
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
```python
|
|
478
|
+
# Agent adapters
|
|
479
|
+
from adapters_claude import ClaudeAdapter
|
|
480
|
+
from adapters_copilot import CopilotAdapter
|
|
481
|
+
|
|
482
|
+
pack = Orchestrator().build_pack("review", "fix the auth bug")
|
|
483
|
+
print(ClaudeAdapter().generate(pack)) # System prompt preamble for Claude
|
|
484
|
+
print(CopilotAdapter().generate(pack)) # .github/copilot-instructions.md
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## Configuration
|
|
490
|
+
|
|
491
|
+
Edit `.context-router/config.yaml`:
|
|
492
|
+
|
|
493
|
+
```yaml
|
|
494
|
+
# Maximum tokens for a generated context pack (default: 8000)
|
|
495
|
+
token_budget: 8000
|
|
496
|
+
|
|
497
|
+
# Repository name (used as the key in the SQLite DB)
|
|
498
|
+
repo_name: default
|
|
499
|
+
|
|
500
|
+
capabilities:
|
|
501
|
+
# Enable LLM-powered summarization (requires API key — future feature)
|
|
502
|
+
llm_summarization: false
|
|
503
|
+
|
|
504
|
+
# fnmatch patterns to exclude from indexing
|
|
505
|
+
ignore_patterns:
|
|
506
|
+
- ".git"
|
|
507
|
+
- "__pycache__"
|
|
508
|
+
- "*.pyc"
|
|
509
|
+
- "*.egg-info"
|
|
510
|
+
- ".venv"
|
|
511
|
+
- "node_modules"
|
|
512
|
+
- "dist"
|
|
513
|
+
- "build"
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## Architecture
|
|
519
|
+
|
|
520
|
+
context-router is a `uv` workspace of focused packages with strict import boundaries:
|
|
521
|
+
|
|
522
|
+
```
|
|
523
|
+
packages/
|
|
524
|
+
contracts/ # Pydantic models + plugin protocols (no internal deps)
|
|
525
|
+
storage-sqlite/ # SQLite DB, migrations, FTS5, repositories
|
|
526
|
+
graph-index/ # File scanner, language dispatch, git diff, community detection
|
|
527
|
+
ranking/ # Token estimator, ContextRanker, query/semantic boost
|
|
528
|
+
core/ # Orchestrator — wires storage + graph + ranking
|
|
529
|
+
language-python/ # Python AST (tree-sitter): symbols, imports, calls
|
|
530
|
+
language-typescript/ # TypeScript/JS AST (tree-sitter): symbols, imports, calls
|
|
531
|
+
language-yaml/ # YAML: k8s resources, Helm charts, GitHub Actions
|
|
532
|
+
language-java/ # Java (stub)
|
|
533
|
+
language-dotnet/ # .NET/C# (stub)
|
|
534
|
+
memory/ # Observation store + FTS
|
|
535
|
+
runtime/ # Stack trace + JUnit/pytest XML parsers
|
|
536
|
+
workspace/ # Multi-repo workspace support
|
|
537
|
+
benchmark/ # 20-task benchmark harness
|
|
538
|
+
adapters-claude/ # Claude system-prompt adapter
|
|
539
|
+
adapters-copilot/ # GitHub Copilot instructions adapter
|
|
540
|
+
adapters-codex/ # Codex task prompt adapter
|
|
541
|
+
apps/
|
|
542
|
+
cli/ # Typer CLI (all commands)
|
|
543
|
+
mcp-server/ # MCP server entry point
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
**Module boundary rules** (enforced in CI):
|
|
547
|
+
|
|
548
|
+
- `contracts` has zero internal dependencies
|
|
549
|
+
- Only `storage-sqlite` touches SQLite
|
|
550
|
+
- Only `core` imports from `storage-sqlite`, `graph-index`, and `ranking`
|
|
551
|
+
- CLI and MCP server only import from `core` and `benchmark`
|
|
552
|
+
|
|
553
|
+
---
|
|
554
|
+
|
|
555
|
+
## Development
|
|
556
|
+
|
|
557
|
+
```bash
|
|
558
|
+
# Install all packages + dev dependencies
|
|
559
|
+
uv sync --all-packages --extra dev
|
|
560
|
+
|
|
561
|
+
# Run all 403 tests
|
|
562
|
+
uv run pytest --tb=short -q
|
|
563
|
+
|
|
564
|
+
# Lint
|
|
565
|
+
uv run ruff check .
|
|
566
|
+
|
|
567
|
+
# Install git pre-push hook (runs tests before every push)
|
|
568
|
+
git config core.hooksPath .githooks
|
|
569
|
+
|
|
570
|
+
# Re-index after code changes
|
|
571
|
+
uv run context-router index
|
|
572
|
+
|
|
573
|
+
# Check release readiness
|
|
574
|
+
/release-check
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
## Adding a Language Analyzer
|
|
580
|
+
|
|
581
|
+
Implement the `LanguageAnalyzer` protocol and register via entry points:
|
|
582
|
+
|
|
583
|
+
```python
|
|
584
|
+
# my_package/analyzer.py
|
|
585
|
+
from pathlib import Path
|
|
586
|
+
from contracts.interfaces import Symbol, DependencyEdge
|
|
587
|
+
|
|
588
|
+
class RustAnalyzer:
|
|
589
|
+
def analyze(self, path: Path) -> list[Symbol | DependencyEdge]:
|
|
590
|
+
...
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
```toml
|
|
594
|
+
# pyproject.toml
|
|
595
|
+
[project.entry-points."context_router.language_analyzers"]
|
|
596
|
+
rs = "my_package.analyzer:RustAnalyzer"
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
Install your package into the workspace and `context-router index` will pick it up automatically.
|
|
600
|
+
|
|
601
|
+
---
|
|
602
|
+
|
|
603
|
+
## Benchmark Results
|
|
604
|
+
|
|
605
|
+
Measured on the context-router codebase itself (286 files, 1 765 symbols, 3 174 edges):
|
|
606
|
+
|
|
607
|
+
| Mode | Avg tokens selected | vs naive (all symbols) | Avg latency |
|
|
608
|
+
|---|---|---|---|
|
|
609
|
+
| review | 1 420 | −73% | 118 ms |
|
|
610
|
+
| implement | 1 680 | −68% | 124 ms |
|
|
611
|
+
| debug | 1 290 | −75% | 142 ms |
|
|
612
|
+
| handover | 1 510 | −71% | 139 ms |
|
|
613
|
+
| **overall** | **1 475** | **−64.7%** | **131 ms** |
|
|
614
|
+
|
|
615
|
+
See [BENCHMARK_RESULTS.md](BENCHMARK_RESULTS.md) for the full per-task breakdown.
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
## Contributing
|
|
620
|
+
|
|
621
|
+
See `.handover/` for architecture context, decision records, and open tasks.
|
|
622
|
+
|
|
623
|
+
- Architecture: `.handover/context/architecture.md`
|
|
624
|
+
- Decision log: `.handover/context/decisions.md`
|
|
625
|
+
- Task list: `.handover/work/tasks.md`
|
|
626
|
+
- Coding standards: `.handover/standards/coding-standards.md`
|
|
627
|
+
|
|
628
|
+
---
|
|
629
|
+
|
|
630
|
+
## License
|
|
631
|
+
|
|
632
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
cli/__init__.py,sha256=T8h6qKEnthCoFdeJSE_uhzsfPej8qEzGlBDbsGChdxc,74
|
|
2
|
+
cli/main.py,sha256=ubpVifEkcvtLV1XKyWJEVESmjSp8A7ok1ckYqfiLAO0,1544
|
|
3
|
+
cli/commands/__init__.py,sha256=Slw8AcMsKWSZoUF1wA3H5Ad7OJQDvvFxnSyg9jzQ6vM,82
|
|
4
|
+
cli/commands/benchmark.py,sha256=Pkb973jfWv43PjDS5HZYRwgcNstVnKhwpxCEImuMgW4,5256
|
|
5
|
+
cli/commands/decisions.py,sha256=KEHrfSFqJVy-eg1ijreBMygJq0_bWaD6o8ybOt1qVds,4948
|
|
6
|
+
cli/commands/explain.py,sha256=cjZWWlbShM_kd3TbSBrJWf0e5Z7bJf6eE5Tp-lh3J7s,1402
|
|
7
|
+
cli/commands/graph.py,sha256=VIWPrbOlHRb3ENF6D3WlSvEbber8ndfFh2s_dVrc1-8,12270
|
|
8
|
+
cli/commands/index.py,sha256=iBLH9v4H4DmJ9mZjmbOmOBdMhTTtznRcr-f8WuGH7b8,5090
|
|
9
|
+
cli/commands/init.py,sha256=Ios-b9P6RCkw8YcpspUYS5p-Qm2LLdxdbONqmXLNrI4,2484
|
|
10
|
+
cli/commands/mcp.py,sha256=yjNcqW3tob64yzqea7w8st_w69MFwAhIfdSdzhsNavo,875
|
|
11
|
+
cli/commands/memory.py,sha256=Egwc9pJLfAYYbOdeDHhJ5u6XdPB95WlEje8IpNdjabw,4341
|
|
12
|
+
cli/commands/pack.py,sha256=00TV0Z7_nEPbMjmiPYbhcr1TTUmNrKbi4DsT7sDUNo8,3331
|
|
13
|
+
cli/commands/watch.py,sha256=BtuskSwhMeiBVcQJiHwoZvJsCry4NxjjctfAlD7ul70,4066
|
|
14
|
+
cli/commands/workspace.py,sha256=s1fqZP6oT-VgzT_xK8wJk0GjYqUw1Oi99C_VKv8GJFo,9072
|
|
15
|
+
context_router_cli-0.2.0.dist-info/METADATA,sha256=rGyGC1Xb3uCWW_6LA_8gLsCbLx13bVXiaTTv649NjKk,19319
|
|
16
|
+
context_router_cli-0.2.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
17
|
+
context_router_cli-0.2.0.dist-info/entry_points.txt,sha256=OvGMK5kUNTs4OUPlxP-yEk5yc8pmXLTG3oje8iHbUiI,48
|
|
18
|
+
context_router_cli-0.2.0.dist-info/RECORD,,
|