codebrain 0.1.0__py3-none-any.whl

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.
Files changed (44) hide show
  1. codebrain/__init__.py +3 -0
  2. codebrain/__main__.py +6 -0
  3. codebrain/agent_bridge.py +162 -0
  4. codebrain/analyzer.py +943 -0
  5. codebrain/api.py +578 -0
  6. codebrain/api_models.py +102 -0
  7. codebrain/cli.py +1927 -0
  8. codebrain/comprehension.py +1939 -0
  9. codebrain/config.py +46 -0
  10. codebrain/context.py +276 -0
  11. codebrain/export.py +334 -0
  12. codebrain/graph/__init__.py +0 -0
  13. codebrain/graph/query.py +656 -0
  14. codebrain/graph/schema.py +113 -0
  15. codebrain/graph/store.py +295 -0
  16. codebrain/hook_runner.py +71 -0
  17. codebrain/hooks.py +107 -0
  18. codebrain/indexer.py +450 -0
  19. codebrain/llm.py +676 -0
  20. codebrain/logging.py +42 -0
  21. codebrain/mcp_server.py +1635 -0
  22. codebrain/memory/__init__.py +5 -0
  23. codebrain/memory/store.py +270 -0
  24. codebrain/parser/__init__.py +0 -0
  25. codebrain/parser/base.py +27 -0
  26. codebrain/parser/config_parser.py +228 -0
  27. codebrain/parser/models.py +44 -0
  28. codebrain/parser/python_parser.py +658 -0
  29. codebrain/parser/registry.py +144 -0
  30. codebrain/parser/typescript_parser.py +1189 -0
  31. codebrain/parser/typescript_treesitter.py +535 -0
  32. codebrain/py.typed +0 -0
  33. codebrain/resolver.py +171 -0
  34. codebrain/settings.py +88 -0
  35. codebrain/utils.py +59 -0
  36. codebrain/validator.py +563 -0
  37. codebrain/watcher/__init__.py +0 -0
  38. codebrain/watcher/file_watcher.py +173 -0
  39. codebrain-0.1.0.dist-info/METADATA +360 -0
  40. codebrain-0.1.0.dist-info/RECORD +44 -0
  41. codebrain-0.1.0.dist-info/WHEEL +5 -0
  42. codebrain-0.1.0.dist-info/entry_points.txt +6 -0
  43. codebrain-0.1.0.dist-info/licenses/LICENSE +21 -0
  44. codebrain-0.1.0.dist-info/top_level.txt +1 -0
