codebread 1.0.5__tar.gz → 1.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.
Files changed (48) hide show
  1. codebread-1.1.0/PKG-INFO +274 -0
  2. codebread-1.1.0/README.md +258 -0
  3. codebread-1.1.0/codebread/__init__.py +40 -0
  4. {codebread-1.0.5 → codebread-1.1.0}/codebread/cli.py +13 -0
  5. codebread-1.1.0/codebread/context.py +170 -0
  6. {codebread-1.0.5 → codebread-1.1.0}/codebread/web/app.js +562 -52
  7. {codebread-1.0.5 → codebread-1.1.0}/codebread/web/index.html +93 -29
  8. codebread-1.1.0/codebread/web/style.css +887 -0
  9. codebread-1.1.0/codebread.egg-info/PKG-INFO +274 -0
  10. {codebread-1.0.5 → codebread-1.1.0}/codebread.egg-info/SOURCES.txt +2 -0
  11. {codebread-1.0.5 → codebread-1.1.0}/pyproject.toml +1 -1
  12. codebread-1.1.0/tests/test_context.py +18 -0
  13. {codebread-1.0.5 → codebread-1.1.0}/tests/test_server.py +12 -0
  14. codebread-1.1.0/tests/test_version.py +24 -0
  15. codebread-1.0.5/PKG-INFO +0 -356
  16. codebread-1.0.5/README.md +0 -340
  17. codebread-1.0.5/codebread/__init__.py +0 -36
  18. codebread-1.0.5/codebread/web/style.css +0 -623
  19. codebread-1.0.5/codebread.egg-info/PKG-INFO +0 -356
  20. codebread-1.0.5/tests/test_version.py +0 -14
  21. {codebread-1.0.5 → codebread-1.1.0}/LICENSE +0 -0
  22. {codebread-1.0.5 → codebread-1.1.0}/codebread/analyzer.py +0 -0
  23. {codebread-1.0.5 → codebread-1.1.0}/codebread/classifier.py +0 -0
  24. {codebread-1.0.5 → codebread-1.1.0}/codebread/connections.py +0 -0
  25. {codebread-1.0.5 → codebread-1.1.0}/codebread/deobfuscate.py +0 -0
  26. {codebread-1.0.5 → codebread-1.1.0}/codebread/diff.py +0 -0
  27. {codebread-1.0.5 → codebread-1.1.0}/codebread/export.py +0 -0
  28. {codebread-1.0.5 → codebread-1.1.0}/codebread/languages.py +0 -0
  29. {codebread-1.0.5 → codebread-1.1.0}/codebread/models.py +0 -0
  30. {codebread-1.0.5 → codebread-1.1.0}/codebread/parsers/__init__.py +0 -0
  31. {codebread-1.0.5 → codebread-1.1.0}/codebread/parsers/generic_parser.py +0 -0
  32. {codebread-1.0.5 → codebread-1.1.0}/codebread/parsers/javascript_parser.py +0 -0
  33. {codebread-1.0.5 → codebread-1.1.0}/codebread/parsers/python_parser.py +0 -0
  34. {codebread-1.0.5 → codebread-1.1.0}/codebread/scanner.py +0 -0
  35. {codebread-1.0.5 → codebread-1.1.0}/codebread/server.py +0 -0
  36. {codebread-1.0.5 → codebread-1.1.0}/codebread.egg-info/dependency_links.txt +0 -0
  37. {codebread-1.0.5 → codebread-1.1.0}/codebread.egg-info/entry_points.txt +0 -0
  38. {codebread-1.0.5 → codebread-1.1.0}/codebread.egg-info/requires.txt +0 -0
  39. {codebread-1.0.5 → codebread-1.1.0}/codebread.egg-info/top_level.txt +0 -0
  40. {codebread-1.0.5 → codebread-1.1.0}/setup.cfg +0 -0
  41. {codebread-1.0.5 → codebread-1.1.0}/tests/test_analyzer.py +0 -0
  42. {codebread-1.0.5 → codebread-1.1.0}/tests/test_config_parser.py +0 -0
  43. {codebread-1.0.5 → codebread-1.1.0}/tests/test_connections.py +0 -0
  44. {codebread-1.0.5 → codebread-1.1.0}/tests/test_deobfuscate.py +0 -0
  45. {codebread-1.0.5 → codebread-1.1.0}/tests/test_generic_parser.py +0 -0
  46. {codebread-1.0.5 → codebread-1.1.0}/tests/test_javascript_parser.py +0 -0
  47. {codebread-1.0.5 → codebread-1.1.0}/tests/test_python_parser.py +0 -0
  48. {codebread-1.0.5 → codebread-1.1.0}/tests/test_scanner.py +0 -0
