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