neux 0.2.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.
- neux-0.2.0/LICENSE +21 -0
- neux-0.2.0/PKG-INFO +75 -0
- neux-0.2.0/README.md +44 -0
- neux-0.2.0/logo.txt +11 -0
- neux-0.2.0/neux/__init__.py +8 -0
- neux-0.2.0/neux/categorizer.py +141 -0
- neux-0.2.0/neux/cli.py +383 -0
- neux-0.2.0/neux/context_builder.py +222 -0
- neux-0.2.0/neux/dashboard/__init__.py +1 -0
- neux-0.2.0/neux/dashboard/api.py +493 -0
- neux-0.2.0/neux/dashboard/app/dist/assets/index-BLhvlKpc.js +108 -0
- neux-0.2.0/neux/dashboard/app/dist/assets/index-CzFuvGhT.css +1 -0
- neux-0.2.0/neux/dashboard/app/dist/index.html +20 -0
- neux-0.2.0/neux/dashboard/server.py +319 -0
- neux-0.2.0/neux/db.py +519 -0
- neux-0.2.0/neux/detectors/__init__.py +62 -0
- neux-0.2.0/neux/detectors/api_design.py +94 -0
- neux-0.2.0/neux/detectors/base.py +151 -0
- neux-0.2.0/neux/detectors/data_access.py +87 -0
- neux-0.2.0/neux/detectors/error_handling.py +73 -0
- neux-0.2.0/neux/detectors/file_structure.py +103 -0
- neux-0.2.0/neux/detectors/imports.py +163 -0
- neux-0.2.0/neux/detectors/naming.py +178 -0
- neux-0.2.0/neux/detectors/security.py +124 -0
- neux-0.2.0/neux/detectors/state_management.py +64 -0
- neux-0.2.0/neux/detectors/style.py +118 -0
- neux-0.2.0/neux/detectors/testing.py +82 -0
- neux-0.2.0/neux/detectors/ui_component.py +87 -0
- neux-0.2.0/neux/engine.py +778 -0
- neux-0.2.0/neux/generator/__init__.py +1 -0
- neux-0.2.0/neux/generator/claude_md.py +169 -0
- neux-0.2.0/neux/generator/templates/claude_md.j2 +54 -0
- neux-0.2.0/neux/generator/templates/conventions.j2 +22 -0
- neux-0.2.0/neux/generator/templates/module.j2 +52 -0
- neux-0.2.0/neux/generator/templates/patterns.j2 +22 -0
- neux-0.2.0/neux/hook_entry.py +122 -0
- neux-0.2.0/neux/hooks.py +197 -0
- neux-0.2.0/neux/reviewer.py +68 -0
- neux-0.2.0/neux/scanner.py +311 -0
- neux-0.2.0/neux/scanners/__init__.py +1 -0
- neux-0.2.0/neux/scanners/base.py +72 -0
- neux-0.2.0/neux/scanners/python_scanner.py +370 -0
- neux-0.2.0/neux/scanners/sql_scanner.py +285 -0
- neux-0.2.0/neux/scanners/typescript_scanner.py +421 -0
- neux-0.2.0/neux.egg-info/PKG-INFO +75 -0
- neux-0.2.0/neux.egg-info/SOURCES.txt +56 -0
- neux-0.2.0/neux.egg-info/dependency_links.txt +1 -0
- neux-0.2.0/neux.egg-info/entry_points.txt +2 -0
- neux-0.2.0/neux.egg-info/requires.txt +11 -0
- neux-0.2.0/neux.egg-info/top_level.txt +1 -0
- neux-0.2.0/pyproject.toml +82 -0
- neux-0.2.0/setup.cfg +4 -0
- neux-0.2.0/tests/test_db.py +42 -0
- neux-0.2.0/tests/test_detectors.py +99 -0
- neux-0.2.0/tests/test_engine.py +73 -0
- neux-0.2.0/tests/test_generator_cli.py +67 -0
- neux-0.2.0/tests/test_hooks.py +66 -0
- neux-0.2.0/tests/test_scanners.py +73 -0
neux-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 IronDevz
|
|
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.
|
neux-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: neux
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Codebase nervous system — knowledge graph for AI-assisted development
|
|
5
|
+
Author: IronDevz
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/IronDevz/neux
|
|
8
|
+
Project-URL: Repository, https://github.com/IronDevz/neux
|
|
9
|
+
Keywords: claude-code,codebase,graph,ast,context,ai
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Software Development
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: typer>=0.9.0
|
|
21
|
+
Requires-Dist: rich>=13.0
|
|
22
|
+
Requires-Dist: jinja2>=3.1
|
|
23
|
+
Requires-Dist: tree-sitter>=0.23
|
|
24
|
+
Requires-Dist: tree-sitter-language-pack>=0.4
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
29
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# NEUX
|
|
33
|
+
|
|
34
|
+
> Codebase nervous system — knowledge graph for AI-assisted development.
|
|
35
|
+
|
|
36
|
+
NEUX is a Python CLI that builds a relationship graph of your codebase in SQLite,
|
|
37
|
+
detects patterns and conventions automatically (no LLM, pure AST), and integrates
|
|
38
|
+
with [Claude Code](https://claude.com/claude-code) via hooks to inject precise context
|
|
39
|
+
at the moment a tool call is about to modify a file.
|
|
40
|
+
|
|
41
|
+
Companion of [ANVL](https://github.com/juanlumanmx29/anvl). ANVL monitors tokens per
|
|
42
|
+
session. NEUX maps project intelligence.
|
|
43
|
+
|
|
44
|
+
⚒ forged by **IronDevz**
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Features (v0.1)
|
|
49
|
+
|
|
50
|
+
- SQLite knowledge graph with FTS5 full-text search
|
|
51
|
+
- Language scanners: Python (`ast`), React/JS/TS/JSX/TSX (tree-sitter), SQL
|
|
52
|
+
- 12 pattern/convention detectors (naming, imports, security, style, UI, API, data, state, errors, file structure, testing)
|
|
53
|
+
- Claude Code hooks that inject contextual rules before `Write`/`Edit`
|
|
54
|
+
- Auto-generated `CLAUDE.md` with module sub-manuals
|
|
55
|
+
- Impact analysis via recursive CTE (no networkx)
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install -e .
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cd your-project
|
|
67
|
+
neux init # initial scan, generates CLAUDE.md, installs hooks
|
|
68
|
+
neux status # graph stats
|
|
69
|
+
neux impact <target> # what breaks if you change this
|
|
70
|
+
neux scan --changed # incremental rescan
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
MIT © IronDevz
|
neux-0.2.0/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# NEUX
|
|
2
|
+
|
|
3
|
+
> Codebase nervous system — knowledge graph for AI-assisted development.
|
|
4
|
+
|
|
5
|
+
NEUX is a Python CLI that builds a relationship graph of your codebase in SQLite,
|
|
6
|
+
detects patterns and conventions automatically (no LLM, pure AST), and integrates
|
|
7
|
+
with [Claude Code](https://claude.com/claude-code) via hooks to inject precise context
|
|
8
|
+
at the moment a tool call is about to modify a file.
|
|
9
|
+
|
|
10
|
+
Companion of [ANVL](https://github.com/juanlumanmx29/anvl). ANVL monitors tokens per
|
|
11
|
+
session. NEUX maps project intelligence.
|
|
12
|
+
|
|
13
|
+
⚒ forged by **IronDevz**
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Features (v0.1)
|
|
18
|
+
|
|
19
|
+
- SQLite knowledge graph with FTS5 full-text search
|
|
20
|
+
- Language scanners: Python (`ast`), React/JS/TS/JSX/TSX (tree-sitter), SQL
|
|
21
|
+
- 12 pattern/convention detectors (naming, imports, security, style, UI, API, data, state, errors, file structure, testing)
|
|
22
|
+
- Claude Code hooks that inject contextual rules before `Write`/`Edit`
|
|
23
|
+
- Auto-generated `CLAUDE.md` with module sub-manuals
|
|
24
|
+
- Impact analysis via recursive CTE (no networkx)
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install -e .
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cd your-project
|
|
36
|
+
neux init # initial scan, generates CLAUDE.md, installs hooks
|
|
37
|
+
neux status # graph stats
|
|
38
|
+
neux impact <target> # what breaks if you change this
|
|
39
|
+
neux scan --changed # incremental rescan
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
MIT © IronDevz
|
neux-0.2.0/logo.txt
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
███▄ █ ▓█████ █ ██ ▒██ ██▒
|
|
2
|
+
██ ▀█ █ ▓█ ▀ ██ ▓██▒▒▒ █ █ ▒░
|
|
3
|
+
▓██ ▀█ ██▒▒███ ▓██ ▒██░░░ █ ░
|
|
4
|
+
▓██▒ ▐▌██▒▒▓█ ▄ ▓▓█ ░██░ ░ █ █ ▒
|
|
5
|
+
▒██░ ▓██░░▒████▒▒▒█████▓ ▒██▒ ▒██▒
|
|
6
|
+
░ ▒░ ▒ ▒ ░░ ▒░ ░░▒▓▒ ▒ ▒ ▒▒ ░ ░▓ ░
|
|
7
|
+
░ ░░ ░ ▒░ ░ ░ ░░░▒░ ░ ░ ░░ ░▒ ░
|
|
8
|
+
░ ░ ░ ░ ░░░ ░ ░ ░ ░
|
|
9
|
+
░ ░ ░ ░ ░ ░
|
|
10
|
+
⚒ forged by IronDevz
|
|
11
|
+
codebase nervous system v0.1.0
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""TaskCategorizer — classify a user prompt + file path into a task category.
|
|
2
|
+
|
|
3
|
+
Returns one of:
|
|
4
|
+
``style_change`` | ``logic_change`` | ``new_feature`` | ``bug_fix`` | ``refactor`` |
|
|
5
|
+
``test_writing`` | ``api_change`` | ``database_change`` | ``config_change`` | ``general``
|
|
6
|
+
|
|
7
|
+
The categorization is score-based: count keyword hits in the prompt, add a
|
|
8
|
+
path hint (e.g. ``components/`` → ``style_change`` weight bump). No NLP, no LLM.
|
|
9
|
+
Kept deliberately simple so the hook entrypoint can run it without any heavy imports.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
|
|
16
|
+
# Keywords per category — bilingual (Spanish + English) to match how IronDevz
|
|
17
|
+
# developers usually phrase requests.
|
|
18
|
+
CATEGORY_KEYWORDS: dict[str, list[str]] = {
|
|
19
|
+
"style_change": [
|
|
20
|
+
"color", "colour", "style", "styles", "estilo", "estilos", "css", "scss",
|
|
21
|
+
"sass", "theme", "tema", "font", "fuente", "tailwind", "responsive",
|
|
22
|
+
"padding", "margin", "layout", "design", "diseño", "ui", "visual",
|
|
23
|
+
"dark mode", "tipograf", "hover", "border",
|
|
24
|
+
],
|
|
25
|
+
"new_feature": [
|
|
26
|
+
"crear", "nuevo", "nueva", "agregar", "añadir", "implementar",
|
|
27
|
+
"construir", "create", "add", "build", "implement", "feature",
|
|
28
|
+
"introduce", "support for", "soporte para",
|
|
29
|
+
],
|
|
30
|
+
"logic_change": [
|
|
31
|
+
"función", "function", "cambiar", "modificar", "change", "modify",
|
|
32
|
+
"update", "actualizar", "adjust", "ajustar", "transform", "lógica",
|
|
33
|
+
"logic", "algorithm", "algoritmo", "flow", "flujo",
|
|
34
|
+
],
|
|
35
|
+
"bug_fix": [
|
|
36
|
+
"bug", "error", "errors", "errores", "fix", "arreglar", "crash",
|
|
37
|
+
"falla", "broken", "roto", "issue", "problema", "incorrect",
|
|
38
|
+
"incorrecto", "no funciona", "not working", "regression", "regresión",
|
|
39
|
+
],
|
|
40
|
+
"refactor": [
|
|
41
|
+
"refactor", "refactoring", "rename", "renombrar", "reorganizar",
|
|
42
|
+
"reorganize", "cleanup", "limpiar", "extract", "extraer", "simplify",
|
|
43
|
+
"simplificar", "dry", "deduplicate",
|
|
44
|
+
],
|
|
45
|
+
"test_writing": [
|
|
46
|
+
"test", "tests", "prueba", "pruebas", "mock", "fixture", "coverage",
|
|
47
|
+
"spec", "unit test", "integration test", "pytest", "jest", "vitest",
|
|
48
|
+
"assert", "expect",
|
|
49
|
+
],
|
|
50
|
+
"api_change": [
|
|
51
|
+
"endpoint", "endpoints", "api", "ruta", "rutas", "route", "routes",
|
|
52
|
+
"middleware", "auth", "authorization", "rest", "graphql", "request",
|
|
53
|
+
"response", "http", "get", "post", "put", "delete", "patch",
|
|
54
|
+
],
|
|
55
|
+
"database_change": [
|
|
56
|
+
"tabla", "table", "migración", "migration", "modelo", "model",
|
|
57
|
+
"schema", "query", "sql", "database", "base de datos", "column",
|
|
58
|
+
"columna", "index", "índice", "foreign key", "constraint",
|
|
59
|
+
],
|
|
60
|
+
"config_change": [
|
|
61
|
+
"config", "configuration", "configuración", "env", ".env", "docker",
|
|
62
|
+
"deploy", "deployment", "ci", "cd", "workflow", "pipeline",
|
|
63
|
+
"environment variable", "variable de entorno", "pyproject",
|
|
64
|
+
"package.json", "tsconfig", "settings",
|
|
65
|
+
],
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# Path hints: substring → category score bonus
|
|
69
|
+
PATH_HINTS: dict[str, str] = {
|
|
70
|
+
"/components/": "style_change",
|
|
71
|
+
"/styles/": "style_change",
|
|
72
|
+
"/css/": "style_change",
|
|
73
|
+
"theme": "style_change",
|
|
74
|
+
"tailwind": "style_change",
|
|
75
|
+
"/api/": "api_change",
|
|
76
|
+
"/routes/": "api_change",
|
|
77
|
+
"/endpoints/": "api_change",
|
|
78
|
+
"/migrations/": "database_change",
|
|
79
|
+
".sql": "database_change",
|
|
80
|
+
"/models/": "database_change",
|
|
81
|
+
"/tests/": "test_writing",
|
|
82
|
+
"test_": "test_writing",
|
|
83
|
+
".test.": "test_writing",
|
|
84
|
+
".spec.": "test_writing",
|
|
85
|
+
"dockerfile": "config_change",
|
|
86
|
+
".env": "config_change",
|
|
87
|
+
"config": "config_change",
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass(slots=True)
|
|
92
|
+
class Categorization:
|
|
93
|
+
category: str
|
|
94
|
+
score: float
|
|
95
|
+
matched_keywords: list[str] = field(default_factory=list)
|
|
96
|
+
path_hint: str | None = None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class TaskCategorizer:
|
|
100
|
+
"""Score-based categorizer. No external dependencies."""
|
|
101
|
+
|
|
102
|
+
def __init__(
|
|
103
|
+
self,
|
|
104
|
+
keywords: dict[str, list[str]] | None = None,
|
|
105
|
+
path_hints: dict[str, str] | None = None,
|
|
106
|
+
):
|
|
107
|
+
self.keywords = keywords or CATEGORY_KEYWORDS
|
|
108
|
+
self.path_hints = path_hints or PATH_HINTS
|
|
109
|
+
|
|
110
|
+
def categorize(self, prompt: str, file_path: str | None = None) -> Categorization:
|
|
111
|
+
if not prompt and not file_path:
|
|
112
|
+
return Categorization("general", 0.0)
|
|
113
|
+
|
|
114
|
+
lower_prompt = (prompt or "").lower()
|
|
115
|
+
scores: dict[str, float] = {k: 0.0 for k in self.keywords}
|
|
116
|
+
matched: dict[str, list[str]] = {k: [] for k in self.keywords}
|
|
117
|
+
|
|
118
|
+
for category, kws in self.keywords.items():
|
|
119
|
+
for kw in kws:
|
|
120
|
+
if kw in lower_prompt:
|
|
121
|
+
scores[category] += 1.0
|
|
122
|
+
matched[category].append(kw)
|
|
123
|
+
|
|
124
|
+
hint_category: str | None = None
|
|
125
|
+
if file_path:
|
|
126
|
+
lower_path = file_path.lower()
|
|
127
|
+
for substr, cat in self.path_hints.items():
|
|
128
|
+
if substr in lower_path:
|
|
129
|
+
scores[cat] = scores.get(cat, 0.0) + 0.5
|
|
130
|
+
hint_category = cat
|
|
131
|
+
break
|
|
132
|
+
|
|
133
|
+
best = max(scores.items(), key=lambda kv: kv[1])
|
|
134
|
+
if best[1] == 0:
|
|
135
|
+
return Categorization("general", 0.0, path_hint=hint_category)
|
|
136
|
+
return Categorization(
|
|
137
|
+
category=best[0],
|
|
138
|
+
score=best[1],
|
|
139
|
+
matched_keywords=matched[best[0]],
|
|
140
|
+
path_hint=hint_category,
|
|
141
|
+
)
|