@@ -0,0 +1,274 @@
1
+ Metadata-Version: 2.4
2
+ Name: codebread
3
+ Version: 1.1.0
4
+ Summary: Interactive codebase analyzer & visualizer — slice open a project and see how it's wired together.
5
+ Author: Danial Irsyad
6
+ License: MIT
7
+ Keywords: codebase,analyzer,visualizer,call-graph,architecture
8
+ Requires-Python: >=3.9
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Provides-Extra: full
12
+ Requires-Dist: pathspec>=0.11; extra == "full"
13
+ Provides-Extra: test
14
+ Requires-Dist: pytest>=7; extra == "test"
15
+ Dynamic: license-file
16
+
17
+ <p align="center">
18
+ <img src="https://cdn.jsdelivr.net/gh/honow48-tech/CodeBread@main/assets/logo-wordmark.png" alt="CodeBread" width="320">
19
+ </p>
20
+
21
+ <p align="center">
22
+ <b>See how any codebase is wired together.</b><br>
23
+ Files, functions, API routes and database tables, mapped in your browser.
24
+ </p>
25
+
26
+ <p align="center">
27
+ <a href="https://pypi.org/project/codebread/"><img alt="PyPI" src="https://img.shields.io/pypi/v/codebread?color=b0541c&label=pypi"></a>
28
+ <a href="https://github.com/honow48-tech/CodeBread/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/honow48-tech/CodeBread/actions/workflows/ci.yml/badge.svg"></a>
29
+ <img alt="Python 3.9+" src="https://img.shields.io/badge/python-3.9%2B-5f5c55">
30
+ <img alt="No dependencies" src="https://img.shields.io/badge/dependencies-none-5f5c55">
31
+ <img alt="MIT" src="https://img.shields.io/badge/license-MIT-5f5c55">
32
+ </p>
33
+
34
+ <p align="center">
35
+ <img src="https://cdn.jsdelivr.net/gh/honow48-tech/CodeBread@main/assets/overview.gif" alt="The CodeBread overview: project totals, a language breakdown, and a file table that previews each file on hover" width="880">
36
+ </p>
37
+
38
+ ## Quick start
39
+
40
+ ```bash
41
+ pip install codebread
42
+ codebread --path ./my-project
43
+ ```
44
+
45
+ A browser tab opens with the project already mapped. Everything runs on your
46
+ machine: nothing is uploaded, and nothing in the scanned project is executed.
47
+
48
+ ## What you get
49
+
50
+ ### Overview
51
+
52
+ Totals, a breakdown of the project by language, and every file in one table.
53
+ Hover a row to preview what the file contains and what it talks to.
54
+
55
+ ### Connections
56
+
57
+ Pick a file to see what uses it, what it uses, and which functions are
58
+ linked. Click a neighbour to follow the trail; a breadcrumb takes you back.
59
+ It only ever draws one file's neighbourhood, so it stays readable on a
60
+ project with thousands of files.
61
+
62
+ <p align="center">
63
+ <img src="https://cdn.jsdelivr.net/gh/honow48-tech/CodeBread@main/assets/connections.gif" alt="The Connections page: callers on the left, the selected file in the middle, the files it uses on the right, joined function to function" width="880">
64
+ </p>
65
+
66
+ ### Map
67
+
68
+ The whole project as a graph. Click a file to open it into its functions.
69
+ Click a function to light up everything it calls and everything that calls
70
+ it, all the way from a frontend `fetch()` to the database table.
71
+
72
+ <p align="center">
73
+ <img src="https://cdn.jsdelivr.net/gh/honow48-tech/CodeBread@main/assets/map.png" alt="The Map view with one function selected and its call chain highlighted" width="880">
74
+ </p>
75
+
76
+ ### Code
77
+
78
+ Read any file with an outline and syntax highlighting, without leaving the page.
79
+
80
+ <p align="center">
81
+ <img src="https://cdn.jsdelivr.net/gh/honow48-tech/CodeBread@main/assets/code.png" alt="The Code view: file tree, function outline and highlighted source" width="880">
82
+ </p>
83
+
84
+ ### Context for AI assistants
85
+
86
+ An AI assistant that reads every file to understand a project spends most of
87
+ its tokens on code it never needed. CodeBread can write the map down instead:
88
+
89
+ ```bash
90
+ codebread --path ./my-project --md
91
+ ```
92
+
93
+ This creates `CODEBREAD.md` in the project: every route, table and function,
94
+ and who calls whom. On CodeBread's own repo it's about **13k tokens instead
95
+ of 83k** for the full source. The report has the same file one click away:
96
+ **Copy for AI** or **Download .md**.
97
+
98
+ ## Commands
99
+
100
+ | Flag | What it does |
101
+ |---|---|
102
+ | `--path, -p PATH` | Folder to scan (asks if you leave it out) |
103
+ | `--md [FILE]` | Write the AI context file (default: `CODEBREAD.md` in the scanned folder) |
104
+ | `--html FILE` | Export the report as one self-contained HTML file you can share |
105
+ | `--json FILE` | Save the scan as JSON |
106
+ | `--load FILE` | Open a saved JSON scan without scanning again |
107
+ | `--diff OLD NEW` | Compare two saved scans and print what changed |
108
+ | `--port 8137` | Port for the local server |
109
+ | `--no-open` | Don't open the browser |
110
+ | `--no-serve` | Scan and export only, no server |
111
+ | `--version` | Print the version |
112
+
113
+ Sharing a report with someone who doesn't have CodeBread:
114
+
115
+ ```bash
116
+ codebread --path . --html report.html --no-serve
117
+ ```
118
+
119
+ ## Languages
120
+
121
+ | Language | Functions | Routes | API calls | Database |
122
+ |---|:---:|:---:|:---:|:---:|
123
+ | Python | ✓ | Flask, FastAPI, Django | requests, httpx, aiohttp | SQLAlchemy, Django, peewee |
124
+ | JavaScript / TypeScript | ✓ | Express, Fastify, Koa, NestJS | fetch, axios | Prisma, Mongoose, Sequelize, Knex, TypeORM |
125
+ | Vue / Svelte | ✓ | same as JS | fetch, axios | same as JS |
126
+ | PHP | ✓ | Laravel | – | raw SQL |
127
+ | Java | ✓ | Spring | – | raw SQL |
128
+ | C# | ✓ | ASP.NET | – | raw SQL |
129
+ | Go | ✓ | Gin, net/http | – | raw SQL |
130
+ | Ruby | ✓ | Rails, Sinatra | – | raw SQL |
131
+ | SQL | – | – | – | `CREATE TABLE` schemas |
132
+
133
+ Files in other languages still appear in the file list, marked as unsupported.
134
+
135
+ <details>
136
+ <summary><b>Full parser details</b></summary>
137
+
138
+ <br>
139
+
140
+ Python is parsed with the standard-library `ast` module, so it also gets
141
+ parameter types, return types and docstrings. Every other language uses
142
+ structural regex with brace matching and gets parameter names only.
143
+
144
+ | Language | Parser | Functions | Classes | Routes | API calls | ORM models | Raw SQL | Call graph | Page links |
145
+ |---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
146
+ | Python | `ast` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | – |
147
+ | JS / TS / JSX / TSX | regex | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | – |
148
+ | Vue / Svelte | regex, `<script>` only | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | – |
149
+ | Java | regex | ✓ | ✓ | ✓ | – | – | ✓ | ✓ | – |
150
+ | C# | regex | ✓ | ✓ | ✓ | – | – | ✓ | ✓ | – |
151
+ | Go | regex | ✓ | structs | ✓ | – | – | ✓ | ✓ | – |
152
+ | PHP | regex | ✓ | ✓ | ✓ | – | – | ✓ | ✓ | ✓ |
153
+ | Ruby | regex | ✓ | ✓ | ✓ | – | – | ✓ | ✓ | ✓ |
154
+ | SQL | regex | – | – | – | – | tables + columns | ✓ | – | – |
155
+ | Config (`.env`, json, yaml, toml, ini, xml) | key scan | – | – | – | – | – | – | – | – |
156
+
157
+ Config files are only scanned for database connection settings, and
158
+ credentials are always masked. Vue and Svelte templates (`@click`, `v-on`)
159
+ aren't parsed, only the `<script>` block.
160
+
161
+ </details>
162
+
163
+ ## How it works
164
+
165
+ CodeBread reads your files and never runs them. It finds functions, routes
166
+ and tables, then matches them up: a `fetch("/api/users")` in the frontend is
167
+ linked to the handler that serves `GET /api/users`, and that handler to the
168
+ `users` table it queries.
169
+
170
+ <details>
171
+ <summary><b>Layers, unused code and call cycles</b></summary>
172
+
173
+ <br>
174
+
175
+ - **Layers.** Each file is scored as frontend, backend, database or config
176
+ from its imports (React, Flask, Prisma…), its folder (`/client`,
177
+ `/server`, `/models`…) and what it contains (routes, models). Files that
178
+ don't clearly fit are left as *Unclassified* rather than guessed.
179
+ - **Unused functions.** Functions nothing calls are flagged, except route
180
+ handlers and entry points like `main` and test functions. It's a starting
181
+ point for finding dead code, not proof: calls the parser can't see are
182
+ missed.
183
+ - **Call cycles.** Functions that call each other in a loop are flagged on
184
+ the map and listed with the warnings.
185
+
186
+ </details>
187
+
188
+ <details>
189
+ <summary><b>Decoding obfuscated code</b></summary>
190
+
191
+ <br>
192
+
193
+ Some code, often bought or "nulled" PHP scripts, hides its strings behind
194
+ hex escapes, `chr()` arithmetic, base64 or junk statements. CodeBread decodes
195
+ these **without running anything**: it only evaluates integer literals and
196
+ basic operators inside a known decode call (`chr(...)`, `base64_decode(...)`),
197
+ and refuses anything else. Decoded values are underlined in the code view
198
+ (hover to see the original), and files with findings get a 🔓 badge.
199
+
200
+ | Language | Hex | Octal | Unicode | Char codes | Base64 | Junk code |
201
+ |---|:---:|:---:|:---:|:---:|:---:|:---:|
202
+ | Python | ✓ | ✓ | ✓ | `chr()` | `b64decode` | – |
203
+ | JS / TS / Vue / Svelte | ✓ | ✓ | ✓ | `fromCharCode` | `atob` | ✓ |
204
+ | Java | – | ✓ | ✓ | `(char)` | `Base64` | ✓ |
205
+ | C# | ✓ | – | ✓ | `(char)` | `FromBase64String` | ✓ |
206
+ | Go | ✓ | ✓ | ✓ | `rune()` | `base64` | ✓ |
207
+ | PHP | ✓ | ✓ | `\u{}` | `chr()` | `base64_decode` | ✓ |
208
+ | Ruby | ✓ | ✓ | ✓ | `.chr` | `decode64` | – |
209
+
210
+ Decoded text goes through the same credential masking as config files.
211
+ Junk-code detection needs `;`-terminated statements, so it's off for Python
212
+ and Ruby rather than guessing.
213
+
214
+ </details>
215
+
216
+ ## Safety
217
+
218
+ - Read-only. Nothing in the scanned project is ever executed.
219
+ - Secrets found in `.env` and config files are masked before they reach the
220
+ report, the JSON export or the AI context file.
221
+ - Runs on `localhost` only. No network calls, no telemetry.
222
+
223
+ Found a security issue? Please follow [SECURITY.md](SECURITY.md) instead of
224
+ opening a public issue.
225
+
226
+ ## Development
227
+
228
+ ```bash
229
+ git clone https://github.com/honow48-tech/CodeBread.git
230
+ cd CodeBread
231
+ pip install -e ".[full,test]"
232
+ pytest -q
233
+ ```
234
+
235
+ No build step: the analyzer is Python's standard library, and the UI is three
236
+ plain files in [`codebread/web/`](codebread/web) (HTML, CSS and vanilla
237
+ JavaScript). `pathspec` in the `full` extra is optional and only improves
238
+ `.gitignore` matching.
239
+
240
+ <details>
241
+ <summary><b>Project layout</b></summary>
242
+
243
+ ```
244
+ codebread.py run without installing: python codebread.py --path .
245
+ codebread/
246
+ cli.py command-line flags
247
+ scanner.py walks the folder, respects .gitignore
248
+ languages.py language detection
249
+ parsers/ Python (ast), JS/TS/Vue, and everything else
250
+ classifier.py frontend / backend / database / config scoring
251
+ connections.py call graph, API-to-route and function-to-table links
252
+ deobfuscate.py static decoding of obfuscated literals
253
+ analyzer.py runs the pipeline
254
+ context.py the AI context Markdown
255
+ diff.py compares two saved scans
256
+ export.py JSON and single-file HTML export
257
+ server.py local web server
258
+ web/ the UI
259
+ tests/ pytest suite with a small fixture project per language
260
+ ```
261
+
262
+ </details>
263
+
264
+ ## Contributing
265
+
266
+ Issues and pull requests are welcome, especially parser improvements for more
267
+ frameworks. Two rules keep the project easy to run: the core stays on the
268
+ Python standard library, and the UI stays plain JavaScript with no build
269
+ step. Please run `pytest -q` and add a fixture under `tests/` for new parser
270
+ behaviour.
271
+
272
+ ## License
273
+
274
+ [MIT](LICENSE)
@@ -0,0 +1,258 @@
1
+ <p align="center">
2
+ <img src="https://cdn.jsdelivr.net/gh/honow48-tech/CodeBread@main/assets/logo-wordmark.png" alt="CodeBread" width="320">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <b>See how any codebase is wired together.</b><br>
7
+ Files, functions, API routes and database tables, mapped in your browser.
8
+ </p>
9
+
10
+ <p align="center">
11
+ <a href="https://pypi.org/project/codebread/"><img alt="PyPI" src="https://img.shields.io/pypi/v/codebread?color=b0541c&label=pypi"></a>
12
+ <a href="https://github.com/honow48-tech/CodeBread/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/honow48-tech/CodeBread/actions/workflows/ci.yml/badge.svg"></a>
13
+ <img alt="Python 3.9+" src="https://img.shields.io/badge/python-3.9%2B-5f5c55">
14
+ <img alt="No dependencies" src="https://img.shields.io/badge/dependencies-none-5f5c55">
15
+ <img alt="MIT" src="https://img.shields.io/badge/license-MIT-5f5c55">
16
+ </p>
17
+
18
+ <p align="center">
19
+ <img src="https://cdn.jsdelivr.net/gh/honow48-tech/CodeBread@main/assets/overview.gif" alt="The CodeBread overview: project totals, a language breakdown, and a file table that previews each file on hover" width="880">
20
+ </p>
21
+
22
+ ## Quick start
23
+
24
+ ```bash
25
+ pip install codebread
26
+ codebread --path ./my-project
27
+ ```
28
+
29
+ A browser tab opens with the project already mapped. Everything runs on your
30
+ machine: nothing is uploaded, and nothing in the scanned project is executed.
31
+
32
+ ## What you get
33
+
34
+ ### Overview
35
+
36
+ Totals, a breakdown of the project by language, and every file in one table.
37
+ Hover a row to preview what the file contains and what it talks to.
38
+
39
+ ### Connections
40
+
41
+ Pick a file to see what uses it, what it uses, and which functions are
42
+ linked. Click a neighbour to follow the trail; a breadcrumb takes you back.
43
+ It only ever draws one file's neighbourhood, so it stays readable on a
44
+ project with thousands of files.
45
+
46
+ <p align="center">
47
+ <img src="https://cdn.jsdelivr.net/gh/honow48-tech/CodeBread@main/assets/connections.gif" alt="The Connections page: callers on the left, the selected file in the middle, the files it uses on the right, joined function to function" width="880">
48
+ </p>
49
+
50
+ ### Map
51
+
52
+ The whole project as a graph. Click a file to open it into its functions.
53
+ Click a function to light up everything it calls and everything that calls
54
+ it, all the way from a frontend `fetch()` to the database table.
55
+
56
+ <p align="center">
57
+ <img src="https://cdn.jsdelivr.net/gh/honow48-tech/CodeBread@main/assets/map.png" alt="The Map view with one function selected and its call chain highlighted" width="880">
58
+ </p>
59
+
60
+ ### Code
61
+
62
+ Read any file with an outline and syntax highlighting, without leaving the page.
63
+
64
+ <p align="center">
65
+ <img src="https://cdn.jsdelivr.net/gh/honow48-tech/CodeBread@main/assets/code.png" alt="The Code view: file tree, function outline and highlighted source" width="880">
66
+ </p>
67
+
68
+ ### Context for AI assistants
69
+
70
+ An AI assistant that reads every file to understand a project spends most of
71
+ its tokens on code it never needed. CodeBread can write the map down instead:
72
+
73
+ ```bash
74
+ codebread --path ./my-project --md
75
+ ```
76
+
77
+ This creates `CODEBREAD.md` in the project: every route, table and function,
78
+ and who calls whom. On CodeBread's own repo it's about **13k tokens instead
79
+ of 83k** for the full source. The report has the same file one click away:
80
+ **Copy for AI** or **Download .md**.
81
+
82
+ ## Commands
83
+
84
+ | Flag | What it does |
85
+ |---|---|
86
+ | `--path, -p PATH` | Folder to scan (asks if you leave it out) |
87
+ | `--md [FILE]` | Write the AI context file (default: `CODEBREAD.md` in the scanned folder) |
88
+ | `--html FILE` | Export the report as one self-contained HTML file you can share |
89
+ | `--json FILE` | Save the scan as JSON |
90
+ | `--load FILE` | Open a saved JSON scan without scanning again |
91
+ | `--diff OLD NEW` | Compare two saved scans and print what changed |
92
+ | `--port 8137` | Port for the local server |
93
+ | `--no-open` | Don't open the browser |
94
+ | `--no-serve` | Scan and export only, no server |
95
+ | `--version` | Print the version |
96
+
97
+ Sharing a report with someone who doesn't have CodeBread:
98
+
99
+ ```bash
100
+ codebread --path . --html report.html --no-serve
101
+ ```
102
+
103
+ ## Languages
104
+
105
+ | Language | Functions | Routes | API calls | Database |
106
+ |---|:---:|:---:|:---:|:---:|
107
+ | Python | ✓ | Flask, FastAPI, Django | requests, httpx, aiohttp | SQLAlchemy, Django, peewee |
108
+ | JavaScript / TypeScript | ✓ | Express, Fastify, Koa, NestJS | fetch, axios | Prisma, Mongoose, Sequelize, Knex, TypeORM |
109
+ | Vue / Svelte | ✓ | same as JS | fetch, axios | same as JS |
110
+ | PHP | ✓ | Laravel | – | raw SQL |
111
+ | Java | ✓ | Spring | – | raw SQL |
112
+ | C# | ✓ | ASP.NET | – | raw SQL |
113
+ | Go | ✓ | Gin, net/http | – | raw SQL |
114
+ | Ruby | ✓ | Rails, Sinatra | – | raw SQL |
115
+ | SQL | – | – | – | `CREATE TABLE` schemas |
116
+
117
+ Files in other languages still appear in the file list, marked as unsupported.
118
+
119
+ <details>
120
+ <summary><b>Full parser details</b></summary>
121
+
122
+ <br>
123
+
124
+ Python is parsed with the standard-library `ast` module, so it also gets
125
+ parameter types, return types and docstrings. Every other language uses
126
+ structural regex with brace matching and gets parameter names only.
127
+
128
+ | Language | Parser | Functions | Classes | Routes | API calls | ORM models | Raw SQL | Call graph | Page links |
129
+ |---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
130
+ | Python | `ast` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | – |
131
+ | JS / TS / JSX / TSX | regex | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | – |
132
+ | Vue / Svelte | regex, `<script>` only | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | – |
133
+ | Java | regex | ✓ | ✓ | ✓ | – | – | ✓ | ✓ | – |
134
+ | C# | regex | ✓ | ✓ | ✓ | – | – | ✓ | ✓ | – |
135
+ | Go | regex | ✓ | structs | ✓ | – | – | ✓ | ✓ | – |
136
+ | PHP | regex | ✓ | ✓ | ✓ | – | – | ✓ | ✓ | ✓ |
137
+ | Ruby | regex | ✓ | ✓ | ✓ | – | – | ✓ | ✓ | ✓ |
138
+ | SQL | regex | – | – | – | – | tables + columns | ✓ | – | – |
139
+ | Config (`.env`, json, yaml, toml, ini, xml) | key scan | – | – | – | – | – | – | – | – |
140
+
141
+ Config files are only scanned for database connection settings, and
142
+ credentials are always masked. Vue and Svelte templates (`@click`, `v-on`)
143
+ aren't parsed, only the `<script>` block.
144
+
145
+ </details>
146
+
147
+ ## How it works
148
+
149
+ CodeBread reads your files and never runs them. It finds functions, routes
150
+ and tables, then matches them up: a `fetch("/api/users")` in the frontend is
151
+ linked to the handler that serves `GET /api/users`, and that handler to the
152
+ `users` table it queries.
153
+
154
+ <details>
155
+ <summary><b>Layers, unused code and call cycles</b></summary>
156
+
157
+ <br>
158
+
159
+ - **Layers.** Each file is scored as frontend, backend, database or config
160
+ from its imports (React, Flask, Prisma…), its folder (`/client`,
161
+ `/server`, `/models`…) and what it contains (routes, models). Files that
162
+ don't clearly fit are left as *Unclassified* rather than guessed.
163
+ - **Unused functions.** Functions nothing calls are flagged, except route
164
+ handlers and entry points like `main` and test functions. It's a starting
165
+ point for finding dead code, not proof: calls the parser can't see are
166
+ missed.
167
+ - **Call cycles.** Functions that call each other in a loop are flagged on
168
+ the map and listed with the warnings.
169
+
170
+ </details>
171
+
172
+ <details>
173
+ <summary><b>Decoding obfuscated code</b></summary>
174
+
175
+ <br>
176
+
177
+ Some code, often bought or "nulled" PHP scripts, hides its strings behind
178
+ hex escapes, `chr()` arithmetic, base64 or junk statements. CodeBread decodes
179
+ these **without running anything**: it only evaluates integer literals and
180
+ basic operators inside a known decode call (`chr(...)`, `base64_decode(...)`),
181
+ and refuses anything else. Decoded values are underlined in the code view
182
+ (hover to see the original), and files with findings get a 🔓 badge.
183
+
184
+ | Language | Hex | Octal | Unicode | Char codes | Base64 | Junk code |
185
+ |---|:---:|:---:|:---:|:---:|:---:|:---:|
186
+ | Python | ✓ | ✓ | ✓ | `chr()` | `b64decode` | – |
187
+ | JS / TS / Vue / Svelte | ✓ | ✓ | ✓ | `fromCharCode` | `atob` | ✓ |
188
+ | Java | – | ✓ | ✓ | `(char)` | `Base64` | ✓ |
189
+ | C# | ✓ | – | ✓ | `(char)` | `FromBase64String` | ✓ |
190
+ | Go | ✓ | ✓ | ✓ | `rune()` | `base64` | ✓ |
191
+ | PHP | ✓ | ✓ | `\u{}` | `chr()` | `base64_decode` | ✓ |
192
+ | Ruby | ✓ | ✓ | ✓ | `.chr` | `decode64` | – |
193
+
194
+ Decoded text goes through the same credential masking as config files.
195
+ Junk-code detection needs `;`-terminated statements, so it's off for Python
196
+ and Ruby rather than guessing.
197
+
198
+ </details>
199
+
200
+ ## Safety
201
+
202
+ - Read-only. Nothing in the scanned project is ever executed.
203
+ - Secrets found in `.env` and config files are masked before they reach the
204
+ report, the JSON export or the AI context file.
205
+ - Runs on `localhost` only. No network calls, no telemetry.
206
+
207
+ Found a security issue? Please follow [SECURITY.md](SECURITY.md) instead of
208
+ opening a public issue.
209
+
210
+ ## Development
211
+
212
+ ```bash
213
+ git clone https://github.com/honow48-tech/CodeBread.git
214
+ cd CodeBread
215
+ pip install -e ".[full,test]"
216
+ pytest -q
217
+ ```
218
+
219
+ No build step: the analyzer is Python's standard library, and the UI is three
220
+ plain files in [`codebread/web/`](codebread/web) (HTML, CSS and vanilla
221
+ JavaScript). `pathspec` in the `full` extra is optional and only improves
222
+ `.gitignore` matching.
223
+
224
+ <details>
225
+ <summary><b>Project layout</b></summary>
226
+
227
+ ```
228
+ codebread.py run without installing: python codebread.py --path .
229
+ codebread/
230
+ cli.py command-line flags
231
+ scanner.py walks the folder, respects .gitignore
232
+ languages.py language detection
233
+ parsers/ Python (ast), JS/TS/Vue, and everything else
234
+ classifier.py frontend / backend / database / config scoring
235
+ connections.py call graph, API-to-route and function-to-table links
236
+ deobfuscate.py static decoding of obfuscated literals
237
+ analyzer.py runs the pipeline
238
+ context.py the AI context Markdown
239
+ diff.py compares two saved scans
240
+ export.py JSON and single-file HTML export
241
+ server.py local web server
242
+ web/ the UI
243
+ tests/ pytest suite with a small fixture project per language
244
+ ```
245
+
246
+ </details>
247
+
248
+ ## Contributing
249
+
250
+ Issues and pull requests are welcome, especially parser improvements for more
251
+ frameworks. Two rules keep the project easy to run: the core stays on the
252
+ Python standard library, and the UI stays plain JavaScript with no build
253
+ step. Please run `pytest -q` and add a fixture under `tests/` for new parser
254
+ behaviour.
255
+
256
+ ## License
257
+
258
+ [MIT](LICENSE)
@@ -0,0 +1,40 @@
1
+ """CodeBread — slice open a codebase and see its internal structure."""
2
+ from __future__ import annotations
3
+
4
+ import os
5
+ import re
6
+
7
+
8
+ def _read_version() -> str:
9
+ """Single source of truth: pyproject.toml's [project] version.
10
+
11
+ A source checkout (pyproject.toml sitting next to the package) wins:
12
+ an editable `pip install -e .` freezes its metadata at install time,
13
+ so after a version bump importlib.metadata keeps reporting the old
14
+ number until you reinstall. Wheel installs have no pyproject.toml
15
+ beside them and fall through to their own (always correct) metadata.
16
+ No toml parser needed for one `version = "..."` line — keeps the
17
+ zero-dependency promise.
18
+ """
19
+ root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
20
+ try:
21
+ with open(os.path.join(root, "pyproject.toml"), encoding="utf-8") as f:
22
+ text = f.read()
23
+ if re.search(r"""^name\s*=\s*["']codebread["']""", text, re.M):
24
+ m = re.search(r"""^version\s*=\s*["']([^"']+)["']""", text, re.M)
25
+ if m:
26
+ return m.group(1)
27
+ except OSError:
28
+ pass
29
+ try:
30
+ from importlib.metadata import PackageNotFoundError, version
31
+ try:
32
+ return version("codebread")
33
+ except PackageNotFoundError:
34
+ pass
35
+ except ImportError:
36
+ pass
37
+ return "0.0.0+unknown"
38
+
39
+
40
+ __version__ = _read_version()
@@ -37,6 +37,11 @@ def main(argv=None) -> int:
37
37
  help="also export the full graph as JSON")
