codegraphy 0.1.0__tar.gz → 1.0.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.
- {codegraphy-0.1.0 → codegraphy-1.0.0}/PKG-INFO +41 -8
- {codegraphy-0.1.0 → codegraphy-1.0.0}/README.md +40 -7
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/__init__.py +1 -1
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/cli.py +14 -15
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/config.py +3 -3
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/db/store.py +11 -0
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/indexer/python.py +10 -2
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/mcp/server.py +4 -4
- {codegraphy-0.1.0 → codegraphy-1.0.0}/codegraphy.egg-info/PKG-INFO +41 -8
- codegraphy-1.0.0/codegraphy.egg-info/SOURCES.txt +24 -0
- codegraphy-1.0.0/codegraphy.egg-info/entry_points.txt +2 -0
- codegraphy-1.0.0/codegraphy.egg-info/top_level.txt +1 -0
- {codegraphy-0.1.0 → codegraphy-1.0.0}/pyproject.toml +3 -3
- codegraphy-0.1.0/codegraphy.egg-info/SOURCES.txt +0 -24
- codegraphy-0.1.0/codegraphy.egg-info/entry_points.txt +0 -2
- codegraphy-0.1.0/codegraphy.egg-info/top_level.txt +0 -1
- {codegraphy-0.1.0 → codegraphy-1.0.0}/LICENSE +0 -0
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/db/__init__.py +0 -0
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/db/schema.py +0 -0
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/indexer/__init__.py +0 -0
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/indexer/base.py +0 -0
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/indexer/walker.py +0 -0
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/mcp/__init__.py +0 -0
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/plugins/__init__.py +0 -0
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/plugins/base.py +0 -0
- {codegraphy-0.1.0/repolens → codegraphy-1.0.0/codegraphy}/plugins/django.py +0 -0
- {codegraphy-0.1.0 → codegraphy-1.0.0}/codegraphy.egg-info/dependency_links.txt +0 -0
- {codegraphy-0.1.0 → codegraphy-1.0.0}/codegraphy.egg-info/requires.txt +0 -0
- {codegraphy-0.1.0 → codegraphy-1.0.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codegraphy
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: SQLite/PostgreSQL codebase knowledge graph and MCP server for Claude Code
|
|
5
5
|
Author: Charan Kulal
|
|
6
6
|
License-Expression: MIT
|
|
@@ -42,6 +42,8 @@ Dynamic: license-file
|
|
|
42
42
|
|
|
43
43
|
Standalone Python package that parses a codebase into a knowledge graph (PostgreSQL or SQLite) and exposes it as an [MCP](https://modelcontextprotocol.io/) server for Claude Code. Claude calls graph tools instead of `Read` + `Bash(grep)` — cuts exploration token cost by 5–10×.
|
|
44
44
|
|
|
45
|
+
**PyPI:** https://pypi.org/project/codegraphy/
|
|
46
|
+
|
|
45
47
|
**Python:** 3.10+
|
|
46
48
|
**License:** MIT
|
|
47
49
|
|
|
@@ -78,6 +80,37 @@ The base PyPI package keeps SQLite support in the standard library path, so Post
|
|
|
78
80
|
|
|
79
81
|
---
|
|
80
82
|
|
|
83
|
+
## PostgreSQL
|
|
84
|
+
|
|
85
|
+
Install PostgreSQL support:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install 'codegraphy[postgres]'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Initialize with a PostgreSQL URL:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
codegraphy init --db postgresql://USER:PASSWORD@HOST:PORT/DBNAME
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Example:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
codegraphy init --db postgresql://postgres:postgres@localhost:5432/codegraphy
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Or set `DATABASE_URL` once and reuse it:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
export DATABASE_URL=postgresql://postgres:postgres@localhost:5432/codegraphy
|
|
107
|
+
codegraphy init
|
|
108
|
+
codegraphy index .
|
|
109
|
+
codegraphy serve
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
81
114
|
## Quickstart
|
|
82
115
|
|
|
83
116
|
```bash
|
|
@@ -136,9 +169,9 @@ Priority: CLI flag → environment variable → `codegraphy.toml` → defaults.
|
|
|
136
169
|
### Environment Variables
|
|
137
170
|
|
|
138
171
|
```bash
|
|
139
|
-
DATABASE_URL=sqlite:///codegraphy.db
|
|
140
|
-
|
|
141
|
-
|
|
172
|
+
DATABASE_URL=sqlite:///codegraphy.db # or postgresql://localhost/codegraphy
|
|
173
|
+
CODEGRAPHY_ROOT=. # project root for grep fallback
|
|
174
|
+
CODEGRAPHY_PLUGINS=codegraphy.plugins.django
|
|
142
175
|
```
|
|
143
176
|
|
|
144
177
|
### Config File (optional)
|
|
@@ -148,7 +181,7 @@ REPOLENS_PLUGINS=repolens.plugins.django
|
|
|
148
181
|
database_url = "postgresql://localhost/codegraphy"
|
|
149
182
|
root = "."
|
|
150
183
|
exclude = ["migrations", "node_modules", ".venv", "__pycache__"]
|
|
151
|
-
plugins = ["
|
|
184
|
+
plugins = ["codegraphy.plugins.django"]
|
|
152
185
|
```
|
|
153
186
|
|
|
154
187
|
---
|
|
@@ -191,9 +224,9 @@ plugins = ["repolens.plugins.django"]
|
|
|
191
224
|
## Architecture
|
|
192
225
|
|
|
193
226
|
```
|
|
194
|
-
|
|
227
|
+
codegraphy/
|
|
195
228
|
├── cli.py # Click CLI entry points
|
|
196
|
-
├── config.py # DATABASE_URL,
|
|
229
|
+
├── config.py # DATABASE_URL, CODEGRAPHY_ROOT, plugin list
|
|
197
230
|
├── db/
|
|
198
231
|
│ ├── schema.py # CREATE TABLE statements (PG + SQLite)
|
|
199
232
|
│ └── store.py # upsert_symbol, upsert_edge, query helpers
|
|
@@ -250,7 +283,7 @@ Detects Django patterns by file naming convention:
|
|
|
250
283
|
|
|
251
284
|
Enable via environment variable:
|
|
252
285
|
```bash
|
|
253
|
-
|
|
286
|
+
CODEGRAPHY_PLUGINS=codegraphy.plugins.django
|
|
254
287
|
```
|
|
255
288
|
|
|
256
289
|
---
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Standalone Python package that parses a codebase into a knowledge graph (PostgreSQL or SQLite) and exposes it as an [MCP](https://modelcontextprotocol.io/) server for Claude Code. Claude calls graph tools instead of `Read` + `Bash(grep)` — cuts exploration token cost by 5–10×.
|
|
4
4
|
|
|
5
|
+
**PyPI:** https://pypi.org/project/codegraphy/
|
|
6
|
+
|
|
5
7
|
**Python:** 3.10+
|
|
6
8
|
**License:** MIT
|
|
7
9
|
|
|
@@ -38,6 +40,37 @@ The base PyPI package keeps SQLite support in the standard library path, so Post
|
|
|
38
40
|
|
|
39
41
|
---
|
|
40
42
|
|
|
43
|
+
## PostgreSQL
|
|
44
|
+
|
|
45
|
+
Install PostgreSQL support:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install 'codegraphy[postgres]'
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Initialize with a PostgreSQL URL:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
codegraphy init --db postgresql://USER:PASSWORD@HOST:PORT/DBNAME
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Example:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
codegraphy init --db postgresql://postgres:postgres@localhost:5432/codegraphy
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or set `DATABASE_URL` once and reuse it:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
export DATABASE_URL=postgresql://postgres:postgres@localhost:5432/codegraphy
|
|
67
|
+
codegraphy init
|
|
68
|
+
codegraphy index .
|
|
69
|
+
codegraphy serve
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
41
74
|
## Quickstart
|
|
42
75
|
|
|
43
76
|
```bash
|
|
@@ -96,9 +129,9 @@ Priority: CLI flag → environment variable → `codegraphy.toml` → defaults.
|
|
|
96
129
|
### Environment Variables
|
|
97
130
|
|
|
98
131
|
```bash
|
|
99
|
-
DATABASE_URL=sqlite:///codegraphy.db
|
|
100
|
-
|
|
101
|
-
|
|
132
|
+
DATABASE_URL=sqlite:///codegraphy.db # or postgresql://localhost/codegraphy
|
|
133
|
+
CODEGRAPHY_ROOT=. # project root for grep fallback
|
|
134
|
+
CODEGRAPHY_PLUGINS=codegraphy.plugins.django
|
|
102
135
|
```
|
|
103
136
|
|
|
104
137
|
### Config File (optional)
|
|
@@ -108,7 +141,7 @@ REPOLENS_PLUGINS=repolens.plugins.django
|
|
|
108
141
|
database_url = "postgresql://localhost/codegraphy"
|
|
109
142
|
root = "."
|
|
110
143
|
exclude = ["migrations", "node_modules", ".venv", "__pycache__"]
|
|
111
|
-
plugins = ["
|
|
144
|
+
plugins = ["codegraphy.plugins.django"]
|
|
112
145
|
```
|
|
113
146
|
|
|
114
147
|
---
|
|
@@ -151,9 +184,9 @@ plugins = ["repolens.plugins.django"]
|
|
|
151
184
|
## Architecture
|
|
152
185
|
|
|
153
186
|
```
|
|
154
|
-
|
|
187
|
+
codegraphy/
|
|
155
188
|
├── cli.py # Click CLI entry points
|
|
156
|
-
├── config.py # DATABASE_URL,
|
|
189
|
+
├── config.py # DATABASE_URL, CODEGRAPHY_ROOT, plugin list
|
|
157
190
|
├── db/
|
|
158
191
|
│ ├── schema.py # CREATE TABLE statements (PG + SQLite)
|
|
159
192
|
│ └── store.py # upsert_symbol, upsert_edge, query helpers
|
|
@@ -210,7 +243,7 @@ Detects Django patterns by file naming convention:
|
|
|
210
243
|
|
|
211
244
|
Enable via environment variable:
|
|
212
245
|
```bash
|
|
213
|
-
|
|
246
|
+
CODEGRAPHY_PLUGINS=codegraphy.plugins.django
|
|
214
247
|
```
|
|
215
248
|
|
|
216
249
|
---
|
|
@@ -10,8 +10,8 @@ def cli():
|
|
|
10
10
|
@click.option('--db', help='Database URL (e.g. postgresql://localhost/codegraphy)')
|
|
11
11
|
def init(db):
|
|
12
12
|
"""Initialize the database schema."""
|
|
13
|
-
import
|
|
14
|
-
from
|
|
13
|
+
import codegraphy.config as config
|
|
14
|
+
from codegraphy.db.store import Store
|
|
15
15
|
|
|
16
16
|
db_url = db or config.DATABASE_URL
|
|
17
17
|
click.echo(f"Initializing schema for {db_url}...")
|
|
@@ -24,16 +24,16 @@ def init(db):
|
|
|
24
24
|
@click.option('--exclude', help='Comma-separated list of directories to exclude')
|
|
25
25
|
def index(path, exclude):
|
|
26
26
|
"""Index a directory into the graph."""
|
|
27
|
-
import
|
|
28
|
-
from
|
|
29
|
-
from
|
|
27
|
+
import codegraphy.config as config
|
|
28
|
+
from codegraphy.db.store import Store
|
|
29
|
+
from codegraphy.indexer.walker import index_path
|
|
30
30
|
|
|
31
31
|
click.echo(f"Indexing {path}...")
|
|
32
32
|
store = Store(config.DATABASE_URL)
|
|
33
33
|
exclude_list = exclude.split(',') if exclude else None
|
|
34
34
|
|
|
35
35
|
# Load plugins
|
|
36
|
-
plugins = [] # TODO: instantiate from config.
|
|
36
|
+
plugins = [] # TODO: instantiate from config.CODEGRAPHY_PLUGINS
|
|
37
37
|
|
|
38
38
|
count = index_path(path, store, plugins, exclude_list)
|
|
39
39
|
click.echo(f"Indexed {count} files.")
|
|
@@ -42,9 +42,8 @@ def index(path, exclude):
|
|
|
42
42
|
def update():
|
|
43
43
|
"""Update index incrementally based on git diff."""
|
|
44
44
|
import subprocess
|
|
45
|
-
import
|
|
46
|
-
from
|
|
47
|
-
from repolens.indexer.walker import index_path
|
|
45
|
+
import codegraphy.config as config
|
|
46
|
+
from codegraphy.db.store import Store
|
|
48
47
|
|
|
49
48
|
click.echo("Updating index...")
|
|
50
49
|
try:
|
|
@@ -63,7 +62,7 @@ def update():
|
|
|
63
62
|
# Re-using index_path is tricky since it takes a root.
|
|
64
63
|
# We can just write a small loop here for the changed files.
|
|
65
64
|
import os
|
|
66
|
-
from
|
|
65
|
+
from codegraphy.indexer.walker import INDEXERS, sha256
|
|
67
66
|
|
|
68
67
|
path = os.path.abspath(file_path)
|
|
69
68
|
if not os.path.exists(path):
|
|
@@ -97,7 +96,7 @@ def update():
|
|
|
97
96
|
@cli.command()
|
|
98
97
|
def serve():
|
|
99
98
|
"""Start the MCP server over stdio."""
|
|
100
|
-
from
|
|
99
|
+
from codegraphy.mcp.server import start_server
|
|
101
100
|
click.echo("Starting MCP server...", err=True)
|
|
102
101
|
start_server()
|
|
103
102
|
|
|
@@ -105,7 +104,7 @@ def serve():
|
|
|
105
104
|
@click.argument('name')
|
|
106
105
|
def search(name):
|
|
107
106
|
"""Search for a symbol in the graph."""
|
|
108
|
-
from
|
|
107
|
+
from codegraphy.mcp.server import search_symbol
|
|
109
108
|
results = search_symbol(name)
|
|
110
109
|
for res in results:
|
|
111
110
|
click.echo(f"[{res['source']}] {res.get('qualified_name') or res.get('file_path')} - {res.get('kind', 'grep')} @ {res['line_start']}")
|
|
@@ -114,7 +113,7 @@ def search(name):
|
|
|
114
113
|
@click.argument('name')
|
|
115
114
|
def usages(name):
|
|
116
115
|
"""Find usages of a symbol."""
|
|
117
|
-
from
|
|
116
|
+
from codegraphy.mcp.server import find_usages
|
|
118
117
|
results = find_usages(name)
|
|
119
118
|
for res in results:
|
|
120
119
|
click.echo(f"[{res['source']}] {res.get('from_qualified') or res.get('file_path')} - {res.get('relation', 'grep')} @ {res['line_start']}")
|
|
@@ -122,8 +121,8 @@ def usages(name):
|
|
|
122
121
|
@cli.command()
|
|
123
122
|
def stats():
|
|
124
123
|
"""Show graph statistics."""
|
|
125
|
-
from
|
|
126
|
-
import
|
|
124
|
+
from codegraphy.db.store import Store
|
|
125
|
+
import codegraphy.config as config
|
|
127
126
|
store = Store(config.DATABASE_URL)
|
|
128
127
|
with store.get_connection() as conn:
|
|
129
128
|
cursor = conn.cursor()
|
|
@@ -2,11 +2,11 @@ import os
|
|
|
2
2
|
|
|
3
3
|
# Default configuration
|
|
4
4
|
DATABASE_URL = os.environ.get("DATABASE_URL", "sqlite:///codegraphy.db")
|
|
5
|
-
|
|
5
|
+
CODEGRAPHY_ROOT = os.environ.get("CODEGRAPHY_ROOT", ".")
|
|
6
6
|
|
|
7
7
|
# Plugin list can be derived from env vars or TOML
|
|
8
|
-
_plugins_env = os.environ.get("
|
|
9
|
-
|
|
8
|
+
_plugins_env = os.environ.get("CODEGRAPHY_PLUGINS", "")
|
|
9
|
+
CODEGRAPHY_PLUGINS = [p.strip() for p in _plugins_env.split(",")] if _plugins_env else []
|
|
10
10
|
|
|
11
11
|
def load_config():
|
|
12
12
|
# Placeholder for loading from codegraphy.toml if needed
|
|
@@ -73,10 +73,21 @@ class Store:
|
|
|
73
73
|
row = cursor.fetchone()
|
|
74
74
|
return row[0] if row else None
|
|
75
75
|
|
|
76
|
+
def _dedupe_symbols(self, symbols: list) -> list:
|
|
77
|
+
deduped = []
|
|
78
|
+
seen = set()
|
|
79
|
+
for symbol in symbols:
|
|
80
|
+
if symbol.qualified_name in seen:
|
|
81
|
+
continue
|
|
82
|
+
seen.add(symbol.qualified_name)
|
|
83
|
+
deduped.append(symbol)
|
|
84
|
+
return deduped
|
|
85
|
+
|
|
76
86
|
def upsert_file(self, file_path: str, git_hash: str, symbols: list, edges: list):
|
|
77
87
|
"""
|
|
78
88
|
Replace symbols and edges for a file.
|
|
79
89
|
"""
|
|
90
|
+
symbols = self._dedupe_symbols(symbols)
|
|
80
91
|
with self.get_connection() as conn:
|
|
81
92
|
cursor = conn.cursor()
|
|
82
93
|
|
|
@@ -44,6 +44,14 @@ class PythonIndexer(BaseIndexer):
|
|
|
44
44
|
return f"{module_path}.{name}" if module_path else name
|
|
45
45
|
return f"{module_path}.{'.'.join(self.current_scope)}.{name}"
|
|
46
46
|
|
|
47
|
+
def get_import_qualname(self, node, imported_name, source_module):
|
|
48
|
+
scope = ".".join(self.current_scope)
|
|
49
|
+
parts = [module_path] if module_path else []
|
|
50
|
+
if scope:
|
|
51
|
+
parts.append(scope)
|
|
52
|
+
parts.extend(["__import__", str(node.lineno), str(node.col_offset), source_module, imported_name])
|
|
53
|
+
return ".".join(parts)
|
|
54
|
+
|
|
47
55
|
def visit_ClassDef(self, node):
|
|
48
56
|
qualname = self.get_qualname(node.name)
|
|
49
57
|
summary = ast.get_docstring(node) or ""
|
|
@@ -108,7 +116,7 @@ class PythonIndexer(BaseIndexer):
|
|
|
108
116
|
for alias in node.names:
|
|
109
117
|
# module level import
|
|
110
118
|
# e.g., import os
|
|
111
|
-
qualname = self.
|
|
119
|
+
qualname = self.get_import_qualname(node, alias.asname or alias.name, alias.name)
|
|
112
120
|
symbols.append(Symbol(
|
|
113
121
|
name=alias.asname or alias.name,
|
|
114
122
|
qualified_name=qualname,
|
|
@@ -129,7 +137,7 @@ class PythonIndexer(BaseIndexer):
|
|
|
129
137
|
if node.module:
|
|
130
138
|
for alias in node.names:
|
|
131
139
|
name = alias.asname or alias.name
|
|
132
|
-
qualname = self.
|
|
140
|
+
qualname = self.get_import_qualname(node, name, node.module)
|
|
133
141
|
symbols.append(Symbol(
|
|
134
142
|
name=name,
|
|
135
143
|
qualified_name=qualname,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from mcp.server.fastmcp import FastMCP
|
|
2
2
|
from ..db.store import Store
|
|
3
|
-
from ..config import DATABASE_URL,
|
|
3
|
+
from ..config import DATABASE_URL, CODEGRAPHY_ROOT
|
|
4
4
|
import subprocess
|
|
5
5
|
|
|
6
6
|
mcp = FastMCP("codegraphy")
|
|
@@ -53,7 +53,7 @@ def search_symbol(name: str, kind: str = None, limit: int = 10, fallback_grep: b
|
|
|
53
53
|
if not results and fallback_grep:
|
|
54
54
|
try:
|
|
55
55
|
# We use subprocess to run grep
|
|
56
|
-
grep_cmd = ['grep', '-rn', '--include=*.py', '--include=*.js', '--include=*.ts', '--include=*.html', name,
|
|
56
|
+
grep_cmd = ['grep', '-rn', '--include=*.py', '--include=*.js', '--include=*.ts', '--include=*.html', name, CODEGRAPHY_ROOT]
|
|
57
57
|
res = subprocess.run(grep_cmd, capture_output=True, text=True)
|
|
58
58
|
if res.stdout:
|
|
59
59
|
for line in res.stdout.splitlines()[:limit]:
|
|
@@ -145,7 +145,7 @@ def find_usages(qualified_name: str, limit: int = 20, fallback_grep: bool = True
|
|
|
145
145
|
if not results and fallback_grep:
|
|
146
146
|
short_name = qualified_name.split('.')[-1]
|
|
147
147
|
try:
|
|
148
|
-
grep_cmd = ['grep', '-rn', short_name,
|
|
148
|
+
grep_cmd = ['grep', '-rn', short_name, CODEGRAPHY_ROOT]
|
|
149
149
|
res = subprocess.run(grep_cmd, capture_output=True, text=True)
|
|
150
150
|
if res.stdout:
|
|
151
151
|
for line in res.stdout.splitlines()[:limit]:
|
|
@@ -276,7 +276,7 @@ def grep_search(pattern: str, include: list[str] = None, exclude: list[str] = No
|
|
|
276
276
|
for exc in exclude:
|
|
277
277
|
cmd.append(f'--exclude-dir={exc}')
|
|
278
278
|
|
|
279
|
-
cmd.extend([pattern,
|
|
279
|
+
cmd.extend([pattern, CODEGRAPHY_ROOT])
|
|
280
280
|
|
|
281
281
|
results = []
|
|
282
282
|
try:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codegraphy
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: SQLite/PostgreSQL codebase knowledge graph and MCP server for Claude Code
|
|
5
5
|
Author: Charan Kulal
|
|
6
6
|
License-Expression: MIT
|
|
@@ -42,6 +42,8 @@ Dynamic: license-file
|
|
|
42
42
|
|
|
43
43
|
Standalone Python package that parses a codebase into a knowledge graph (PostgreSQL or SQLite) and exposes it as an [MCP](https://modelcontextprotocol.io/) server for Claude Code. Claude calls graph tools instead of `Read` + `Bash(grep)` — cuts exploration token cost by 5–10×.
|
|
44
44
|
|
|
45
|
+
**PyPI:** https://pypi.org/project/codegraphy/
|
|
46
|
+
|
|
45
47
|
**Python:** 3.10+
|
|
46
48
|
**License:** MIT
|
|
47
49
|
|
|
@@ -78,6 +80,37 @@ The base PyPI package keeps SQLite support in the standard library path, so Post
|
|
|
78
80
|
|
|
79
81
|
---
|
|
80
82
|
|
|
83
|
+
## PostgreSQL
|
|
84
|
+
|
|
85
|
+
Install PostgreSQL support:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install 'codegraphy[postgres]'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Initialize with a PostgreSQL URL:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
codegraphy init --db postgresql://USER:PASSWORD@HOST:PORT/DBNAME
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Example:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
codegraphy init --db postgresql://postgres:postgres@localhost:5432/codegraphy
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Or set `DATABASE_URL` once and reuse it:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
export DATABASE_URL=postgresql://postgres:postgres@localhost:5432/codegraphy
|
|
107
|
+
codegraphy init
|
|
108
|
+
codegraphy index .
|
|
109
|
+
codegraphy serve
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
81
114
|
## Quickstart
|
|
82
115
|
|
|
83
116
|
```bash
|
|
@@ -136,9 +169,9 @@ Priority: CLI flag → environment variable → `codegraphy.toml` → defaults.
|
|
|
136
169
|
### Environment Variables
|
|
137
170
|
|
|
138
171
|
```bash
|
|
139
|
-
DATABASE_URL=sqlite:///codegraphy.db
|
|
140
|
-
|
|
141
|
-
|
|
172
|
+
DATABASE_URL=sqlite:///codegraphy.db # or postgresql://localhost/codegraphy
|
|
173
|
+
CODEGRAPHY_ROOT=. # project root for grep fallback
|
|
174
|
+
CODEGRAPHY_PLUGINS=codegraphy.plugins.django
|
|
142
175
|
```
|
|
143
176
|
|
|
144
177
|
### Config File (optional)
|
|
@@ -148,7 +181,7 @@ REPOLENS_PLUGINS=repolens.plugins.django
|
|
|
148
181
|
database_url = "postgresql://localhost/codegraphy"
|
|
149
182
|
root = "."
|
|
150
183
|
exclude = ["migrations", "node_modules", ".venv", "__pycache__"]
|
|
151
|
-
plugins = ["
|
|
184
|
+
plugins = ["codegraphy.plugins.django"]
|
|
152
185
|
```
|
|
153
186
|
|
|
154
187
|
---
|
|
@@ -191,9 +224,9 @@ plugins = ["repolens.plugins.django"]
|
|
|
191
224
|
## Architecture
|
|
192
225
|
|
|
193
226
|
```
|
|
194
|
-
|
|
227
|
+
codegraphy/
|
|
195
228
|
├── cli.py # Click CLI entry points
|
|
196
|
-
├── config.py # DATABASE_URL,
|
|
229
|
+
├── config.py # DATABASE_URL, CODEGRAPHY_ROOT, plugin list
|
|
197
230
|
├── db/
|
|
198
231
|
│ ├── schema.py # CREATE TABLE statements (PG + SQLite)
|
|
199
232
|
│ └── store.py # upsert_symbol, upsert_edge, query helpers
|
|
@@ -250,7 +283,7 @@ Detects Django patterns by file naming convention:
|
|
|
250
283
|
|
|
251
284
|
Enable via environment variable:
|
|
252
285
|
```bash
|
|
253
|
-
|
|
286
|
+
CODEGRAPHY_PLUGINS=codegraphy.plugins.django
|
|
254
287
|
```
|
|
255
288
|
|
|
256
289
|
---
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
codegraphy/__init__.py
|
|
5
|
+
codegraphy/cli.py
|
|
6
|
+
codegraphy/config.py
|
|
7
|
+
codegraphy.egg-info/PKG-INFO
|
|
8
|
+
codegraphy.egg-info/SOURCES.txt
|
|
9
|
+
codegraphy.egg-info/dependency_links.txt
|
|
10
|
+
codegraphy.egg-info/entry_points.txt
|
|
11
|
+
codegraphy.egg-info/requires.txt
|
|
12
|
+
codegraphy.egg-info/top_level.txt
|
|
13
|
+
codegraphy/db/__init__.py
|
|
14
|
+
codegraphy/db/schema.py
|
|
15
|
+
codegraphy/db/store.py
|
|
16
|
+
codegraphy/indexer/__init__.py
|
|
17
|
+
codegraphy/indexer/base.py
|
|
18
|
+
codegraphy/indexer/python.py
|
|
19
|
+
codegraphy/indexer/walker.py
|
|
20
|
+
codegraphy/mcp/__init__.py
|
|
21
|
+
codegraphy/mcp/server.py
|
|
22
|
+
codegraphy/plugins/__init__.py
|
|
23
|
+
codegraphy/plugins/base.py
|
|
24
|
+
codegraphy/plugins/django.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
codegraphy
|
|
@@ -37,10 +37,10 @@ html = ["tree-sitter", "tree-sitter-html"]
|
|
|
37
37
|
all = ["psycopg2-binary", "pgvector", "tree-sitter", "tree-sitter-javascript", "tree-sitter-typescript", "tree-sitter-html"]
|
|
38
38
|
|
|
39
39
|
[project.scripts]
|
|
40
|
-
codegraphy = "
|
|
40
|
+
codegraphy = "codegraphy.cli:cli"
|
|
41
41
|
|
|
42
42
|
[tool.setuptools.dynamic]
|
|
43
|
-
version = { attr = "
|
|
43
|
+
version = { attr = "codegraphy.__version__" }
|
|
44
44
|
|
|
45
45
|
[tool.setuptools.packages.find]
|
|
46
|
-
include = ["
|
|
46
|
+
include = ["codegraphy*"]
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
LICENSE
|
|
2
|
-
README.md
|
|
3
|
-
pyproject.toml
|
|
4
|
-
codegraphy.egg-info/PKG-INFO
|
|
5
|
-
codegraphy.egg-info/SOURCES.txt
|
|
6
|
-
codegraphy.egg-info/dependency_links.txt
|
|
7
|
-
codegraphy.egg-info/entry_points.txt
|
|
8
|
-
codegraphy.egg-info/requires.txt
|
|
9
|
-
codegraphy.egg-info/top_level.txt
|
|
10
|
-
repolens/__init__.py
|
|
11
|
-
repolens/cli.py
|
|
12
|
-
repolens/config.py
|
|
13
|
-
repolens/db/__init__.py
|
|
14
|
-
repolens/db/schema.py
|
|
15
|
-
repolens/db/store.py
|
|
16
|
-
repolens/indexer/__init__.py
|
|
17
|
-
repolens/indexer/base.py
|
|
18
|
-
repolens/indexer/python.py
|
|
19
|
-
repolens/indexer/walker.py
|
|
20
|
-
repolens/mcp/__init__.py
|
|
21
|
-
repolens/mcp/server.py
|
|
22
|
-
repolens/plugins/__init__.py
|
|
23
|
-
repolens/plugins/base.py
|
|
24
|
-
repolens/plugins/django.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
repolens
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|