AI Infrastructure
Synapse
A local code graph for AI agents. Fewer tokens spent finding the code that matters.
Intro
Synapse indexes your repositories with tree-sitter, stores a code graph in an embedded database on your machine, and serves ranked context to your IDE or agent over the Model Context Protocol (MCP). It ships as a single binary and runs on your machine.
Why I built it
I wanted to cut the tokens my LLMs spent finding code, first when they reviewed my work and later when they wrote it. I tried Graphify first. On my Swift app the savings were small, so I wrote my own.
What I measured
Three tests, all scripted, with no live agent. Tokens are estimated as characters divided by 4 over each command and its output. When a graph tool's answer is incomplete, the grep cost is added, because an agent would still need it. The grep commands were written knowing the answer, so grep is a best case. Numbers checked on November 3, 2026 against my benchmark notes and the v0.5.0 release page.
Test 1: one Swift app, 8 questions
A private Swift and SwiftUI app with 134 Swift files and 358 commits. Each question has a hand-written answer key.
| Tool | Complete answers | Estimated tokens to answer |
|---|---|---|
| grep and git | 8 of 8 | 13,125 |
| Graphify 0.9.45, code-only | 3 of 8 | 14,724 |
| Synapse, first run | 3 of 8 | 16,486 |
| Synapse, after the fixes | 7 of 8 | 5,159 |
Where Synapse wins: callers across files cost grep 5,713 tokens and Synapse 218. A type's dependencies cost grep 4,751 and Synapse 324. Where grep wins: plain text patterns, such as which docs mention a name (17 tokens against 45) and a well-built git log for the most-changed file (138 against 549). Measured on Synapse main commit bcdf410.
Test 2: 60 questions on 9 private repos
Repos in JavaScript, TypeScript, React, Python and Next.js. The question subjects were chosen by fixed rules, the same in every repo, so none was hand-picked.
| Tool | Complete answers | Estimated tokens to answer |
|---|---|---|
| grep and git | 60 of 60 | 221,856 |
| Graphify 0.9.45, code-only | 32 of 60 | 116,050 |
| Synapse, first run | 24 of 60 | 135,196 |
| Synapse, after the fixes shipped in v0.5.0 | 53 of 60 | 21,848 |
Seven questions are still incomplete: four co-change questions (Synapse weights recent history, the key counts all history), two path questions where my answer key is wrong and Synapse's "no path" is correct for one of them, and one explain question. I left the keys frozen and scored every tool against them. Measured on main commit d94e09f.
Test 3: 8 cross-service questions
Eight services that call each other over HTTP, with answer keys from the company's service manifest.
| Tool | Complete answers | Estimated tokens to answer |
|---|---|---|
| grep and git, with the env var names known | 8 of 8 | 557 |
| Graphify 0.9.45, code-only, merged graphs | 1 of 8 | 10,792 |
| Synapse, first run | 0 of 8 | not applicable |
| Synapse, base-URL env vars declared in synapse.yaml | 8 of 8 | 1,570 |
| Synapse, nothing declared | 3 of 8 | 1,437 |
Precision: in a random sample of 30 of the 144 cross-repo endpoint links, each checked by reading the client and route code, all 30 were correct at the route level. Recall is the weaker number: of 1,154 client calls found, 161 are linked (99 through declared variables, 62 by inference). Most of the rest are external APIs, tests, or calls whose path is built in another file. Grep is cheaper here because its commands already knew the env var names. Synapse's value is finding the links without that knowledge. Measured on main commit 99e6f00.
How to read these results
- I wrote the questions, the answer keys and the fixes. An independent task set would be a better test.
- The fixes were written after I saw these results, on the same questions. A run on repos I did not tune against is next.
- The declared env vars came from the same service manifest as the answer keys.
- All ten repos come from one company and share conventions.
- No live agents and no exact tokenizer. Every token figure is an estimate.
What it does
- Indexes Go, JavaScript, TypeScript, Python, Swift, Java, Kotlin, Ruby, PHP, C, C++ and C#.
- Answers who calls a function, what a type change affects, what a file depends on, and the call path between two functions.
- Uses git history to show which files change together, and links documentation to the code it describes.
- Reads OpenAPI, GraphQL and Protobuf contracts and links handlers to clients across repos.
- Links HTTP routes to client calls across repos without spec files: Express, Hono, FastAPI, Flask and Next.js routes, and fetch, axios, got, ky, httpx and requests clients.
- Serves all of it over MCP to your IDE or agent.
Language support
| Language | Type edges | HTTP route and client linking | Benchmarked |
|---|---|---|---|
| Swift | Yes | No | Yes |
| JavaScript, TypeScript | Yes | Express, Hono, Next.js routes; fetch, axios, got, ky clients | Yes |
| Python | Yes | FastAPI, Flask routes; httpx, requests clients | Yes |
| Go, Java, Kotlin, Ruby, PHP, C, C++, C# | Not yet | Not yet | No |
Install
Homebrew on macOS
brew install keelwright-hq/synapse/synapse
Go
Needs a C toolchain, because tree-sitter uses CGO.
go install github.com/keelwright-hq/synapse/cmd/synapse@latest
Prebuilt binaries for macOS (arm64, amd64) and Linux (amd64, arm64) are on the GitHub releases page. Linux binaries need glibc 2.34 or newer. Then run synapse version. If you installed both with go install and Homebrew, run which -a synapse and keep one.
Cross-service linking
Declare how other services reach each member in synapse.yaml:
version: 1
repos:
- name: api
path: ./api
http:
base_env: [API_URL]
gateway_prefix: /api-svc
- name: web
path: ./webWith nothing declared, a call links only when exactly one other service matches. Ties are left unlinked on purpose. Then ask who calls a service:
synapse query services --workspace . --consumers-of api --sites 5
Status
Public beta, v0.5.0, Apache-2.0. I am looking for testers on real codebases, especially multi-repo ones and Go, Java and C# repos, which I have not benchmarked. If it misses something or links the wrong service, open an issue.
Hosted version
I am exploring a hosted option for teams, for example federation across many repos. If that would help you, tell me.
hello@keelwright.caKnown limits
- Type edges exist for Swift, JavaScript, TypeScript and Python only.
- No type inference: calls through a protocol-typed property stay unresolved when several types implement the method.
- Co-change favors recent history over all-time history.
- Pub/Sub and cron callers are not linked across services. Frontends that choose a service by a base key link only by inference.
- Go, Java, Kotlin, Ruby, PHP, C, C++ and C# are not benchmarked.