codebrain/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """CodeBrain — persistent structural knowledge graph for codebases."""
2
+
3
+ __version__ = "0.1.0"
codebrain/__main__.py ADDED
@@ -0,0 +1,6 @@
1
+ """Allow running as `python -m codebrain`."""
2
+
3
+ from codebrain.cli import cli
4
+
5
+ if __name__ == "__main__":
6
+ cli()
@@ -0,0 +1,162 @@
1
+ """Agent bridge — makes LLM agents aware of CodeBrain.
2
+
3
+ Generates:
4
+ - CLAUDE.md with codebase context for Claude Code
5
+ - .codebrain/context.json for any agent to consume
6
+ - MCP server configuration snippet
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ from pathlib import Path
13
+
14
+ from codebrain.comprehension import ComprehensionEngine
15
+ from codebrain.config import CODEBRAIN_DIR, DB_FILENAME
16
+ from codebrain.graph.store import GraphStore
17
+
18
+
19
+ def generate_claude_md(repo_root: Path) -> str:
20
+ """Generate a CLAUDE.md file with codebase structural context.
21
+
22
+ This file is automatically read by Claude Code at session start,
23
+ giving the agent instant structural knowledge.
24
+ """
25
+ db_path = repo_root / CODEBRAIN_DIR / DB_FILENAME
26
+ if not db_path.exists():
27
+ return "# CodeBrain not initialized. Run `brain init` first.\n"
28
+
29
+ with GraphStore(db_path) as store:
30
+ comp = ComprehensionEngine(store)
31
+ overview = comp.system_overview()
32
+ hotspots = comp.risk_hotspots(top_n=10)
33
+
34
+ stats = overview["stats"]
35
+ lines: list[str] = []
36
+
37
+ lines.append("# Codebase Structure (auto-generated by CodeBrain)")
38
+ lines.append("")
39
+
40
+ # Structural safety gate — MUST be first so the agent reads it
41
+ lines.append("## Structural Safety Gate")
42
+ lines.append("")
43
+ lines.append("Before writing any file that modifies existing functions, classes, or methods,")
44
+ lines.append("call the `propose_change` MCP tool with the file path and full new content.")
45
+ lines.append("")
46
+ lines.append("- **SAFE**: proceed with writing")
47
+ lines.append("- **CAUTION**: review the warnings, fix if needed, then write")
48
+ lines.append("- **UNSAFE**: do NOT write. Fix the violations first.")
49
+ lines.append("")
50
+ lines.append("Do not skip this step. It prevents you from breaking callers in other files.")
51
+ lines.append("")
52
+
53
+ lines.append(f"**{stats['files']} files, {stats['nodes']} symbols, {stats['edges']} edges**")
54
+ lines.append("")
55
+
56
+ # Packages
57
+ lines.append("## Packages")
58
+ for name, info in overview["packages"].items():
59
+ doc = f" - {info['docstring']}" if info["docstring"] else ""
60
+ deps = f" (depends on: {', '.join(info['depends_on'])})" if info["depends_on"] else ""
61
+ lines.append(f"- **{name}**: {info['file_count']} files, {info['node_count']} symbols{doc}{deps}")
62
+ lines.append("")
63
+
64
+ # Entry points
65
+ if overview["entry_points"]:
66
+ lines.append("## Entry Points")
67
+ for ep in overview["entry_points"]:
68
+ lines.append(f"- `{ep['file_path']}:{ep['line']}`")
69
+ lines.append("")
70
+
71
+ # Risk hotspots
72
+ if hotspots:
73
+ lines.append("## High-Impact Symbols (change with care)")
74
+ for h in hotspots[:10]:
75
+ lines.append(f"- `{h['name']}` ({h['type']}) in `{h['file_path']}` - {h['direct_dependents']} dependents, affects {h['affected_files']} files")
76
+ lines.append("")
77
+
78
+ # MCP instructions
79
+ lines.append("## CodeBrain Tools")
80
+ lines.append("")
81
+ lines.append("This repo has a CodeBrain knowledge graph. Use these CLI commands instead of grepping:")
82
+ lines.append("- `brain search <name>` - find symbols by name")
83
+ lines.append("- `brain context <name> --json` - get full structural context for a symbol")
84
+ lines.append("- `brain impact <name> --json` - see what breaks if a symbol changes")
85
+ lines.append("- `brain validate <file> --json` - validate a file change against the graph")
86
+ lines.append("- `brain module <file> --json` - understand a module's role and dependencies")
87
+ lines.append("- `brain overview --json` - system-level codebase overview")
88
+ lines.append("- `brain hotspots --json` - find riskiest symbols")
89
+ lines.append("")
90
+ lines.append("**Always run `brain validate <file> --json` after modifying a file.**")
91
+ lines.append("")
92
+
93
+ return "\n".join(lines)
94
+
95
+
96
+ def generate_context_json(repo_root: Path) -> dict:
97
+ """Generate .codebrain/context.json for any agent to consume.
98
+
99
+ This is a structured representation of the codebase that can be
100
+ injected into any LLM's context.
101
+ """
102
+ db_path = repo_root / CODEBRAIN_DIR / DB_FILENAME
103
+ if not db_path.exists():
104
+ return {"error": "CodeBrain not initialized"}
105
+
106
+ with GraphStore(db_path) as store:
107
+ comp = ComprehensionEngine(store)
108
+ overview = comp.system_overview()
109
+ hotspots = comp.risk_hotspots(top_n=15)
110
+
111
+ from codebrain.analyzer import StructuralAnalyzer
112
+ analyzer = StructuralAnalyzer(store)
113
+ layers = analyzer.detect_layers()
114
+
115
+ return {
116
+ "codebrain_version": "0.1.0",
117
+ "overview": overview,
118
+ "risk_hotspots": hotspots,
119
+ "architectural_layers": layers,
120
+ "instructions": {
121
+ "before_modifying": "Run `brain validate <file> --json` to check impact.",
122
+ "to_understand_symbol": "Run `brain context <name> --json` instead of reading source.",
123
+ "to_find_code": "Run `brain search <query> --json` instead of grepping.",
124
+ },
125
+ }
126
+
127
+
128
+ def generate_mcp_config(repo_root: Path) -> dict:
129
+ """Generate MCP server configuration for claude_desktop_config.json."""
130
+ return {
131
+ "codebrain": {
132
+ "command": "python",
133
+ "args": ["-m", "codebrain.mcp_server"],
134
+ "cwd": str(repo_root),
135
+ }
136
+ }
137
+
138
+
139
+ def write_agent_files(repo_root: Path) -> list[str]:
140
+ """Write all agent integration files. Returns list of files written."""
141
+ written: list[str] = []
142
+
143
+ # CLAUDE.md at repo root
144
+ claude_md = repo_root / "CLAUDE.md"
145
+ content = generate_claude_md(repo_root)
146
+ claude_md.write_text(content, encoding="utf-8")
147
+ written.append(str(claude_md))
148
+
149
+ # context.json inside .codebrain/
150
+ ctx_path = repo_root / CODEBRAIN_DIR / "context.json"
151
+ ctx_path.parent.mkdir(parents=True, exist_ok=True)
152
+ ctx_data = generate_context_json(repo_root)
153
+ ctx_path.write_text(json.dumps(ctx_data, indent=2), encoding="utf-8")
154
+ written.append(str(ctx_path))
155
+
156
+ # MCP config snippet
157
+ mcp_path = repo_root / CODEBRAIN_DIR / "mcp_config.json"
158
+ mcp_data = generate_mcp_config(repo_root)
159
+ mcp_path.write_text(json.dumps(mcp_data, indent=2), encoding="utf-8")
160
+ written.append(str(mcp_path))
161
+
162
+ return written