The context router loads keywords from a project-local config file, making it easy to customize for any codebase.
The scripts will work immediately with minimal setup:
- They'll detect file mentions from your actual messages
- Co-activation will happen based on file proximity in
.claude/structure - Token savings will still be 50-70% without customization
But for 80-95% savings: Customize keywords to match your domain.
Create .claude/keywords.json in your project root:
{
"keywords": {
"systems/production.md": [
"prod", "production", "deploy", "kubernetes", "k8s"
],
"systems/staging.md": [
"staging", "test env", "qa", "integration tests"
],
"modules/auth.md": [
"auth", "authentication", "login", "oauth", "jwt", "session"
],
"modules/database.md": [
"database", "postgres", "sql", "migrations", "schema"
],
"integrations/stripe.md": [
"stripe", "payment", "billing", "subscription"
]
},
"co_activation": {
"modules/auth.md": [
"modules/api.md",
"modules/database.md"
],
"integrations/stripe.md": [
"modules/api.md"
]
},
"pinned": [
"systems/network.md"
]
}The router checks for config in this order:
.claude/keywords.json(project-local)~/.claude/keywords.json(global fallback)- Empty defaults (no activation)
cp ~/.claude-cognitive/templates/keywords.json.example .claude/keywords.jsonFirst, list what you have:
ls .claude/systems/
ls .claude/modules/
ls .claude/integrations/Example output:
systems/production.md
systems/staging.md
modules/auth.md
modules/api.md
modules/database.md
integrations/stripe.md
For each file, ask: "What words would make me want to see this file?"
Example: modules/auth.md
- Direct mentions: "auth", "authentication", "login"
- Related concepts: "oauth", "jwt", "session", "token"
- Technical terms: "passport.js", "bcrypt", "password reset"
- Common questions: "how do users log in", "session management"
{
"keywords": {
"systems/production.md": [
"prod", "production", "deploy", "kubernetes", "k8s", "live"
],
"systems/staging.md": [
"staging", "test", "qa", "integration", "pre-prod"
],
"modules/auth.md": [
"auth", "authentication", "login", "oauth", "jwt", "session",
"passport", "bcrypt", "password", "reset", "signup", "signin"
],
"modules/api.md": [
"api", "endpoint", "route", "express", "fastapi", "rest",
"graphql", "controller", "handler"
],
"modules/database.md": [
"database", "db", "postgres", "sql", "orm", "sequelize",
"migration", "schema", "query", "models"
],
"integrations/stripe.md": [
"stripe", "payment", "billing", "subscription", "checkout",
"webhook", "invoice", "customer"
]
},
"co_activation": {
"modules/auth.md": [
"modules/api.md",
"modules/database.md"
],
"integrations/stripe.md": [
"modules/api.md",
"modules/webhooks.md"
]
},
"pinned": ["systems/network.md"]
}The co_activation section defines which files boost each other when one activates:
{
"co_activation": {
"modules/auth.md": [
"modules/api.md",
"modules/database.md"
],
"integrations/stripe.md": [
"modules/api.md",
"modules/webhooks.md"
]
}
}When auth.md activates (score = 1.0), api.md and database.md get a +0.35 boost.
Files in the pinned array never decay below WARM:
{
"pinned": [
"systems/network.md",
"systems/architecture.md"
]
}Use for:
- System architecture overview
- Critical topology diagrams
- Shared infrastructure everyone needs
Don't overuse: 2-3 files max recommended
Decay rates are still configured in the script itself. Edit ~/.claude/scripts/context-router-v2.py:
DECAY_RATES = {
"systems/": 0.85, # Infrastructure is stable
"modules/": 0.70, # Code changes frequently
"integrations/": 0.80, # APIs semi-stable
"docs/": 0.75, # Documentation medium
"default": 0.70
}Higher number = slower decay (file stays relevant longer)
Start Claude Code and say:
I need to debug the authentication flow
Then check if modules/auth.md activated:
tail -20 ~/.claude/context_injection.logShould see:
[HOT] modules/auth.md (score: 1.00)
If you mention auth, related files should warm up:
Show me how authentication works
Check log:
[HOT] modules/auth.md (score: 1.00)
[WARM] modules/api.md (score: 0.35)
[WARM] modules/database.md (score: 0.35)
In subsequent messages without mentioning auth:
How does the frontend work?
Auth should decay:
[WARM] modules/auth.md (score: 0.70) # 1.0 * 0.70 decay
{
"keywords": {
"systems/frontend.md": [
"frontend", "react", "vue", "ui", "component", "css"
],
"systems/backend.md": [
"backend", "api", "server", "node", "express", "django"
],
"modules/auth.md": [
"auth", "login", "jwt", "session"
],
"modules/database.md": [
"database", "postgres", "sql", "orm"
]
}
}{
"keywords": {
"systems/user-service.md": [
"user service", "users", "accounts", "profiles"
],
"systems/payment-service.md": [
"payment", "billing", "stripe", "transactions"
],
"integrations/kafka.md": [
"kafka", "event bus", "messaging", "queue"
]
}
}{
"keywords": {
"modules/ingestion.md": [
"ingestion", "data collection", "sources", "extract"
],
"modules/transformation.md": [
"transform", "etl", "clean", "normalize"
],
"modules/storage.md": [
"storage", "s3", "data lake", "warehouse"
]
}
}- Include common variations: "auth", "authentication", "login"
- Add technical terms: "jwt", "oauth", "bcrypt"
- Include error messages: "401", "unauthorized", "invalid token"
- Think like your questions: "how do users log in"
- Use overly generic words ("the", "system", "code")
- Duplicate keywords across unrelated files
- Add keywords just to have more (quality > quantity)
Check your keyword mapping:
# From project root
python3 -c "
import json
from pathlib import Path
config_path = Path('.claude/keywords.json')
if config_path.exists():
config = json.load(open(config_path))
keywords = config.get('keywords', {})
co_activation = config.get('co_activation', {})
pinned = config.get('pinned', [])
print('Files mapped:', len(keywords))
print('\nKeywords per file:')
for file, kws in sorted(keywords.items()):
print(f' {file}: {len(kws)} keywords')
print('\nCo-activations:')
for file, related in sorted(co_activation.items()):
print(f' {file} -> {len(related)} related files')
print('\nPinned files:', pinned)
else:
print('No .claude/keywords.json found')
"Recustomize when:
- Adding new files to
.claude/ - Files aren't activating when you expect
- Frequently typing the same thing without file activation
- Token usage higher than expected
Don't customize if:
- It's working well
- You just set it up (give it time)
- Making it perfect (good enough is fine)
If keywords aren't working:
- Check logs:
tail -f ~/.claude/context_injection.log - Verify file paths match
.claude/structure - Try more specific keywords
- Post in GitHub Discussions with example
If co-activation isn't working:
- Check
co_activationin yourkeywords.json - Verify file names match exactly
- Start with direct mentions first
Project-local config makes customization easy.
You'll still get 50-70% token savings without customization. Customization gets you to 80-95%.
Start simple. Iterate based on actual usage. Perfection isn't required.