Remove Go-era cruft, update THIRD_PARTY.md for pure C project

- Delete cmd/codebase-memory-mcp/assets/ — skills and codex instructions
  are embedded as C string literals in src/cli/cli.c since v0.5.0
- Move BENCHMARK.md to docs/ to reduce root clutter
- Fix setup scripts: replace stale go build with scripts/build.sh
- THIRD_PARTY.md: replace Go module dependencies with vendored C
  libraries (sqlite3, mimalloc, mongoose, yyjson, xxhash, tre),
  fix CGo reference to static compilation
This commit is contained in:
Martin Vogel committed 2026-03-22 01:09:12 +01:00
1 parent e080233b09
commit c38853f999
9 files changed
+14 -522

No files matched your search

+12 -10
View File
@@ -15,7 +15,7 @@ The tree-sitter C runtime is vendored in `internal/cbm/vendored/ts_runtime/`.
Pre-generated parser sources are vendored in `internal/cbm/vendored/grammars/<lang>/`.
Each grammar is the work of its upstream authors; we vendor only the generated
`parser.c` (and `scanner.c` where applicable) for CGo compilation.
`parser.c` (and `scanner.c` where applicable) for static compilation.
| Grammar | Upstream Repository | License | Copyright |
|---------|-------------------|---------|-----------|
@@ -84,16 +84,18 @@ Each grammar is the work of its upstream authors; we vendor only the generated
| yaml | [tree-sitter/tree-sitter-yaml](https://github.com/tree-sitter/tree-sitter-yaml) | MIT | (c) Max Brunsfeld |
| zig | [tree-sitter/tree-sitter-zig](https://github.com/tree-sitter/tree-sitter-zig) | MIT | (c) Max Brunsfeld |
## Go Module Dependencies
## Vendored C Libraries
| Module | License | Project |
|--------|---------|---------|
| github.com/mattn/go-sqlite3 | MIT | [mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) |
| github.com/modelcontextprotocol/go-sdk | MIT | [modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) |
| github.com/zeebo/xxh3 | BSD-2-Clause | [zeebo/xxh3](https://github.com/zeebo/xxh3) |
| golang.org/x/sync | BSD-3-Clause | [golang.org/x/sync](https://pkg.go.dev/golang.org/x/sync) |
| golang.org/x/sys | BSD-3-Clause | [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) |
| gopkg.in/yaml.v3 | MIT + Apache-2.0 | [go-yaml/yaml](https://github.com/go-yaml/yaml) |
All C dependencies are vendored in `vendored/` — zero system library dependencies required.
| Library | License | Project |
|---------|---------|---------|
| SQLite 3 | Public Domain | [sqlite.org](https://www.sqlite.org/) |
| mimalloc | MIT | [microsoft/mimalloc](https://github.com/microsoft/mimalloc) |
| Mongoose | Dual GPLv2 / Commercial | [cesanta/mongoose](https://github.com/cesanta/mongoose) |
| yyjson | MIT | [ibireme/yyjson](https://github.com/ibireme/yyjson) |
| xxHash | BSD-2-Clause | [Cyan4973/xxHash](https://github.com/Cyan4973/xxHash) |
| TRE | BSD-2-Clause | [laurikari/tre](https://github.com/laurikari/tre) |
## Notes
@@ -1,34 +0,0 @@
# Codebase Knowledge Graph
This project has a code knowledge graph available via MCP tools. Use it for
structural questions instead of grep — one graph query returns what would take
dozens of file-by-file searches.
## Finding Code
- "Who calls X?" → use `trace_call_path` with `direction=inbound`
- "What does X call?" → use `trace_call_path` with `direction=outbound`
- "Find functions matching pattern" → use `search_graph` with `name_pattern`
- "Find all routes" → use `search_graph` with `label=Route`
- "Show codebase structure" → use `get_graph_schema` for overview
## Tracing Dependencies
- Always discover exact names first: `search_graph(name_pattern=".*Partial.*")`
- Then trace: `trace_call_path(function_name="ExactName", direction="both")`
- Cross-service HTTP calls: `query_graph("MATCH (a)-[r:HTTP_CALLS]->(b) RETURN a.name, b.name, r.url_path")`
- Read source: `get_code_snippet(qualified_name="project.path.FunctionName")`
## Quality Analysis
- Dead code: `search_graph` with `max_degree=0`, `exclude_entry_points=true`, `relationship=CALLS`, `direction=inbound`
- High fan-out: `search_graph` with `min_degree=10`, `relationship=CALLS`, `direction=outbound`
- Change coupling: `query_graph("MATCH (a)-[r:FILE_CHANGES_WITH]->(b) WHERE r.coupling_score >= 0.5 RETURN ...")`
## Important
- Always check `list_projects` first — run `index_repository` if the project is missing
- Use `search_graph` to discover exact names before `trace_call_path` (it requires exact match)
- The graph doesn't index text content — use grep for string literals, error messages, config values
- Results default to 10 per page — check `has_more` and use `offset` to paginate
- Use `project` parameter when multiple repos are indexed
@@ -1,90 +0,0 @@
---
name: codebase-memory-exploring
description: >
This skill should be used when the user asks to "explore the codebase",
"understand the architecture", "what functions exist", "show me the structure",
"how is the code organized", "find functions matching", "search for classes",
"list all routes", "show API endpoints", or needs codebase orientation.
---
# Codebase Exploration via Knowledge Graph
Use graph tools for structural code questions. They return precise results in ~500 tokens vs ~80K for grep-based exploration.
## Workflow
### Step 1: Check if project is indexed
```
list_projects
```
If the project is missing from the list:
```
index_repository(repo_path="/path/to/project")
```
If already indexed, skip — auto-sync keeps the graph fresh.
### Step 2: Get a structural overview
```
get_graph_schema
```
This returns node label counts (functions, classes, routes, etc.), edge type counts, and relationship patterns. Use it to understand what's in the graph before querying.
### Step 3: Find specific code elements
Find functions by name pattern:
```
search_graph(label="Function", name_pattern=".*Handler.*")
```
Find classes:
```
search_graph(label="Class", name_pattern=".*Service.*")
```
Find all REST routes:
```
search_graph(label="Route")
```
Find modules/packages:
```
search_graph(label="Module")
```
Scope to a specific directory:
```
search_graph(label="Function", qn_pattern=".*services\\.order\\..*")
```
### Step 4: Read source code
After finding a function via search, read its source:
```
get_code_snippet(qualified_name="project.path.to.FunctionName")
```
### Step 5: Understand structure
For file/directory exploration within the indexed project:
```
list_directory(path="src/services")
```
## When to Use Grep Instead
- Searching for **string literals** or error messages → `search_code` or Grep
- Finding a file by exact name → Glob
- The graph doesn't index text content, only structural elements
## Key Tips
- Results default to 10 per page. Check `has_more` and use `offset` to paginate.
- Use `project` parameter when multiple repos are indexed.
- Route nodes have a `properties.handler` field with the actual handler function name.
- `exclude_labels` removes noise (e.g., `exclude_labels=["Route"]` when searching by name pattern).
@@ -1,101 +0,0 @@
---
name: codebase-memory-quality
description: >
This skill should be used when the user asks about "dead code",
"find dead code", "detect dead code", "show dead code", "dead code analysis",
"unused functions", "find unused functions", "unreachable code",
"identify high fan-out functions", "find complex functions",
"code quality audit", "find functions nobody calls",
"reduce codebase size", "refactor candidates", "cleanup candidates",
or needs code quality analysis.
---
# Code Quality Analysis via Knowledge Graph
Use graph degree filtering to find dead code, high-complexity functions, and refactor candidates — all in single tool calls.
## Workflow
### Dead Code Detection
Find functions with zero inbound CALLS edges, excluding entry points:
```
search_graph(
label="Function",
relationship="CALLS",
direction="inbound",
max_degree=0,
exclude_entry_points=true
)
```
`exclude_entry_points=true` removes route handlers, `main()`, and framework-registered functions that have zero callers by design.
### Verify Dead Code Candidates
Before deleting, verify each candidate truly has no callers:
```
trace_call_path(function_name="SuspectFunction", direction="inbound", depth=1)
```
Also check for read references (callbacks, stored in variables):
```
query_graph(query="MATCH (a)-[r:USAGE]->(b) WHERE b.name = 'SuspectFunction' RETURN a.name, a.file_path LIMIT 10")
```
### High Fan-Out Functions (calling 10+ others)
These are often doing too much and are refactor candidates:
```
search_graph(
label="Function",
relationship="CALLS",
direction="outbound",
min_degree=10
)
```
### High Fan-In Functions (called by 10+ others)
These are critical functions — changes have wide impact:
```
search_graph(
label="Function",
relationship="CALLS",
direction="inbound",
min_degree=10
)
```
### Files That Change Together (Hidden Coupling)
Find files with high git change coupling:
```
query_graph(query="MATCH (a)-[r:FILE_CHANGES_WITH]->(b) WHERE r.coupling_score >= 0.5 RETURN a.name, b.name, r.coupling_score, r.co_change_count ORDER BY r.coupling_score DESC LIMIT 20")
```
High coupling between unrelated files suggests hidden dependencies.
### Unused Imports
```
search_graph(
relationship="IMPORTS",
direction="outbound",
max_degree=0,
label="Module"
)
```
## Key Tips
- `search_graph` with degree filters has no row cap (unlike `query_graph` which caps at 200).
- Use `file_pattern` to scope analysis to specific directories: `file_pattern="**/services/**"`.
- Dead code detection works best after a full index — run `index_repository` if the project was recently set up.
- Paginate results with `limit` and `offset` — check `has_more` in the response.
@@ -1,154 +0,0 @@
---
name: codebase-memory-reference
description: >
This skill should be used when the user asks about "codebase-memory-mcp tools",
"graph query syntax", "Cypher query examples", "edge types",
"how to use search_graph", "query_graph examples", or needs reference
documentation for the codebase knowledge graph tools.
---
# Codebase Memory MCP — Tool Reference
## Tools (14 total)
| Tool | Purpose |
|------|---------|
| `index_repository` | Parse and ingest repo into graph (only once — auto-sync keeps it fresh) |
| `index_status` | Check indexing status (ready/indexing/not found) |
| `list_projects` | List all indexed projects with timestamps and counts |
| `delete_project` | Remove a project from the graph |
| `search_graph` | Structured search with filters (name, label, degree, file pattern) |
| `search_code` | Grep-like text search within indexed project files |
| `trace_call_path` | BFS call chain traversal (exact name match required). Supports `risk_labels=true` for impact classification. |
| `detect_changes` | Map git diff to affected symbols + blast radius with risk scoring |
| `query_graph` | Cypher-like graph queries (200-row cap) |
| `get_graph_schema` | Node/edge counts, relationship patterns |
| `get_code_snippet` | Read source code by qualified name |
| `read_file` | Read any file from indexed project |
| `list_directory` | List files/directories with glob filter |
| `ingest_traces` | Ingest OpenTelemetry traces to validate HTTP_CALLS edges |
## Edge Types
| Type | Meaning |
|------|---------|
| `CALLS` | Direct function call within same service |
| `HTTP_CALLS` | Synchronous cross-service HTTP request |
| `ASYNC_CALLS` | Async dispatch (Cloud Tasks, Pub/Sub, SQS, Kafka) |
| `IMPORTS` | Module/package import |
| `DEFINES` / `DEFINES_METHOD` | Module/class defines a function/method |
| `HANDLES` | Route node handled by a function |
| `IMPLEMENTS` | Type implements an interface |
| `OVERRIDE` | Struct method overrides an interface method |
| `USAGE` | Read reference (callback, variable assignment) |
| `FILE_CHANGES_WITH` | Git history change coupling |
| `CONTAINS_FILE` / `CONTAINS_FOLDER` / `CONTAINS_PACKAGE` | Structural containment |
## Node Labels
`Project`, `Package`, `Folder`, `File`, `Module`, `Class`, `Function`, `Method`, `Interface`, `Enum`, `Type`, `Route`
## Qualified Name Format
`<project>.<path_parts>.<name>` — file path with `/` replaced by `.`, extension removed.
Examples:
- `myproject.cmd.server.main.HandleRequest` (Go)
- `myproject.services.orders.ProcessOrder` (Python)
- `myproject.src.components.App.App` (TypeScript)
Use `search_graph` to discover qualified names, then pass them to `get_code_snippet`.
## Cypher Subset (for query_graph)
**Supported:**
- `MATCH` with node labels and relationship types
- Variable-length paths: `-[:CALLS*1..3]->`
- `WHERE` with `=`, `<>`, `>`, `<`, `>=`, `<=`, `=~` (regex), `CONTAINS`, `STARTS WITH`
- `WHERE` with `AND`, `OR`, `NOT`
- `RETURN` with property access, `COUNT(x)`, `DISTINCT`
- `ORDER BY` with `ASC`/`DESC`
- `LIMIT`
- Edge property access: `r.confidence`, `r.url_path`, `r.coupling_score`
**Not supported:** `WITH`, `COLLECT`, `SUM`, `CREATE/DELETE/SET`, `OPTIONAL MATCH`, `UNION`
## Common Cypher Patterns
```
# Cross-service HTTP calls with confidence
MATCH (a)-[r:HTTP_CALLS]->(b) RETURN a.name, b.name, r.url_path, r.confidence LIMIT 20
# Filter by URL path
MATCH (a)-[r:HTTP_CALLS]->(b) WHERE r.url_path CONTAINS '/orders' RETURN a.name, b.name
# Interface implementations
MATCH (s)-[r:OVERRIDE]->(i) RETURN s.name, i.name LIMIT 20
# Change coupling
MATCH (a)-[r:FILE_CHANGES_WITH]->(b) WHERE r.coupling_score >= 0.5 RETURN a.name, b.name, r.coupling_score
# Functions calling a specific function
MATCH (f:Function)-[:CALLS]->(g:Function) WHERE g.name = 'ProcessOrder' RETURN f.name LIMIT 20
```
## Regex-Powered Search (No Full-Text Index Needed)
`search_graph` and `search_code` support full Go regex, making full-text search indexes unnecessary. Regex patterns provide precise, composable queries that cover all common discovery scenarios:
### search_graph — name_pattern / qn_pattern
| Pattern | Matches | Use case |
|---------|---------|----------|
| `.*Handler$` | names ending in Handler | Find all handlers |
| `(?i)auth` | case-insensitive "auth" | Find auth-related symbols |
| `get\|fetch\|load` | any of three words | Find data-loading functions |
| `^on[A-Z]` | names starting with on + uppercase | Find event handlers |
| `.*Service.*Impl` | Service...Impl pattern | Find service implementations |
| `^(Get\|Set\|Delete)` | CRUD prefixes | Find CRUD operations |
| `.*_test$` | names ending in _test | Find test functions |
| `.*\\.controllers\\..*` | qn_pattern for directory scoping | Scope to controllers dir |
### search_code — regex=true
| Pattern | Matches | Use case |
|---------|---------|----------|
| `TODO\|FIXME\|HACK` | multi-pattern scan | Find tech debt markers |
| `(?i)password\|secret\|token` | case-insensitive secrets | Security scan |
| `func\\s+Test` | Go test functions | Find test entry points |
| `api[._/]v[0-9]` | API version references | Find versioned API usage |
| `import.*from ['"]@` | scoped npm imports | Find package imports |
### Combining Filters for Surgical Queries
```
# Find unused auth handlers
search_graph(name_pattern="(?i).*auth.*handler.*", max_degree=0, exclude_entry_points=true)
# Find high fan-out functions in the services directory
search_graph(qn_pattern=".*\\.services\\..*", min_degree=10, relationship="CALLS", direction="outbound")
# Find all route handlers matching a URL pattern
search_code(pattern="(?i)(POST|PUT).*\\/api\\/v[0-9]\\/orders", regex=true)
```
## Critical Pitfalls
1. **`search_graph(relationship="HTTP_CALLS")` does NOT return edges** — it filters nodes by degree. Use `query_graph` with Cypher to see actual edges.
2. **`query_graph` has a 200-row cap** before aggregation — COUNT queries silently undercount on large codebases. Use `search_graph` with `min_degree`/`max_degree` for counting.
3. **`trace_call_path` needs exact names** — use `search_graph(name_pattern=".*Partial.*")` first to discover names.
4. **`direction="outbound"` misses cross-service callers** — use `direction="both"` for full context.
## Decision Matrix
| Question | Use |
|----------|-----|
| Who calls X? | `trace_call_path(direction="inbound")` |
| What does X call? | `trace_call_path(direction="outbound")` |
| Full call context | `trace_call_path(direction="both")` |
| Find by name pattern | `search_graph(name_pattern="...")` |
| Dead code | `search_graph(max_degree=0, exclude_entry_points=true)` |
| Cross-service edges | `query_graph` with Cypher |
| Impact of local changes | `detect_changes()` |
| Risk-classified trace | `trace_call_path(risk_labels=true)` |
| Text search | `search_code` or Grep |
@@ -1,125 +0,0 @@
---
name: codebase-memory-tracing
description: >
This skill should be used when the user asks "who calls this function",
"what does X call", "trace the call chain", "find callers of",
"show dependencies", "what depends on", "trace call path",
"find all references to", "impact analysis", or needs to understand
function call relationships and dependency chains.
---
# Call Chain Tracing via Knowledge Graph
Use graph tools to trace function call relationships. One `trace_call_path` call replaces dozens of grep searches across files.
## Workflow
### Step 1: Discover the exact function name
`trace_call_path` requires an **exact** name match. If you don't know the exact name, discover it first with regex:
```
search_graph(name_pattern=".*Order.*", label="Function")
```
Use full regex for precise discovery — no full-text search needed:
- `(?i)order` — case-insensitive
- `^(Get|Set|Delete)Order` — CRUD variants
- `.*Order.*Handler$` — handlers only
- `qn_pattern=".*services\\.order\\..*"` — scope to order service directory
This returns matching functions with their qualified names and file locations.
### Step 2: Trace callers (who calls this function?)
```
trace_call_path(function_name="ProcessOrder", direction="inbound", depth=3)
```
Returns a hop-by-hop list of all functions that call `ProcessOrder`, up to 3 levels deep.
### Step 3: Trace callees (what does this function call?)
```
trace_call_path(function_name="ProcessOrder", direction="outbound", depth=3)
```
### Step 4: Full context (both callers and callees)
```
trace_call_path(function_name="ProcessOrder", direction="both", depth=3)
```
**Always use `direction="both"` for complete context.** Cross-service HTTP_CALLS edges from other services appear as inbound edges — `direction="outbound"` alone misses them.
### Step 5: Read suspicious code
After finding interesting callers/callees, read their source:
```
get_code_snippet(qualified_name="project.path.module.FunctionName")
```
## Cross-Service HTTP Calls
To see all HTTP links between services with URLs and confidence scores:
```
query_graph(query="MATCH (a)-[r:HTTP_CALLS]->(b) RETURN a.name, b.name, r.url_path, r.confidence ORDER BY r.confidence DESC LIMIT 20")
```
Filter by URL path:
```
query_graph(query="MATCH (a)-[r:HTTP_CALLS]->(b) WHERE r.url_path CONTAINS '/orders' RETURN a.name, b.name, r.url_path")
```
## Async Dispatch (Cloud Tasks, Pub/Sub, etc.)
Find dispatch functions by name pattern, then trace:
```
search_graph(name_pattern=".*CreateTask.*|.*send_to_pubsub.*")
trace_call_path(function_name="CreateMultidataTask", direction="both")
```
## Interface Implementations
Find which structs implement an interface method:
```
query_graph(query="MATCH (s)-[r:OVERRIDE]->(i) WHERE i.name = 'Read' RETURN s.name, i.name LIMIT 20")
```
## Read References (callbacks, variable assignments)
```
query_graph(query="MATCH (a)-[r:USAGE]->(b) WHERE b.name = 'ProcessOrder' RETURN a.name, a.file_path LIMIT 20")
```
## Risk-Classified Impact Analysis
Add `risk_labels=true` to get risk classification on each node:
```
trace_call_path(function_name="ProcessOrder", direction="inbound", depth=3, risk_labels=true)
```
Returns nodes with `risk` (CRITICAL/HIGH/MEDIUM/LOW) based on hop depth, plus an `impact_summary` with counts. Risk mapping: hop 1=CRITICAL, 2=HIGH, 3=MEDIUM, 4+=LOW.
## Detect Changes (Git Diff Impact)
Map uncommitted changes to affected symbols and their blast radius:
```
detect_changes()
detect_changes(scope="staged")
detect_changes(scope="branch", base_branch="main")
```
Returns changed files, changed symbols, and impacted callers with risk classification. Scopes: `unstaged`, `staged`, `all` (default), `branch`.
## Key Tips
- Start with `depth=1` for quick answers, increase only if needed (max 5).
- Edge types in trace results: `CALLS` (direct), `HTTP_CALLS` (cross-service), `ASYNC_CALLS` (async dispatch), `USAGE` (read reference), `OVERRIDE` (interface implementation).
- `search_graph(relationship="HTTP_CALLS")` filters nodes by degree — it does NOT return edges. Use `query_graph` with Cypher to see actual edges with properties.
- Results are capped at 200 nodes per trace.
- `detect_changes` requires git in PATH.
View File
File renamed without changes.
+1 -1
View File
@@ -213,7 +213,7 @@ if ($FromSource) {
Write-Host ""
Write-Host "Building binary (this may take a minute)..." -ForegroundColor White
$wslBinaryPath = "/home/$wslUser/.local/bin/$BinaryName"
Invoke-WSL "mkdir -p /home/$wslUser/.local/bin && cd $sourceDir && CGO_ENABLED=1 go build -buildvcs=false -o $wslBinaryPath ./cmd/codebase-memory-mcp/"
Invoke-WSL "mkdir -p /home/$wslUser/.local/bin && cd $sourceDir && scripts/build.sh && cp build/c/codebase-memory-mcp $wslBinaryPath"
Write-Ok "Built to $wslBinaryPath (inside WSL)"
# Verify
+1 -7
View File
@@ -199,13 +199,7 @@ build_from_source() {
echo "${BOLD}Building binary (this may take a minute)...${RESET}"
mkdir -p "$INSTALL_DIR"
local build_flags=""
# Use -buildvcs=false in WSL (git metadata fails across filesystem boundaries)
if grep -qi microsoft /proc/version 2>/dev/null; then
build_flags="-buildvcs=false"
fi
(cd "$SOURCE_DIR" && CGO_ENABLED=1 go build $build_flags -o "${INSTALL_DIR}/${BINARY_NAME}" ./cmd/codebase-memory-mcp/)
(cd "$SOURCE_DIR" && scripts/build.sh && cp build/c/codebase-memory-mcp "${INSTALL_DIR}/${BINARY_NAME}")
ok "Built and installed to ${INSTALL_DIR}/${BINARY_NAME}"
}