Codebase intelligence layer
Your codebase, as a graph your agent can read.
sciogen indexes your code once into a queryable knowledge graph — every symbol, every call, resolved to its exact definition. Then a coding agent reads structure instead of raw files, for a fraction of the tokens.
The problem
Reading files is the wrong granularity.
To learn one function's callers, an agent pulls thousands of lines of source into its context window and infers the call graph itself. sciogen precomputes that structure, so the same answer is a handful of typed records with exact file:line locations.
Without sciogen
With sciogen
Phase 1 · Indexing
Five stages turn source into a resolved graph.
Every file flows through the same pipeline. Only the normalizer knows languages; everything downstream is language-agnostic — and only changed files are ever re-processed.
Tree-sitter
Language-specific ASTs from 100+ grammars behind a single API.
Universal IR
Python, JS, Go all become the same typed nodes. The only layer with language knowledge.
Symbol resolver
Every reference traced to its exact definition, with a confidence score.
KuzuDB graph
Typed nodes and edges materialized into an embedded graph store via Cypher.
SHA256 differ
Only changed files re-run. A no-op re-index is instant; one file, under a second.
Phase 2 · Querying
Deterministic queries. Typed answers. Never raw source.
Real output, from sciogen indexing its own source. Structural queries hit the graph; semantic queries hit local vectors; hybrid uses vector hits as seeds for graph expansion.
$ sciogen callers resolve_file 6 symbols → resolve_file hops conf via symbol location 1 0.90 CALLS Pipeline._link sciogen/index/pipeline.py:335 1 0.60 CALLS edges_of tests/test_resolver.py:19 1 0.60 CALLS test_extends_resolution tests/test_resolver.py:124 1 0.60 CALLS test_local_call_full… tests/test_resolver.py:24 1 0.60 CALLS test_test_for_naming… tests/test_resolver.py:136
$ sciogen impact GraphStore --depth 3 5 symbols → GraphStore hops conf via symbol location 1 0.90 CALLS SciogenGraph.graph_store sciogen/api.py:40 1 0.90 MUTATES GraphStore.__init__ sciogen/stores/graph.py:76 2 0.90 CALLS SciogenGraph.snapshot sciogen/api.py:121 3 0.40 CALLS explore sciogen/cli/main.py:262 3 0.40 CALLS test_explore_html_generation tests/test_pipeline…
$ sciogen search "deduplicate embeddings by content hash" score kind symbol location 0.71 FunctionNode Pipeline._embed sciogen/index/pipeline.py:210 0.66 FunctionNode MetaStore.embedding_hashes sciogen/stores/meta.py:243 0.58 ChunkNode _embed · part 2 sciogen/index/pipeline.py:216 0.52 FunctionNode HashingEmbedder.embed sciogen/embed/hashing.py:34
$ sciogen index . ✓ Scanning project structure... ✓ Parsing Python... ✓ Building knowledge graph... ✓ Embedding 380 symbols... ✓ Linking dependencies... ✓ Done! 521 nodes · 1,217 edges · indexed in 25.4s Ready. Your codebase is now queryable. $ sciogen index . # nothing changed ✓ Done! 521 nodes · 1,217 edges · indexed in 0.2s
The honest part
Every edge carries a confidence score.
Static analysis is incomplete, not wrong. A call through dynamic dispatch can't be proven — so sciogen keeps the edge and scores it low, instead of dropping it and faking a clean graph. You set the threshold at query time.
Path confidence
On a multi-hop traversal, a chain is only as trustworthy as its weakest link. sciogen reports the minimum edge confidence along the best path — so a two-hop caller through one shaky edge is scored honestly, not averaged into false certainty.
min(0.9, 0.4, 1.0) → 0.4Two ways it's used
You read it in the terminal. Your agent reads it over MCP.
The graph lives in a .sciogen/ directory inside the repo. Nobody reads those binary stores directly — the query layer turns a question into a small typed answer.
Index & explore
Build the graph, then open it as an interactive browser GUI — collapsed to files, expanding into classes, functions, and call edges on click.
Query, don't crawl
Eight tools over the Model Context Protocol. The agent calls analyze_impact or get_context_for_task and gets typed records — then opens only the files it points to.
Nodes, typed edges, and confidence scores. One embedded graph, queried with Cypher — no server.
Embeddings at four granularities — file, class, function, chunk — of normalized summaries, never raw code.
File hashes, the symbol table, and reference records that make incremental re-resolution possible.
███████╗ ██████╗██╗ ██████╗ ██████╗ ███████╗███╗ ██╗ ██╔════╝██╔════╝██║██╔═══██╗██╔════╝ ██╔════╝████╗ ██║ ███████╗██║ ██║██║ ██║██║ ███╗█████╗ ██╔██╗ ██║ ╚════██║██║ ██║██║ ██║██║ ██║██╔══╝ ██║╚██╗██║ ███████║╚██████╗██║╚██████╔╝╚██████╔╝███████╗██║ ╚████║ ╚══════╝ ╚═════╝╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝
Index once. Query forever.
One command builds the graph. Everything after is a sub-second lookup — for you, and for the agent working beside you.