sciogen 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sciogen-0.1.0/.gitignore +37 -0
- sciogen-0.1.0/LICENSE +21 -0
- sciogen-0.1.0/PKG-INFO +217 -0
- sciogen-0.1.0/README.md +181 -0
- sciogen-0.1.0/docs/api.md +127 -0
- sciogen-0.1.0/docs/architecture.md +229 -0
- sciogen-0.1.0/docs/cli.md +83 -0
- sciogen-0.1.0/docs/mcp.md +56 -0
- sciogen-0.1.0/docs/quickstart.md +100 -0
- sciogen-0.1.0/docs/schema.md +77 -0
- sciogen-0.1.0/pyproject.toml +68 -0
- sciogen-0.1.0/sciogen/__init__.py +24 -0
- sciogen-0.1.0/sciogen/api.py +151 -0
- sciogen-0.1.0/sciogen/cli/__init__.py +1 -0
- sciogen-0.1.0/sciogen/cli/banner.py +19 -0
- sciogen-0.1.0/sciogen/cli/console.py +10 -0
- sciogen-0.1.0/sciogen/cli/explore/__init__.py +57 -0
- sciogen-0.1.0/sciogen/cli/explore/template.html +341 -0
- sciogen-0.1.0/sciogen/cli/main.py +322 -0
- sciogen-0.1.0/sciogen/config.py +82 -0
- sciogen-0.1.0/sciogen/discovery.py +125 -0
- sciogen-0.1.0/sciogen/embed/__init__.py +51 -0
- sciogen-0.1.0/sciogen/embed/hashing.py +53 -0
- sciogen-0.1.0/sciogen/embed/nomic.py +34 -0
- sciogen-0.1.0/sciogen/index/__init__.py +5 -0
- sciogen-0.1.0/sciogen/index/pipeline.py +363 -0
- sciogen-0.1.0/sciogen/ir.py +182 -0
- sciogen-0.1.0/sciogen/mcp/__init__.py +1 -0
- sciogen-0.1.0/sciogen/mcp/server.py +94 -0
- sciogen-0.1.0/sciogen/normalize/__init__.py +32 -0
- sciogen-0.1.0/sciogen/normalize/base.py +121 -0
- sciogen-0.1.0/sciogen/normalize/generic.py +18 -0
- sciogen-0.1.0/sciogen/normalize/javascript.py +365 -0
- sciogen-0.1.0/sciogen/normalize/python.py +358 -0
- sciogen-0.1.0/sciogen/parsing/__init__.py +1 -0
- sciogen-0.1.0/sciogen/parsing/languages.py +67 -0
- sciogen-0.1.0/sciogen/parsing/parser.py +46 -0
- sciogen-0.1.0/sciogen/query/__init__.py +27 -0
- sciogen-0.1.0/sciogen/query/engine.py +326 -0
- sciogen-0.1.0/sciogen/query/results.py +172 -0
- sciogen-0.1.0/sciogen/resolve/__init__.py +5 -0
- sciogen-0.1.0/sciogen/resolve/resolver.py +398 -0
- sciogen-0.1.0/sciogen/stores/__init__.py +1 -0
- sciogen-0.1.0/sciogen/stores/graph.py +316 -0
- sciogen-0.1.0/sciogen/stores/meta.py +324 -0
- sciogen-0.1.0/sciogen/stores/vectors.py +108 -0
- sciogen-0.1.0/site/index.html +862 -0
- sciogen-0.1.0/site/public/logo.png +0 -0
- sciogen-0.1.0/tests/conftest.py +95 -0
- sciogen-0.1.0/tests/test_cli.py +58 -0
- sciogen-0.1.0/tests/test_discovery.py +63 -0
- sciogen-0.1.0/tests/test_normalize_python.py +146 -0
- sciogen-0.1.0/tests/test_pipeline_and_query.py +213 -0
- sciogen-0.1.0/tests/test_resolver.py +148 -0
sciogen-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# sciogen index (generated per-project; never committed)
|
|
2
|
+
.sciogen/
|
|
3
|
+
|
|
4
|
+
# Python build / packaging
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
*.egg-info/
|
|
8
|
+
__pycache__/
|
|
9
|
+
*.py[cod]
|
|
10
|
+
*.egg
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# Test / tooling caches
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.mypy_cache/
|
|
20
|
+
.ruff_cache/
|
|
21
|
+
.coverage
|
|
22
|
+
htmlcov/
|
|
23
|
+
|
|
24
|
+
# Local tool settings
|
|
25
|
+
.claude/settings.local.json
|
|
26
|
+
|
|
27
|
+
# OS / editor
|
|
28
|
+
.DS_Store
|
|
29
|
+
Thumbs.db
|
|
30
|
+
*.swp
|
|
31
|
+
.idea/
|
|
32
|
+
.vscode/
|
|
33
|
+
|
|
34
|
+
#MD Files
|
|
35
|
+
CLAUDE.md
|
|
36
|
+
RELEASING.md
|
|
37
|
+
site/_artifact_body.html
|
sciogen-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 sciogen contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
sciogen-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sciogen
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Codebase intelligence layer — a queryable knowledge graph over your code.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ayanbag/sciogen
|
|
6
|
+
Project-URL: Repository, https://github.com/ayanbag/sciogen
|
|
7
|
+
Project-URL: Documentation, https://github.com/ayanbag/sciogen/tree/main/docs
|
|
8
|
+
Project-URL: Issues, https://github.com/ayanbag/sciogen/issues
|
|
9
|
+
Author: sciogen contributors
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: code-search,knowledge-graph,mcp,static-analysis,tree-sitter
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: chromadb>=0.5
|
|
22
|
+
Requires-Dist: kuzu>=0.7
|
|
23
|
+
Requires-Dist: mcp>=1.0
|
|
24
|
+
Requires-Dist: rich>=13.7
|
|
25
|
+
Requires-Dist: tree-sitter-language-pack<1.0,>=0.6
|
|
26
|
+
Requires-Dist: tree-sitter<0.26,>=0.22
|
|
27
|
+
Requires-Dist: typer>=0.12
|
|
28
|
+
Requires-Dist: watchdog>=4.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest-timeout; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
32
|
+
Provides-Extra: embeddings
|
|
33
|
+
Requires-Dist: einops; extra == 'embeddings'
|
|
34
|
+
Requires-Dist: sentence-transformers>=3.0; extra == 'embeddings'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
<img src="site/public/logo.png" alt="Image" width="100%" />
|
|
38
|
+
|
|
39
|
+
<div align="center">
|
|
40
|
+
<p>
|
|
41
|
+
<a href="https://pypi.org/project/sciogen/"><img alt="PyPI" src="https://img.shields.io/pypi/v/sciogen.svg"></a>
|
|
42
|
+
<a href="https://pypi.org/project/sciogen/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/sciogen.svg"></a>
|
|
43
|
+
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
|
|
44
|
+
</p>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
**Codebase intelligence layer** — a queryable knowledge graph over your code.
|
|
48
|
+
|
|
49
|
+
sciogen parses a codebase once, resolves every reference to the exact definition it
|
|
50
|
+
points to, and materializes the result into an embedded triple store. After that,
|
|
51
|
+
questions like *"who calls `AuthService.login`?"*, *"what breaks if I change
|
|
52
|
+
`UserModel.find_by_email`?"*, or *"where is the password hashing logic?"* are
|
|
53
|
+
sub-second index lookups that return **typed objects with file/line locations** —
|
|
54
|
+
not grep results, not raw source dumps.
|
|
55
|
+
|
|
56
|
+
sciogen is a **static analysis and indexing tool**. It never calls an LLM, never
|
|
57
|
+
counts tokens, and has no concept of a context window. It is to codebases what
|
|
58
|
+
Elasticsearch is to documents: precomputed, queryable structure.
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
pip install sciogen
|
|
62
|
+
sciogen index .
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
███████╗ ██████╗██╗ ██████╗ ██████╗ ███████╗███╗ ██╗
|
|
67
|
+
██╔════╝██╔════╝██║██╔═══██╗██╔════╝ ██╔════╝████╗ ██║
|
|
68
|
+
███████╗██║ ██║██║ ██║██║ ███╗█████╗ ██╔██╗ ██║
|
|
69
|
+
╚════██║██║ ██║██║ ██║██║ ██║██╔══╝ ██║╚██╗██║
|
|
70
|
+
███████║╚██████╗██║╚██████╔╝╚██████╔╝███████╗██║ ╚████║
|
|
71
|
+
╚══════╝ ╚═════╝╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝
|
|
72
|
+
Codebase Intelligence Layer v0.1.0
|
|
73
|
+
|
|
74
|
+
✓ Scanning project structure...
|
|
75
|
+
✓ Reading 143 files...
|
|
76
|
+
✓ Parsing Python, TypeScript...
|
|
77
|
+
✓ Building knowledge graph...
|
|
78
|
+
✓ Embedding 1,204 symbols...
|
|
79
|
+
✓ Linking dependencies...
|
|
80
|
+
✓ Done! 1,204 nodes · 3,456 edges · indexed in 4.2s
|
|
81
|
+
Ready. Your codebase is now queryable.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Why
|
|
85
|
+
|
|
86
|
+
A coding agent understands a codebase by **reading files** — and files are the
|
|
87
|
+
wrong granularity. To learn one function's callers it reads thousands of lines
|
|
88
|
+
of source into its context window, burning tokens on noise. sciogen precomputes
|
|
89
|
+
the structure once, so the same answer is a handful of typed records with exact
|
|
90
|
+
`file:line` locations.
|
|
91
|
+
|
|
92
|
+
You run `sciogen index .` once. The knowledge graph is written to a `.sciogen/`
|
|
93
|
+
directory **inside the codebase**. From then on, an agent working in that repo
|
|
94
|
+
reads the graph instead of the raw files — the callers of a symbol, the blast
|
|
95
|
+
radius of a change, where a concept lives — for a fraction of the tokens a
|
|
96
|
+
file-by-file crawl would cost. sciogen itself never calls an LLM and is unaware
|
|
97
|
+
of tokens; the savings are a consequence of returning structure instead of
|
|
98
|
+
source.
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
index once ─────────────► .sciogen/ (graph stored in the repo)
|
|
102
|
+
(sciogen index .) │
|
|
103
|
+
▼
|
|
104
|
+
agent asks: "who calls login?" → typed records + file:line
|
|
105
|
+
agent asks: "what breaks if …?" → impact subgraph, not 40 files
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## The two ways it's used
|
|
109
|
+
|
|
110
|
+
**You — from the terminal.** `sciogen index .` builds the graph; `sciogen
|
|
111
|
+
explore` opens it as an interactive browser GUI to inspect the codebase
|
|
112
|
+
visually.
|
|
113
|
+
|
|
114
|
+
**Your coding agent — over MCP.** `sciogen mcp .` exposes the graph to any
|
|
115
|
+
agent (Claude Code, etc.) through the Model Context Protocol, so it can query
|
|
116
|
+
callers, dependencies, impact, and semantic search directly instead of reading
|
|
117
|
+
files. See [docs/mcp.md](docs/mcp.md).
|
|
118
|
+
|
|
119
|
+
## What the graph gives an agent
|
|
120
|
+
|
|
121
|
+
- **Exact call graphs** — a call to `login()` resolves to
|
|
122
|
+
`src/auth/service.py:AuthService.login`, not the string `"login"`. References
|
|
123
|
+
static analysis cannot prove (dynamic dispatch, injected dependencies) are kept
|
|
124
|
+
with a **low confidence score** rather than silently dropped, so the caller
|
|
125
|
+
chooses how much to trust each edge.
|
|
126
|
+
- **Impact analysis** — everything that may break if a symbol changes:
|
|
127
|
+
transitive callers with hop counts, subclasses, implementors, tests, mutators —
|
|
128
|
+
and the same for a whole PR at once from a unified diff.
|
|
129
|
+
- **Semantic + hybrid search** — local embeddings at four granularities (file,
|
|
130
|
+
class, function, chunk); hybrid mode expands vector hits through the graph.
|
|
131
|
+
- **Incremental by design** — SHA256 differ with a stat fast path; a single-file
|
|
132
|
+
change re-indexes in under a second, and dependent files are re-linked without
|
|
133
|
+
being re-parsed.
|
|
134
|
+
- **Interactive visualization** — `sciogen explore` renders the graph in your
|
|
135
|
+
browser from one self-contained HTML file. No server.
|
|
136
|
+
|
|
137
|
+
## Getting started
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
pip install sciogen
|
|
141
|
+
# optional, for real code-optimized semantic search (larger, one model download):
|
|
142
|
+
pip install "sciogen[embeddings]"
|
|
143
|
+
|
|
144
|
+
cd your-project
|
|
145
|
+
sciogen index . # build the graph (stored in ./.sciogen; incremental after)
|
|
146
|
+
sciogen explore # inspect it visually in the browser
|
|
147
|
+
sciogen mcp . # serve it to your coding agent over MCP
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Add `.sciogen/` to your `.gitignore` — it's machine-local and regenerable.
|
|
151
|
+
|
|
152
|
+
You can also query directly from the terminal for a quick look:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
sciogen search "password hashing" # semantic search
|
|
156
|
+
sciogen callers AuthService.login # who calls this?
|
|
157
|
+
sciogen impact UserModel.find_by_email # what breaks if this changes?
|
|
158
|
+
sciogen deps src/auth/service.py # imports, transitive deps
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
See [docs/cli.md](docs/cli.md) for every command.
|
|
162
|
+
|
|
163
|
+
## Architecture in one paragraph
|
|
164
|
+
|
|
165
|
+
`sciogen index` runs a five-stage pipeline per file: **tree-sitter** parses
|
|
166
|
+
(100+ languages, one API), a **normalizer** converts the language-specific AST
|
|
167
|
+
into a universal IR (only this layer knows languages), the **symbol resolver**
|
|
168
|
+
traces every reference to its exact definition with a confidence score, the
|
|
169
|
+
**graph builder** materializes typed nodes/edges into **KuzuDB** (Cypher), and a
|
|
170
|
+
**SHA256 differ** backed by **SQLite** makes re-runs incremental. Embeddings of
|
|
171
|
+
normalized symbol summaries (never raw code) go to **ChromaDB** at four
|
|
172
|
+
granularities. Queries are deterministic: structural queries hit KuzuDB, semantic
|
|
173
|
+
queries hit ChromaDB, hybrid uses vector hits as seeds for graph expansion. The
|
|
174
|
+
full design — including the performance architecture (parallel parsing, batched
|
|
175
|
+
transactional writes, embed deduplication, incremental re-resolution) — is in
|
|
176
|
+
[docs/architecture.md](docs/architecture.md).
|
|
177
|
+
|
|
178
|
+
## Storage
|
|
179
|
+
|
|
180
|
+
Everything is embedded — no servers, no ports, one `.sciogen/` directory:
|
|
181
|
+
|
|
182
|
+
| Store | Role |
|
|
183
|
+
|-------|------|
|
|
184
|
+
| KuzuDB | Graph topology — nodes, typed edges, confidence scores |
|
|
185
|
+
| ChromaDB | Vector embeddings at file/class/function/chunk granularity |
|
|
186
|
+
| SQLite | File hashes, symbol table, reference records, schema version |
|
|
187
|
+
|
|
188
|
+
Add `.sciogen/` to your `.gitignore`.
|
|
189
|
+
|
|
190
|
+
## Documentation
|
|
191
|
+
|
|
192
|
+
| Doc | Contents |
|
|
193
|
+
|-----|----------|
|
|
194
|
+
| [docs/quickstart.md](docs/quickstart.md) | Install, first index, first queries |
|
|
195
|
+
| [docs/cli.md](docs/cli.md) | Every command and flag |
|
|
196
|
+
| [docs/mcp.md](docs/mcp.md) | MCP tools and agent setup — how an agent consumes the graph |
|
|
197
|
+
| [docs/schema.md](docs/schema.md) | Node types, edge types, confidence model |
|
|
198
|
+
| [docs/architecture.md](docs/architecture.md) | The two phases, every design decision, performance architecture |
|
|
199
|
+
| [docs/api.md](docs/api.md) | Embedded Python API — only if you're building tooling *on top of* sciogen |
|
|
200
|
+
|
|
201
|
+
## Supported languages
|
|
202
|
+
|
|
203
|
+
Full symbol extraction: **Python**, **JavaScript**, **TypeScript/TSX**.
|
|
204
|
+
File-level indexing (parse check + file search): Go, Rust, Java, Ruby, PHP, C,
|
|
205
|
+
C++, C#, Kotlin, Swift, Scala, Lua. Adding full support for a language means
|
|
206
|
+
writing one normalizer — see [docs/architecture.md](docs/architecture.md#ast-normalizer).
|
|
207
|
+
|
|
208
|
+
## Development
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
git clone <repo> && cd sciogen
|
|
212
|
+
python -m venv .venv && .venv/Scripts/activate # or bin/activate
|
|
213
|
+
pip install -e ".[dev]"
|
|
214
|
+
pytest
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
MIT license.
|
sciogen-0.1.0/README.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<img src="site/public/logo.png" alt="Image" width="100%" />
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<p>
|
|
5
|
+
<a href="https://pypi.org/project/sciogen/"><img alt="PyPI" src="https://img.shields.io/pypi/v/sciogen.svg"></a>
|
|
6
|
+
<a href="https://pypi.org/project/sciogen/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/sciogen.svg"></a>
|
|
7
|
+
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
|
|
8
|
+
</p>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
**Codebase intelligence layer** — a queryable knowledge graph over your code.
|
|
12
|
+
|
|
13
|
+
sciogen parses a codebase once, resolves every reference to the exact definition it
|
|
14
|
+
points to, and materializes the result into an embedded triple store. After that,
|
|
15
|
+
questions like *"who calls `AuthService.login`?"*, *"what breaks if I change
|
|
16
|
+
`UserModel.find_by_email`?"*, or *"where is the password hashing logic?"* are
|
|
17
|
+
sub-second index lookups that return **typed objects with file/line locations** —
|
|
18
|
+
not grep results, not raw source dumps.
|
|
19
|
+
|
|
20
|
+
sciogen is a **static analysis and indexing tool**. It never calls an LLM, never
|
|
21
|
+
counts tokens, and has no concept of a context window. It is to codebases what
|
|
22
|
+
Elasticsearch is to documents: precomputed, queryable structure.
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
pip install sciogen
|
|
26
|
+
sciogen index .
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
███████╗ ██████╗██╗ ██████╗ ██████╗ ███████╗███╗ ██╗
|
|
31
|
+
██╔════╝██╔════╝██║██╔═══██╗██╔════╝ ██╔════╝████╗ ██║
|
|
32
|
+
███████╗██║ ██║██║ ██║██║ ███╗█████╗ ██╔██╗ ██║
|
|
33
|
+
╚════██║██║ ██║██║ ██║██║ ██║██╔══╝ ██║╚██╗██║
|
|
34
|
+
███████║╚██████╗██║╚██████╔╝╚██████╔╝███████╗██║ ╚████║
|
|
35
|
+
╚══════╝ ╚═════╝╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝
|
|
36
|
+
Codebase Intelligence Layer v0.1.0
|
|
37
|
+
|
|
38
|
+
✓ Scanning project structure...
|
|
39
|
+
✓ Reading 143 files...
|
|
40
|
+
✓ Parsing Python, TypeScript...
|
|
41
|
+
✓ Building knowledge graph...
|
|
42
|
+
✓ Embedding 1,204 symbols...
|
|
43
|
+
✓ Linking dependencies...
|
|
44
|
+
✓ Done! 1,204 nodes · 3,456 edges · indexed in 4.2s
|
|
45
|
+
Ready. Your codebase is now queryable.
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Why
|
|
49
|
+
|
|
50
|
+
A coding agent understands a codebase by **reading files** — and files are the
|
|
51
|
+
wrong granularity. To learn one function's callers it reads thousands of lines
|
|
52
|
+
of source into its context window, burning tokens on noise. sciogen precomputes
|
|
53
|
+
the structure once, so the same answer is a handful of typed records with exact
|
|
54
|
+
`file:line` locations.
|
|
55
|
+
|
|
56
|
+
You run `sciogen index .` once. The knowledge graph is written to a `.sciogen/`
|
|
57
|
+
directory **inside the codebase**. From then on, an agent working in that repo
|
|
58
|
+
reads the graph instead of the raw files — the callers of a symbol, the blast
|
|
59
|
+
radius of a change, where a concept lives — for a fraction of the tokens a
|
|
60
|
+
file-by-file crawl would cost. sciogen itself never calls an LLM and is unaware
|
|
61
|
+
of tokens; the savings are a consequence of returning structure instead of
|
|
62
|
+
source.
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
index once ─────────────► .sciogen/ (graph stored in the repo)
|
|
66
|
+
(sciogen index .) │
|
|
67
|
+
▼
|
|
68
|
+
agent asks: "who calls login?" → typed records + file:line
|
|
69
|
+
agent asks: "what breaks if …?" → impact subgraph, not 40 files
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## The two ways it's used
|
|
73
|
+
|
|
74
|
+
**You — from the terminal.** `sciogen index .` builds the graph; `sciogen
|
|
75
|
+
explore` opens it as an interactive browser GUI to inspect the codebase
|
|
76
|
+
visually.
|
|
77
|
+
|
|
78
|
+
**Your coding agent — over MCP.** `sciogen mcp .` exposes the graph to any
|
|
79
|
+
agent (Claude Code, etc.) through the Model Context Protocol, so it can query
|
|
80
|
+
callers, dependencies, impact, and semantic search directly instead of reading
|
|
81
|
+
files. See [docs/mcp.md](docs/mcp.md).
|
|
82
|
+
|
|
83
|
+
## What the graph gives an agent
|
|
84
|
+
|
|
85
|
+
- **Exact call graphs** — a call to `login()` resolves to
|
|
86
|
+
`src/auth/service.py:AuthService.login`, not the string `"login"`. References
|
|
87
|
+
static analysis cannot prove (dynamic dispatch, injected dependencies) are kept
|
|
88
|
+
with a **low confidence score** rather than silently dropped, so the caller
|
|
89
|
+
chooses how much to trust each edge.
|
|
90
|
+
- **Impact analysis** — everything that may break if a symbol changes:
|
|
91
|
+
transitive callers with hop counts, subclasses, implementors, tests, mutators —
|
|
92
|
+
and the same for a whole PR at once from a unified diff.
|
|
93
|
+
- **Semantic + hybrid search** — local embeddings at four granularities (file,
|
|
94
|
+
class, function, chunk); hybrid mode expands vector hits through the graph.
|
|
95
|
+
- **Incremental by design** — SHA256 differ with a stat fast path; a single-file
|
|
96
|
+
change re-indexes in under a second, and dependent files are re-linked without
|
|
97
|
+
being re-parsed.
|
|
98
|
+
- **Interactive visualization** — `sciogen explore` renders the graph in your
|
|
99
|
+
browser from one self-contained HTML file. No server.
|
|
100
|
+
|
|
101
|
+
## Getting started
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install sciogen
|
|
105
|
+
# optional, for real code-optimized semantic search (larger, one model download):
|
|
106
|
+
pip install "sciogen[embeddings]"
|
|
107
|
+
|
|
108
|
+
cd your-project
|
|
109
|
+
sciogen index . # build the graph (stored in ./.sciogen; incremental after)
|
|
110
|
+
sciogen explore # inspect it visually in the browser
|
|
111
|
+
sciogen mcp . # serve it to your coding agent over MCP
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Add `.sciogen/` to your `.gitignore` — it's machine-local and regenerable.
|
|
115
|
+
|
|
116
|
+
You can also query directly from the terminal for a quick look:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
sciogen search "password hashing" # semantic search
|
|
120
|
+
sciogen callers AuthService.login # who calls this?
|
|
121
|
+
sciogen impact UserModel.find_by_email # what breaks if this changes?
|
|
122
|
+
sciogen deps src/auth/service.py # imports, transitive deps
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
See [docs/cli.md](docs/cli.md) for every command.
|
|
126
|
+
|
|
127
|
+
## Architecture in one paragraph
|
|
128
|
+
|
|
129
|
+
`sciogen index` runs a five-stage pipeline per file: **tree-sitter** parses
|
|
130
|
+
(100+ languages, one API), a **normalizer** converts the language-specific AST
|
|
131
|
+
into a universal IR (only this layer knows languages), the **symbol resolver**
|
|
132
|
+
traces every reference to its exact definition with a confidence score, the
|
|
133
|
+
**graph builder** materializes typed nodes/edges into **KuzuDB** (Cypher), and a
|
|
134
|
+
**SHA256 differ** backed by **SQLite** makes re-runs incremental. Embeddings of
|
|
135
|
+
normalized symbol summaries (never raw code) go to **ChromaDB** at four
|
|
136
|
+
granularities. Queries are deterministic: structural queries hit KuzuDB, semantic
|
|
137
|
+
queries hit ChromaDB, hybrid uses vector hits as seeds for graph expansion. The
|
|
138
|
+
full design — including the performance architecture (parallel parsing, batched
|
|
139
|
+
transactional writes, embed deduplication, incremental re-resolution) — is in
|
|
140
|
+
[docs/architecture.md](docs/architecture.md).
|
|
141
|
+
|
|
142
|
+
## Storage
|
|
143
|
+
|
|
144
|
+
Everything is embedded — no servers, no ports, one `.sciogen/` directory:
|
|
145
|
+
|
|
146
|
+
| Store | Role |
|
|
147
|
+
|-------|------|
|
|
148
|
+
| KuzuDB | Graph topology — nodes, typed edges, confidence scores |
|
|
149
|
+
| ChromaDB | Vector embeddings at file/class/function/chunk granularity |
|
|
150
|
+
| SQLite | File hashes, symbol table, reference records, schema version |
|
|
151
|
+
|
|
152
|
+
Add `.sciogen/` to your `.gitignore`.
|
|
153
|
+
|
|
154
|
+
## Documentation
|
|
155
|
+
|
|
156
|
+
| Doc | Contents |
|
|
157
|
+
|-----|----------|
|
|
158
|
+
| [docs/quickstart.md](docs/quickstart.md) | Install, first index, first queries |
|
|
159
|
+
| [docs/cli.md](docs/cli.md) | Every command and flag |
|
|
160
|
+
| [docs/mcp.md](docs/mcp.md) | MCP tools and agent setup — how an agent consumes the graph |
|
|
161
|
+
| [docs/schema.md](docs/schema.md) | Node types, edge types, confidence model |
|
|
162
|
+
| [docs/architecture.md](docs/architecture.md) | The two phases, every design decision, performance architecture |
|
|
163
|
+
| [docs/api.md](docs/api.md) | Embedded Python API — only if you're building tooling *on top of* sciogen |
|
|
164
|
+
|
|
165
|
+
## Supported languages
|
|
166
|
+
|
|
167
|
+
Full symbol extraction: **Python**, **JavaScript**, **TypeScript/TSX**.
|
|
168
|
+
File-level indexing (parse check + file search): Go, Rust, Java, Ruby, PHP, C,
|
|
169
|
+
C++, C#, Kotlin, Swift, Scala, Lua. Adding full support for a language means
|
|
170
|
+
writing one normalizer — see [docs/architecture.md](docs/architecture.md#ast-normalizer).
|
|
171
|
+
|
|
172
|
+
## Development
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
git clone <repo> && cd sciogen
|
|
176
|
+
python -m venv .venv && .venv/Scripts/activate # or bin/activate
|
|
177
|
+
pip install -e ".[dev]"
|
|
178
|
+
pytest
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
MIT license.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Python API
|
|
2
|
+
|
|
3
|
+
The whole library is one facade class, `SciogenGraph`, reached through
|
|
4
|
+
`sciogen.open()`. The CLI and MCP server are thin adapters over it.
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
import sciogen
|
|
8
|
+
|
|
9
|
+
graph = sciogen.open("path/to/repo") # opens (creates) the .sciogen index
|
|
10
|
+
graph.index() # incremental build; returns IndexStats
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`SciogenGraph` is a context manager; stores open lazily on first use.
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
with sciogen.open(".") as graph:
|
|
17
|
+
graph.index()
|
|
18
|
+
info = graph.get_symbol("AuthService.login")
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Indexing
|
|
22
|
+
|
|
23
|
+
### `graph.index(reporter=None, rebuild=False) -> IndexStats`
|
|
24
|
+
|
|
25
|
+
Build or incrementally update the index. `rebuild=True` wipes `.sciogen/` first.
|
|
26
|
+
`reporter` is an optional progress sink (the CLI passes a Rich adapter; omit for
|
|
27
|
+
silence).
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
stats = graph.index()
|
|
31
|
+
stats.nodes, stats.edges, stats.seconds
|
|
32
|
+
stats.files_indexed, stats.files_unchanged, stats.files_deleted, stats.files_failed
|
|
33
|
+
stats.errors # list[(path, error_message)]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Structural queries
|
|
37
|
+
|
|
38
|
+
All return typed dataclasses with `.to_dict()`. Every node reference carries an
|
|
39
|
+
exact `file` / `line_start` / `line_end`.
|
|
40
|
+
|
|
41
|
+
### `get_symbol(name, file=None) -> SymbolInfo`
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
info = graph.get_symbol("AuthService.login")
|
|
45
|
+
info.node.kind # "FunctionNode"
|
|
46
|
+
info.node.file # "src/auth/service.py"
|
|
47
|
+
info.node.params # ["self", "username: str", "password: str"]
|
|
48
|
+
info.node.line_start
|
|
49
|
+
info.relations # [Relation(kind, other, direction, confidence), ...]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Pass `file=` to disambiguate a name defined in several places. Raises
|
|
53
|
+
`sciogen.query.engine.SymbolNotFound` if nothing matches.
|
|
54
|
+
|
|
55
|
+
### `get_callers(symbol, depth=1, min_confidence=0.0) -> ImpactGraph`
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
result = graph.get_callers("hash_password", depth=2)
|
|
59
|
+
for item in result.impacted: # sorted by (hops, -confidence)
|
|
60
|
+
item.node.id, item.hops, item.confidence, item.relation
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`confidence` is the path confidence — the weakest edge along the best path.
|
|
64
|
+
|
|
65
|
+
### `analyze_impact(symbol, max_depth=5, min_confidence=0.0) -> ImpactGraph`
|
|
66
|
+
|
|
67
|
+
Everything that may break if `symbol` changes: transitive callers (up to
|
|
68
|
+
`max_depth`) plus one-hop subclasses, implementors, tests, and mutators.
|
|
69
|
+
|
|
70
|
+
### `get_dependencies(file) -> DependencyInfo`
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
deps = graph.get_dependencies("src/auth/service.py")
|
|
74
|
+
deps.direct_files # files directly imported
|
|
75
|
+
deps.transitive_files # reachable beyond direct
|
|
76
|
+
deps.external_modules # third-party / stdlib module names
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### `get_diff_impact(unified_diff) -> DiffImpact`
|
|
80
|
+
|
|
81
|
+
Feed a unified diff; get the union impact of every symbol it touches.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
result = graph.get_diff_impact(open("pr.diff").read())
|
|
85
|
+
result.changed_symbols # symbols whose lines the diff overlaps
|
|
86
|
+
result.unmatched_files # files in the diff not in the index
|
|
87
|
+
result.impact # ImpactGraph over all changed symbols at once
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Semantic & hybrid queries
|
|
91
|
+
|
|
92
|
+
### `search(query, mode="semantic", granularity=None, k=10) -> SearchResults`
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
graph.search("password hashing logic")
|
|
96
|
+
graph.search("all code related to auth", mode="hybrid")
|
|
97
|
+
graph.search("classes that manage sessions", granularity="class")
|
|
98
|
+
|
|
99
|
+
for hit in results.hits:
|
|
100
|
+
hit.node, hit.score, hit.granularity, hit.via # via: "semantic" | "graph"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`hybrid` mode uses vector hits as seeds and expands through the graph;
|
|
104
|
+
graph-expanded hits are marked `via="graph"`.
|
|
105
|
+
|
|
106
|
+
### `get_context_for_task(description, k=15) -> ContextBundle`
|
|
107
|
+
|
|
108
|
+
Broad intent → curated subgraph.
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
bundle = graph.get_context_for_task("add rate limiting to login")
|
|
112
|
+
bundle.files # ranked most-relevant first
|
|
113
|
+
bundle.symbols # SearchHit list
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Result types
|
|
117
|
+
|
|
118
|
+
All defined in `sciogen.query.results`, all plain dataclasses with `.to_dict()`:
|
|
119
|
+
`SymbolNode`, `SymbolInfo`, `Relation`, `ImpactedSymbol`, `ImpactGraph`,
|
|
120
|
+
`DependencyInfo`, `SearchHit`, `SearchResults`, `DiffImpact`, `ContextBundle`.
|
|
121
|
+
|
|
122
|
+
## Notes
|
|
123
|
+
|
|
124
|
+
- Query results are memoized in an LRU keyed by the index version; a re-index
|
|
125
|
+
invalidates the whole cache at once.
|
|
126
|
+
- Queries never return raw source code — only typed nodes with locations. The
|
|
127
|
+
caller decides whether to open the file.
|