Skip to content

Commit e680c49

Browse files
feat: v0.6.0 — inline context injection, 13→5 tools (#23)
* feat: v0.6.0 — inline context injection, 13→5 tools, MCP resources + prompts Replace indirect 3-line CLAUDE.md pointer with rich inline context injection (architecture, risk map, directives) between <!-- codecortex:start/end --> markers. Reduces MCP tools from 13 to 5 proven, irreplaceable ones. Adds 3 MCP resources and 2 MCP prompts. Includes coupling noise filter, static fallback paths, and new `inject` CLI command. Changes: - NEW: src/core/context-injection.ts — generates ~60-80 line inline Markdown - NEW: src/cli/commands/inject.ts — standalone CLI command - NEW: src/mcp/resources.ts — 3 MCP resources (overview, hotspots, module/{name}) - NEW: src/mcp/prompts.ts — 2 MCP prompts (start_session, before_editing) - NEW: generateHotspotsMarkdown() in temporal.ts — static hotspots.md generation - NEW: coupling noise filter (go.mod↔go.sum, Cargo pairs, golden clusters) - REMOVED: 8 MCP tools (5 read + 3 write) — agents use static files instead - REMOVED: src/mcp/tools/write.ts (0 organic usage) - 279 tests passing, tsc clean Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update README and server comment for v0.6.0 Update tool count (13→5), add MCP resources/prompts sections, inline context injection docs, inject CLI command, coupling noise filter. Rewrote "What makes it unique" and "How It Works" sections. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 66d89a7 commit e680c49

25 files changed

Lines changed: 1171 additions & 780 deletions

CLAUDE.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Persistent codebase knowledge layer for AI agents. Pre-builds architecture, depe
66
- TypeScript, ESM (`"type": "module"`)
77
- tree-sitter (native N-API) + 27 language grammar packages
88
- @modelcontextprotocol/sdk - MCP server (stdio transport)
9-
- commander - CLI (init, serve, update, status, symbols, search, modules, hotspots, hook, upgrade)
9+
- commander - CLI (init, serve, update, inject, status, symbols, search, modules, hotspots, hook, upgrade)
1010
- simple-git - git integration + temporal analysis
1111
- zod - schema validation for LLM analysis results
1212
- yaml - cortex.yaml manifest
@@ -45,16 +45,25 @@ Hybrid extraction:
4545
- `codecortex symbols [query]` - browse and filter the symbol index
4646
- `codecortex search <query>` - search across all knowledge files
4747
- `codecortex modules [name]` - list modules or deep-dive into one
48+
- `codecortex inject` - regenerate inline context in CLAUDE.md and agent config files
4849
- `codecortex hotspots` - files ranked by risk (churn + coupling + bugs)
4950
- `codecortex hook install|uninstall|status` - manage git hooks for auto-update
5051
- `codecortex upgrade` - check for and install latest version
5152

52-
## MCP Tools (13)
53-
Read (10): get_project_overview, get_module_context, get_session_briefing, search_knowledge, get_decision_history, get_dependency_graph, lookup_symbol, get_change_coupling, get_hotspots, get_edit_briefing
54-
Write (3): record_decision, update_patterns, record_observation
53+
## MCP Tools (5)
54+
get_project_overview, get_dependency_graph, lookup_symbol, get_change_coupling, get_edit_briefing
5555

56-
All read tools include `_freshness` metadata (status, lastAnalyzed, filesChangedSince, changedFiles, message).
57-
All read tools return context-safe responses (<10K chars) via truncation utilities in `src/utils/truncate.ts`.
56+
## MCP Resources (3)
57+
- `codecortex://project/overview` — constitution (architecture, risk map)
58+
- `codecortex://project/hotspots` — risk-ranked files
59+
- `codecortex://module/{name}` — module documentation (template)
60+
61+
## MCP Prompts (2)
62+
- `start_session` — constitution + latest session for context
63+
- `before_editing` — risk assessment for files you plan to edit
64+
65+
All tools include `_freshness` metadata (status, lastAnalyzed, filesChangedSince, changedFiles, message).
66+
All tools return context-safe responses (<10K chars) via truncation utilities in `src/utils/truncate.ts`.
5867

5968
## Pre-Publish Checklist
6069
Run ALL of these before `npm publish`. Do not skip any step.
@@ -72,7 +81,7 @@ Run ALL of these before `npm publish`. Do not skip any step.
7281
- **Grammar smoke test** (`parser.test.ts`): Loads every language in `LANGUAGE_LOADERS` via `parseSource()`. Catches missing packages, broken native builds, wrong require paths. This is what would have caught the tree-sitter-liquid issue.
7382
- **Version-check tests**: Update notification, cache lifecycle, PM detection, upgrade commands.
7483
- **Hook tests**: Git hook install/uninstall/status integration tests.
75-
- **MCP tests**: All 13 tools (read + write), simulation tests.
84+
- **MCP tests**: All 5 tools, resources, prompts, simulation tests.
7685

7786
### Known limitations
7887
- tree-sitter native bindings don't compile on Node 24 yet (upstream issue)
@@ -91,7 +100,7 @@ Run ALL of these before `npm publish`. Do not skip any step.
91100
src/
92101
cli/ - commander CLI (init, serve, update, status)
93102
mcp/ - MCP server + tools
94-
core/ - knowledge store (graph, modules, decisions, sessions, patterns, constitution, search, agent-instructions, freshness)
103+
core/ - knowledge store (graph, modules, decisions, sessions, patterns, constitution, search, agent-instructions, context-injection, freshness)
95104
extraction/ - tree-sitter native N-API (parser, symbols, imports, calls)
96105
git/ - git diff, history, temporal analysis
97106
types/ - TypeScript types + Zod schemas

README.md

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Every AI coding session starts with exploration — grepping, reading wrong file
2222

2323
## The Solution
2424

25-
CodeCortex eliminates the cold start. It pre-builds codebase knowledge — architecture, dependencies, risk areas, hidden coupling — so agents skip the exploration phase and go straight to the right files.
25+
CodeCortex eliminates the cold start. It pre-builds codebase knowledge — architecture, dependencies, risk areas, hidden coupling — and injects it directly into your agent's context (CLAUDE.md, .cursorrules, etc.) so agents have project knowledge from the first prompt.
2626

2727
**Not a middleware. Not a proxy. Just knowledge your agent loads on day one.**
2828

@@ -43,7 +43,7 @@ Three capabilities no other tool provides:
4343

4444
2. **Risk scores** — File X has been bug-fixed 7 times, has 6 hidden dependencies, and co-changes with 3 other files. Risk score: 35. You can't learn this from reading code.
4545

46-
3. **Cross-session memory**Decisions, patterns, observations persist. The agent doesn't start from zero each session.
46+
3. **Inline context injection**Project knowledge is injected directly into CLAUDE.md, .cursorrules, and other agent config files with architecture, risk map, and editing directives. Agents use it without any setup.
4747

4848
**Example from a real codebase:**
4949
- `schema.help.ts` and `schema.labels.ts` co-changed in 12/14 commits (86%) with **zero imports between them**
@@ -61,8 +61,8 @@ npm install -g codecortex-ai --legacy-peer-deps
6161
cd /path/to/your-project
6262
codecortex init
6363

64-
# Check knowledge freshness
65-
codecortex status
64+
# Regenerate inline context in CLAUDE.md and agent config files
65+
codecortex inject
6666
```
6767

6868
### Connect to Claude Code
@@ -101,7 +101,7 @@ Add to `.cursor/mcp.json`:
101101

102102
## What Gets Generated
103103

104-
All knowledge lives in `.codecortex/` as flat files in your repo:
104+
All knowledge lives in `.codecortex/` as flat files in your repo, plus inline context is injected into agent config files:
105105

106106
```
107107
.codecortex/
@@ -111,11 +111,16 @@ All knowledge lives in `.codecortex/` as flat files in your repo:
111111
graph.json # dependency graph (imports, calls, modules)
112112
symbols.json # full symbol index (functions, classes, types...)
113113
temporal.json # git coupling, hotspots, bug history
114+
hotspots.md # risk-ranked files (static, always available)
114115
AGENT.md # tool usage guide for AI agents
115116
modules/*.md # per-module structural analysis
116117
decisions/*.md # architectural decision records
117118
sessions/*.md # session change logs
118119
patterns.md # coding patterns and conventions
120+
121+
CLAUDE.md # ← inline context injected here
122+
.cursorrules # ← and here (if exists)
123+
.windsurfrules # ← and here (if exists)
119124
```
120125

121126
## Six Knowledge Layers
@@ -129,37 +134,34 @@ All knowledge lives in `.codecortex/` as flat files in your repo:
129134
| 5. Patterns | How code is written here | `patterns.md` |
130135
| 6. Sessions | What changed between sessions | `sessions/*.md` |
131136

132-
## MCP Tools (13)
137+
## MCP Tools (5)
133138

134-
### Navigation — "Where should I look?" (4 tools)
139+
Five focused tools that provide capabilities agents can't get from reading code:
135140

136141
| Tool | Description |
137142
|------|-------------|
138143
| `get_project_overview` | Architecture, modules, risk map. Call this first. |
139-
| `search_knowledge` | Find where a function/class/type is DEFINED by name. Ranked results. |
144+
| `get_dependency_graph` | Import/export graph filtered by module or file. |
140145
| `lookup_symbol` | Precise symbol lookup with kind and file path filters. |
141-
| `get_module_context` | Module files, deps, temporal signals. Zoom into a module. |
146+
| `get_change_coupling` | Files that must change together. Hidden dependencies flagged. |
147+
| `get_edit_briefing` | Pre-edit risk: co-change warnings, hidden deps, bug history. **Always call before editing.** |
142148

143-
### Risk — "What could go wrong?" (4 tools)
149+
### MCP Resources (3)
144150

145-
| Tool | Description |
146-
|------|-------------|
147-
| `get_edit_briefing` | Pre-edit risk: co-change warnings, hidden deps, bug history. **Always call before editing.** |
148-
| `get_hotspots` | Files ranked by risk (churn x coupling x bugs). |
149-
| `get_change_coupling` | Files that must change together. Hidden dependencies flagged. |
150-
| `get_dependency_graph` | Import/export graph filtered by module or file. |
151+
Static knowledge available without tool calls:
151152

152-
### Memory — "Remember this" (5 tools)
153+
| Resource | Description |
154+
|----------|-------------|
155+
| `codecortex://project/overview` | Full project constitution |
156+
| `codecortex://project/hotspots` | Risk-ranked file table |
157+
| `codecortex://module/{name}` | Per-module documentation |
153158

154-
| Tool | Description |
155-
|------|-------------|
156-
| `get_session_briefing` | What changed since the last session. |
157-
| `get_decision_history` | Why things were built this way. |
158-
| `record_decision` | Save an architectural decision. |
159-
| `update_patterns` | Document coding conventions. |
160-
| `record_observation` | Record anything you learned about the codebase. |
159+
### MCP Prompts (2)
161160

162-
All read tools include `_freshness` metadata and return context-safe responses (<10K chars) via size-adaptive caps.
161+
| Prompt | Description |
162+
|--------|-------------|
163+
| `start_session` | Returns constitution + latest session context |
164+
| `before_editing` | Takes file paths, returns risk/coupling/bug briefing |
163165

164166
## CLI Commands
165167

@@ -168,6 +170,7 @@ All read tools include `_freshness` metadata and return context-safe responses (
168170
| `codecortex init` | Discover project + extract symbols + analyze git history |
169171
| `codecortex serve` | Start MCP server (stdio transport) |
170172
| `codecortex update` | Re-extract changed files, update affected modules |
173+
| `codecortex inject` | Regenerate inline context in CLAUDE.md and agent config files |
171174
| `codecortex status` | Show knowledge freshness, stale modules, symbol counts |
172175
| `codecortex symbols [query]` | Browse and filter the symbol index |
173176
| `codecortex search <query>` | Search across symbols, file paths, and docs |
@@ -180,6 +183,8 @@ All read tools include `_freshness` metadata and return context-safe responses (
180183

181184
**Hybrid extraction:** tree-sitter native N-API for structure (symbols, imports, calls across 27 languages) + host LLM for semantics (what modules do, why they're built that way). Zero extra API keys.
182185

186+
**Inline context injection:** After analysis, CodeCortex injects a rich knowledge section directly into CLAUDE.md and other agent config files. This includes architecture overview, risk map with coupled file names, and editing directives — so agents have project context from the first prompt without needing MCP.
187+
183188
**Git hooks** keep knowledge fresh — `codecortex update` runs automatically on every commit, re-extracting changed files and updating temporal analysis.
184189

185190
**Size-adaptive responses** — CodeCortex classifies your project (micro → extra-large) and adjusts response caps accordingly. A 23-file project gets full detail. A 6,400-file project gets intelligent summaries. Every MCP tool response stays under 10K chars.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codecortex-ai",
3-
"version": "0.5.0",
3+
"version": "0.6.0",
44
"description": "Persistent codebase knowledge layer for AI agents — architecture, dependencies, coupling, and risk served via MCP",
55
"type": "module",
66
"bin": {

src/cli/commands/init.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { writeFile, writeJsonStream, ensureDir, cortexPath } from '../../utils/f
1414
import { readFile } from 'node:fs/promises'
1515
import { generateStructuralModuleDocs } from '../../core/module-gen.js'
1616
import { generateAgentInstructions } from '../../core/agent-instructions.js'
17+
import { generateHotspotsMarkdown } from '../../git/temporal.js'
1718
import { createDecision, writeDecision, listDecisions } from '../../core/decisions.js'
1819
import type { SymbolRecord, ImportEdge, CallEdge, SymbolIndex, ProjectInfo } from '../../types/index.js'
1920

@@ -40,6 +41,7 @@ export async function initCommand(opts: { root: string; days: string }): Promise
4041
const allImports: ImportEdge[] = []
4142
const allCalls: CallEdge[] = []
4243
let extractionErrors = 0
44+
const langStats = new Map<string, { files: number; symbols: number }>()
4345

4446
let parsed = 0
4547
const parseable = project.files.filter(f => languageFromPath(f.path)).length
@@ -49,6 +51,9 @@ export async function initCommand(opts: { root: string; days: string }): Promise
4951
const lang = languageFromPath(file.path)
5052
if (!lang) continue
5153

54+
const stats = langStats.get(lang) || { files: 0, symbols: 0 }
55+
stats.files++
56+
5257
try {
5358
const tree = await parseFile(file.absolutePath, lang)
5459
const source = await readFile(file.absolutePath, 'utf-8')
@@ -57,12 +62,14 @@ export async function initCommand(opts: { root: string; days: string }): Promise
5762
const imports = extractImports(tree, file.path, lang)
5863
const calls = extractCalls(tree, file.path, lang)
5964

65+
stats.symbols += symbols.length
6066
allSymbols.push(...symbols)
6167
allImports.push(...imports)
6268
allCalls.push(...calls)
6369
} catch {
6470
extractionErrors++
6571
}
72+
langStats.set(lang, stats)
6673
parsed++
6774
if (showProgress && parsed % 5000 === 0) {
6875
process.stdout.write(`\r Progress: ${parsed}/${parseable} files (${allSymbols.length} symbols)`)
@@ -74,6 +81,13 @@ export async function initCommand(opts: { root: string; days: string }): Promise
7481
if (extractionErrors > 0) {
7582
console.log(` (${extractionErrors} files skipped due to parse errors)`)
7683
}
84+
85+
// Warn about languages with 0 symbols extracted
86+
for (const [lang, stats] of langStats) {
87+
if (stats.files > 0 && stats.symbols === 0) {
88+
console.log(` \u26a0 Warning: ${lang} \u2014 ${stats.files} files parsed, 0 symbols extracted. Grammar may not support this language.`)
89+
}
90+
}
7791
console.log('')
7892

7993
// Step 3: Build dependency graph
@@ -140,9 +154,10 @@ export async function initCommand(opts: { root: string; days: string }): Promise
140154
// Write graph.json
141155
await writeGraph(root, graph)
142156

143-
// Write temporal.json
157+
// Write temporal.json + hotspots.md
144158
if (temporalData) {
145159
await writeFile(cortexPath(root, 'temporal.json'), JSON.stringify(temporalData, null, 2))
160+
await writeFile(cortexPath(root, 'hotspots.md'), generateHotspotsMarkdown(temporalData))
146161
}
147162

148163
// Write overview.md — compact summary only (no raw file listing)
@@ -162,7 +177,7 @@ export async function initCommand(opts: { root: string; days: string }): Promise
162177
await writeManifest(root, manifest)
163178

164179
// Write patterns.md (empty template)
165-
await writeFile(cortexPath(root, 'patterns.md'), '# Coding Patterns\n\nNo patterns recorded yet. Use `update_patterns` to add patterns.\n')
180+
await writeFile(cortexPath(root, 'patterns.md'), '# Coding Patterns\n\nNo patterns recorded yet. Edit this file directly to add patterns.\n')
166181

167182
// Generate structural module docs
168183
const moduleDocsGenerated = await generateStructuralModuleDocs(root, {
@@ -185,8 +200,8 @@ export async function initCommand(opts: { root: string; days: string }): Promise
185200
console.log(' Written: constitution.md')
186201
console.log('')
187202

188-
// Step 7: Agent onboarding
189-
console.log('Step 7/7: Generating agent instructions...')
203+
// Step 7: Agent onboarding + inline context injection
204+
console.log('Step 7/7: Generating inline context...')
190205
const updatedFiles = await generateAgentInstructions(root)
191206

192207
// Seed a starter decision (skip if decisions already exist)

src/cli/commands/inject.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { resolve } from 'node:path'
2+
import { existsSync } from 'node:fs'
3+
import { cortexPath } from '../../utils/files.js'
4+
import { injectAllAgentFiles } from '../../core/context-injection.js'
5+
6+
export async function injectCommand(opts: { root: string }): Promise<void> {
7+
const root = resolve(opts.root)
8+
9+
if (!existsSync(cortexPath(root, 'cortex.yaml'))) {
10+
console.error('Error: No CodeCortex knowledge found. Run `codecortex init` first.')
11+
process.exitCode = 1
12+
return
13+
}
14+
15+
console.log('Regenerating inline context...')
16+
const updated = await injectAllAgentFiles(root)
17+
18+
if (updated.length === 0) {
19+
console.log(' All agent config files are already up to date.')
20+
} else {
21+
for (const file of updated) {
22+
console.log(` Updated: ${file}`)
23+
}
24+
}
25+
console.log('')
26+
console.log('Done. Agent config files now contain inline project knowledge.')
27+
}

src/cli/commands/update.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { generateConstitution } from '../../core/constitution.js'
1616
import { createSession, writeSession, getLatestSession } from '../../core/sessions.js'
1717
import { readFile as fsRead } from 'node:fs/promises'
1818
import { generateStructuralModuleDocs } from '../../core/module-gen.js'
19+
import { generateHotspotsMarkdown } from '../../git/temporal.js'
20+
import { injectAllAgentFiles } from '../../core/context-injection.js'
1921
import type { SymbolRecord, ImportEdge, CallEdge, SymbolIndex } from '../../types/index.js'
2022

2123
export async function updateCommand(opts: { root: string; days: string }): Promise<void> {
@@ -100,6 +102,7 @@ export async function updateCommand(opts: { root: string; days: string }): Promi
100102
await writeGraph(root, graph)
101103
if (temporalData) {
102104
await writeFile(cortexPath(root, 'temporal.json'), JSON.stringify(temporalData, null, 2))
105+
await writeFile(cortexPath(root, 'hotspots.md'), generateHotspotsMarkdown(temporalData))
103106
}
104107

105108
// Generate structural module docs (skip existing)
@@ -125,6 +128,9 @@ export async function updateCommand(opts: { root: string; days: string }): Promi
125128
temporal: temporalData,
126129
})
127130

131+
// Refresh inline context in agent config files
132+
await injectAllAgentFiles(root)
133+
128134
// Create session log
129135
const diff = await getUncommittedDiff(root).catch(() => ({ filesChanged: [], summary: 'no changes' }))
130136
const previousSession = await getLatestSession(root)

src/cli/grouped-help.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Command, Help } from 'commander'
22

33
const COMMAND_GROUPS: Array<{ title: string; commands: string[] }> = [
4-
{ title: 'Core', commands: ['init', 'serve', 'update', 'status'] },
4+
{ title: 'Core', commands: ['init', 'serve', 'update', 'inject', 'status'] },
55
{ title: 'Query', commands: ['symbols', 'search', 'modules', 'hotspots'] },
66
{ title: 'Utility', commands: ['hook', 'upgrade'] },
77
]

src/cli/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Command } from 'commander'
55
import { initCommand } from './commands/init.js'
66
import { serveCommand } from './commands/serve.js'
77
import { updateCommand } from './commands/update.js'
8+
import { injectCommand } from './commands/inject.js'
89
import { statusCommand } from './commands/status.js'
910
import { symbolsCommand } from './commands/symbols.js'
1011
import { searchCommand } from './commands/search.js'
@@ -51,6 +52,12 @@ program
5152
.option('-d, --days <number>', 'Days of git history to re-analyze', '90')
5253
.action(updateCommand)
5354

55+
program
56+
.command('inject')
57+
.description('Regenerate inline context in CLAUDE.md and agent config files')
58+
.option('-r, --root <path>', 'Project root directory', process.cwd())
59+
.action(injectCommand)
60+
5461
program
5562
.command('status')
5663
.description('Show knowledge freshness and symbol counts')

0 commit comments

Comments
 (0)