38
38
  parser.add_argument("--html", metavar="OUT.html",
39
39
  help="also export a self-contained static HTML file")
40
+ parser.add_argument("--md", nargs="?", const="", metavar="OUT.md",
41
+ help="also write an AI context brief (Markdown) - a "
42
+ "compact map of the project an assistant can read "
43
+ "instead of every file. Default: CODEBREAD.md in "
44
+ "the scanned folder")
40
45
  parser.add_argument("--no-open", action="store_true",
41
46
  help="don't auto-open the browser")
42
47
  parser.add_argument("--no-serve", action="store_true",
@@ -89,6 +94,14 @@ def main(argv=None) -> int:
89
94
  print(f"[codebread] {graph['stats']['warnings']} warning(s) - "
90
95
  f"they are shown as badges in the UI, nothing was hidden.")
91
96
 
97
+ from .context import export_markdown, to_markdown
98
+ graph["contextMd"] = to_markdown(graph) # powers the report's "Copy for AI" / download
99
+ if args.md is not None:
100
+ default_dir = graph.get("meta", {}).get("root") or os.getcwd()
101
+ if not os.path.isdir(default_dir): # --load of a graph scanned elsewhere
102
+ default_dir = os.getcwd()
103
+ p = export_markdown(graph, args.md or os.path.join(default_dir, "CODEBREAD.md"))
104
+ print(f"[codebread] AI context brief written to {p}")
92
105
  if args.json:
93
106
  p = export_json(graph, args.json)
94
107
  print(f"[codebread] Graph JSON written to {p}")