Scope your AI context before it explodes
Project description
context-router
Problem
Working with AI tools on large codebases causes context explosion. Every task loads the entire codebase into the prompt.
What context-router does
Routes a task to the agent that owns it. Scopes the prompt to only the relevant files. Keeps a lightweight map of who owns what.
What context-router does NOT do
Does not call any LLM. Does not automate anything. Does not execute code.
Without context-router:
"fix the auth bug" → loads 847 files → model touches 6 modules it shouldn't
With context-router:
context-router ask "fix the auth bug" --file src/auth/token.py → Agent: backend-engineer → Touch only: src/auth/token.py, src/auth/session.py → Do not modify: src/api/, src/db/, src/frontend/
Install
pip install context-router
Local dev:
pip install -e .
Usage
1. Define your agents
context-router init creates 3 core agents automatically:
agents/
├── dispatcher.agent.yaml ← routes all tasks (do not edit)
├── memory-keeper.agent.yaml ← syncs memory after commits (do not edit)
├── validator.agent.yaml ← validates diffs before applying (do not edit)
└── default.agent.yaml ← template — copy and rename for your domains
Add one agent per domain in your project.
Create an agents/ directory in your project and add one YAML file per agent:
# agents/backend-engineer.agent.yaml
name: backend-engineer
owned_paths:
- src/auth/*.py
- src/api/*.py
- src/db/*.py
description: Handles backend logic including authentication, API routes, and database models.
2. Initialize
context-router init
Specify your AI tool:
context-router init --tool claude # Claude Code
context-router init --tool cursor # Cursor
context-router init --tool copilot # GitHub Copilot
context-router init --tool codex # Codex / OpenAI
context-router init --tool windsurf # Windsurf
context-router init --tool aider # Aider
context-router init --tool all # generate all
If you skip --tool, context-router detects your tool automatically or asks you to choose.
| Tool | Config file generated |
|---|---|
| Claude Code | CLAUDE.md + AGENTS.md |
| Cursor | .cursorrules |
| GitHub Copilot | .github/copilot-instructions.md |
| Codex | AGENTS.md |
| Windsurf | .windsurfrules |
| Aider | .aider.conf.yml |
Scans all *.agent.yaml files in agents/, writes .context-router/project_map.json, and
scaffolds the full memory structure.
After context-router init your project contains:
.context-router/
├── CORE.md ← global invariants (always loaded)
├── CORE_LITE.md ← minimal version for quick tasks
├── project_map.json ← agent ownership map (auto-generated)
└── memory/
├── MEMORY.md ← status, architecture, recent fixes
├── MEMORY_MAP.md ← file/function ownership
├── MEMORY_CHANGELOG.md ← full fix history (load on demand)
├── MEMORY_INTELLIGENCE.md ← domain knowledge (load on demand)
└── MEMORY_REFERENCE.md ← lessons learned, roadmap (load on demand)
Session start prompt for your AI tool:
Read: .context-router/CORE.md
Read: .context-router/memory/MEMORY.md
Read: .context-router/memory/MEMORY_MAP.md
Then paste: context-router ask "your task" --file path/to/file
For quick/simple tasks use CORE_LITE.md instead of CORE.md.
Load MEMORY_CHANGELOG.md only when debugging old behavior.
Load MEMORY_INTELLIGENCE.md only for domain-specialist tasks.
Initialized. 3 agents registered.
3. Route a task
context-router ask "fix the auth token expiry bug" --file src/auth/token.py
Agent: backend-engineer
Files: src/auth/token.py, src/auth/session.py
Prompt:
Read: agents/backend-engineer.agent.yaml
Task: fix the auth token expiry bug
Touch only: src/auth/token.py, src/auth/session.py
Do not modify: src/api/routes.py, src/db/models.py
Without --file, context-router keyword-matches your task against agent descriptions:
context-router ask "authentication is broken"
Agent: backend-engineer
Files: src/auth/*.py, src/api/*.py, src/db/*.py
Prompt:
Read: agents/backend-engineer.agent.yaml
Task: authentication is broken
Touch only: src/auth/*.py, src/api/*.py, src/db/*.py
Do not modify: src/ui/*.tsx, src/infra/*.sh
4. Validate a diff
context-router validate --staged # checks git diff --cached
context-router validate --diff my.patch # checks a saved diff file
Loads .context-router/validator.yaml and runs all matching rules against the diff.
Exits 0 on PASS, 1 on FAIL.
STATUS: FAIL
REASON: 'reader.readtext' used outside `with _ocr_lock:` block
RETRY_WITH:
FIX_HINT: Wrap reader.readtext() inside `with _ocr_lock:`
Rule types: lock_guard, pair_call, no_output, line_count, threshold_drift.
See .context-router/validator.yaml (generated by context-router init) for full field reference.
Usage — run command
Manual mode (no API key needed)
context-router run "fix the login form" --file src/frontend/login.js
─────────────────────────────────────
Agent: frontend
Prompt: .context-router/current-task.md
─────────────────────────────────────
1. Paste the prompt into your AI tool
2. Save the diff output as:
.context-router/output.diff
3. Run: context-router run --continue
─────────────────────────────────────
Auto mode (API key in .env)
cp .env.example .env
# add your key to .env
context-router run "fix the login form" --file src/frontend/login.js
Auto mode — using anthropic (claude-sonnet-4-6)
Attempt 1/3...
STATUS: PASS
Apply the diff to your codebase.
Override model
context-router run "task" --file path --model claude-opus-4-6
Meta-controller retry loop
MetaController wraps any agent/validator pair with a failure-aware retry loop.
from context_router.meta_controller import MetaController
from pathlib import Path
mc = MetaController(
task="fix the token expiry bug",
root=Path("."),
config_path=Path(".context-router/retry_config.yaml"),
)
result = mc.run(agent_runner, validator)
# result = {"passed": True/False, "attempts": N, "report_path": None | "logs/..."}
agent_runner(task, prompt_patches, param_patches) → str
validator(output) → (bool passed, str fail_text)
On FAIL, the controller:
- Stashes working tree (
git stash) - Builds a retry plan from
retry_config.yaml(prompt constraints + param overrides) - Re-runs the agent with accumulated patches
- On
retry_with: human— escalates immediately, writes failure report - After MAX_RETRIES (3) — restores working tree, writes report to
logs/
retry_config.yaml example:
categories: [system, logic, output, cross_agent]
prompt_patches:
logic:
2: "add inline comments explaining each change"
3: "minimal fix only — change one thing at a time"
category_map:
my_rule_id: logic
human_hints:
logic: "Logic error — review the change manually."
See examples/reel-engine/retry_config.yaml for a full real-world example.
Agent YAML format
name: string # unique identifier, used in output
owned_paths: # glob patterns — files this agent is responsible for
- src/auth/*.py
- src/api/*.py
description: one sentence # used for keyword fallback matching when no --file given
Adding a new agent
- Create
agents/<name>.agent.yaml - Run
context-router init
That's it.
How it works
context-router init
└── scans agents/*.agent.yaml
└── writes .context-router/project_map.json {glob → agent_name}
context-router ask "task" --file src/auth/token.py
└── loads project_map.json
└── matches file path against globs
└── prints structured prompt block
└── no network, no LLM, no side effects
Optional: graphify
graphify builds an AST-based knowledge graph of your codebase. Zero API cost. Run it after every code change:
graphify update .
Output: graphify-out/GRAPH_REPORT.md — node/edge/community structure for your codebase.
How graphify integrates with context-router
Data flow:
code change
→ graphify update .
→ graphify-out/GRAPH_REPORT.md (always regenerated)
→ @memory-keeper (post-commit)
reads GRAPH_REPORT.md
updates MEMORY_MAP.md (always, after every commit)
agents during a task
→ read MEMORY_MAP.md (session start, always)
→ read GRAPH_REPORT.md (on demand only — unknown deps)
Rules:
graphify update .is always a plain shell command — no API callsGRAPH_REPORT.mdis read on demand only (not at session start)MEMORY_MAP.mdis the agent-readable ownership tablegraphify-out/files are never loaded at session start- graphify never writes to
.context-router/directly
Trigger graphify after every code change:
graphify update .
Your AI tool reads the output:
Read graphify-out/GRAPH_REPORT.md only when tracing
unknown cross-file dependencies.
Success criteria
- Install in under 2 minutes
- Understand it fully in under 5 minutes
- Add a new agent by editing one YAML file
- Reduces context size when working with any AI coding tool
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llm_context_router-0.6.0.tar.gz.
File metadata
- Download URL: llm_context_router-0.6.0.tar.gz
- Upload date:
- Size: 35.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4da17e726fca7889cf177c5b8bc90870675fe6b61cabe7084e9eeac7b9f658d9
|
|
| MD5 |
4ce9f111b6a30e378e1efc8ea6d23e9e
|
|
| BLAKE2b-256 |
d1508b04b5e7a1f4e9e099a9582c1293df9817acd7eb0f99012bca5497267924
|
File details
Details for the file llm_context_router-0.6.0-py3-none-any.whl.
File metadata
- Download URL: llm_context_router-0.6.0-py3-none-any.whl
- Upload date:
- Size: 24.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f0b2c7cfbcee5355779e05ef966050a1b969d4481c016e1cb5fc7b0e9f144c9
|
|
| MD5 |
5f26db2dc07940988e9e5516147e3844
|
|
| BLAKE2b-256 |
8a3cffcffb5a80ae7b2c06d1f38606942f6135b05b89bda4daf8f85ccf97de3f
|