|
| 1 | +<p align="center"> |
| 2 | + <img src="assets/logo-wordmark.png" alt="CodeBread" width="360"> |
| 3 | +</p> |
| 4 | + |
| 5 | +<p align="center"> |
| 6 | + <b>Slice open any codebase and see how it's actually wired together.</b><br> |
| 7 | + An interactive, zero-dependency map of files → functions → API routes → database tables. |
| 8 | +</p> |
| 9 | + |
| 10 | +<p align="center"> |
| 11 | + <img alt="version" src="https://img.shields.io/badge/version-1.0.0-2dd4bf"> |
| 12 | + <img alt="python" src="https://img.shields.io/badge/python-3.9%2B-0284c7"> |
| 13 | + <img alt="deps" src="https://img.shields.io/badge/required%20dependencies-none-2dd4bf"> |
| 14 | + <img alt="license" src="https://img.shields.io/badge/license-MIT-8b5cf6"> |
| 15 | +</p> |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +## What is this |
| 20 | + |
| 21 | +CodeBread scans a project, extracts every function and class, maps how |
| 22 | +everything connects — **frontend → API → backend → database** — and renders |
| 23 | +it as an interactive node-graph in your browser. Click a file to slice it |
| 24 | +open into its functions; click a function to see everything it calls and |
| 25 | +everything that calls it, with the full chain lit up end to end. |
| 26 | + |
| 27 | +**The problem it solves:** dropping into a codebase you didn't write — or one |
| 28 | +an AI generated for you — and not knowing where anything is. Reading files |
| 29 | +one at a time doesn't build a mental model fast. CodeBread builds the model |
| 30 | +for you: it finds the routes, follows the `fetch()` calls to the handlers |
| 31 | +that answer them, follows the handlers to the tables they touch, and draws |
| 32 | +the whole path. |
| 33 | + |
| 34 | +## Why I built this |
| 35 | + |
| 36 | +This started as a personal tool. I kept generating projects with AI and then |
| 37 | +staring at the result with no idea how the pieces fit together — which file |
| 38 | +called which, where the API boundary actually was, what touched the |
| 39 | +database. I wanted something that would just *show* me, instead of me |
| 40 | +grepping through the tree file by file. CodeBread is that tool. |
| 41 | + |
| 42 | +It's a v1.0 — actively used by me on my own projects, and I'll keep adding |
| 43 | +to it. If it's useful to you too, that's a bonus. Issues and PRs are welcome. |
| 44 | + |
| 45 | +## What it's built with |
| 46 | + |
| 47 | +- **Backend/analysis engine:** pure Python **standard library** — no |
| 48 | + required third-party packages, nothing to `pip install` beyond Python |
| 49 | + itself. Parsing is stdlib `ast` for Python and structural regex for |
| 50 | + everything else (see language table below). |
| 51 | +- **Frontend:** vanilla **JavaScript + SVG**, no framework, no build step, |
| 52 | + no `npm install`. The entire UI is three files (`app.js`, `index.html`, |
| 53 | + `style.css`). |
| 54 | +- **Serving:** a tiny local server built on `http.server` from the stdlib. |
| 55 | + |
| 56 | +That's it. Clone it, run it, nothing to compile. |
| 57 | + |
| 58 | +--- |
| 59 | + |
| 60 | +## Install |
| 61 | + |
| 62 | +```bash |
| 63 | +# option A: install the CLI |
| 64 | +pip install . |
| 65 | + |
| 66 | +# option B: don't install anything, just run it |
| 67 | +python codebread.py --path /path/to/project |
| 68 | +``` |
| 69 | + |
| 70 | +Optional extra (better `.gitignore` matching while scanning): |
| 71 | + |
| 72 | +```bash |
| 73 | +pip install .[full] # adds pathspec |
| 74 | +``` |
| 75 | + |
| 76 | +Requires **Python 3.9+**. Nothing else. |
| 77 | + |
| 78 | +## Use |
| 79 | + |
| 80 | +```bash |
| 81 | +codebread --path /path/to/project # scan + open the UI in your browser |
| 82 | +codebread # prompts for the path |
| 83 | +python codebread.py --path . # uninstalled, same thing |
| 84 | +``` |
| 85 | + |
| 86 | +That's the whole quick start: point it at a folder, a browser tab opens with |
| 87 | +the map already scanned. |
| 88 | + |
| 89 | +### CLI reference |
| 90 | + |
| 91 | +| Flag | What it does | |
| 92 | +|---|---| |
| 93 | +| `--path, -p PATH` | root folder to scan (prompted if omitted) | |
| 94 | +| `--port 8137` | local server port (auto-picks a free one nearby if taken) | |
| 95 | +| `--json out.json` | export the full graph as JSON | |
| 96 | +| `--load out.json` | re-open a saved scan without re-scanning | |
| 97 | +| `--html out.html` | export a **self-contained static HTML** file you can share | |
| 98 | +| `--diff old.json new.json` | compare two saved scans and print what changed (files/functions/tables added, removed, changed) | |
| 99 | +| `--no-open` | don't auto-open the browser | |
| 100 | +| `--no-serve` | scan + export only, don't start the server | |
| 101 | +| `--version` | print the installed version | |
| 102 | + |
| 103 | +--- |
| 104 | + |
| 105 | +## What you get |
| 106 | + |
| 107 | +- **Explorer sidebar** — the full folder tree, expandable like a file |
| 108 | + explorer; every file tagged with its layer color. |
| 109 | +- **Orbit layout (default)** — files float freely in space, spread apart so |
| 110 | + connections stay untangled. Expand a file and its functions arrange in a |
| 111 | + clean ring around it, spoked by straight lines back to the center. A |
| 112 | + **Free** force-directed layout is also available (toggle bottom-right). |
| 113 | +- **Focus mode** — clears the canvas so you inspect one file at a time: |
| 114 | + pick a file in the Explorer and only it, its functions, and its direct |
| 115 | + connections show up. Toggle it off to go back to the full overview. |
| 116 | +- **Progressive reveal (OSINT-style)** — click a file to slice it open into |
| 117 | + its numbered functions; click a function to draw in what it calls and |
| 118 | + what calls it. Dense codebases stay readable. |
| 119 | +- **Full-chain highlight** — select any node and its complete end-to-end |
| 120 | + chain lights up (frontend `fetch()` → `GET /api/users` route → handler → |
| 121 | + `users` table), everything unrelated dims. |
| 122 | +- **Right-click for actions** — a context menu on every node, edge, and |
| 123 | + the empty canvas: reveal connections, focus a file, open it in the IDE |
| 124 | + view, jump to a route's source/target, copy a name or path, and more. |
| 125 | +- **Insights panel** — flags orphaned functions (no detected callers) and |
| 126 | + circular call chains, both clickable to jump straight to them. |
| 127 | +- **Diff mode** — compare two saved scans (`--diff old.json new.json`) to |
| 128 | + see exactly what changed between them. |
| 129 | +- **Minimap + breadcrumb** — a live minimap of the whole graph with a |
| 130 | + draggable viewport, and a breadcrumb showing the real folder path of |
| 131 | + whatever's currently selected. |
| 132 | +- **Keyboard navigation** — `←`/`→` step through a selected node's |
| 133 | + neighbors, `↑`/`↓` walk back/forward through your selection history, |
| 134 | + `/` to search. |
| 135 | +- **Detail panel** — params, return type, auto-generated description |
| 136 | + ("Function 3 · handles GET /api/users · queries users"), every caller and |
| 137 | + callee, clickable. |
| 138 | +- **View the actual code** — every function has an expandable |
| 139 | + **▸ View code** section: syntax-highlighted source with real line |
| 140 | + numbers. A full **IDE view** (⌗) opens any file whole, with an outline |
| 141 | + sidebar. |
| 142 | +- **Search** (`/`) and **layer filter** (Frontend / Backend / Database / |
| 143 | + Config) in the header. |
| 144 | +- **Warnings, never silence** — unreadable files, unsupported languages and |
| 145 | + permission problems show up as ⚠ badges and in the warnings list, never |
| 146 | + hidden. Secrets found in config files are always masked. |
| 147 | + |
| 148 | +## Language support |
| 149 | + |
| 150 | +| Language | Parser | Extracted | |
| 151 | +|---|---|---| |
| 152 | +| Python | stdlib `ast` (precise) | functions, classes, params/annotations, docstrings, Flask/FastAPI/Django routes, SQLAlchemy/Django models, raw SQL, `requests`/`httpx` calls | |
| 153 | +| JavaScript / TypeScript / JSX / TSX / Vue / Svelte | structural regex + brace matching | functions, arrow fns, classes, Express/Nest/Fastify routes, `fetch`/`axios` calls, Mongoose/Prisma/Sequelize/Knex/TypeORM, raw SQL | |
| 154 | +| Java, C#, Go, PHP, Ruby | structural regex | functions/methods, classes, Spring/ASP.NET/Laravel/Rails/Gin routes, raw SQL | |
| 155 | +| SQL | regex | `CREATE TABLE` schemas with columns | |
| 156 | +| Config (`.env`, json/yaml/toml/ini, settings.py…) | key scan | DB connection settings — **credentials always masked** | |
| 157 | +| Anything else (Rust, Kotlin, Swift, C/C++…) | — | shown in the UI as "⚠ Unsupported — parsing skipped", never silently dropped | |
| 158 | + |
| 159 | +## How it classifies layers |
| 160 | + |
| 161 | +Score-based heuristics combining framework import signatures |
| 162 | +(React/Vue → frontend, Flask/Express → backend, SQLAlchemy/Prisma → |
| 163 | +database), folder conventions (`/client`, `/server`, `/models`…), file |
| 164 | +extensions, and extracted facts (defines routes → backend, defines models → |
| 165 | +database). Ambiguous files are marked **Unclassified** instead of guessed. |
| 166 | + |
| 167 | +## How orphan + cycle detection works |
| 168 | + |
| 169 | +- **Orphaned functions**: any function/method with zero detected incoming |
| 170 | + calls, that isn't a route handler and isn't a common framework entry |
| 171 | + point (`__init__`, `main`, `setUp`, test functions, …). Flagged with a |
| 172 | + badge on the node and listed in the Insights panel — a good starting |
| 173 | + point for finding dead code (heuristic, not exhaustive: it can miss calls |
| 174 | + the static parser doesn't recognize). |
| 175 | +- **Circular call chains**: an iterative cycle-detection pass over the |
| 176 | + call graph (no recursion, so it's safe on large codebases) flags |
| 177 | + functions that call each other in a loop, both on the node (↻ badge) and |
| 178 | + as a listed chain in the Insights panel. |
| 179 | + |
| 180 | +## Project layout |
| 181 | + |
| 182 | +``` |
| 183 | +codebread.py ← runnable entry point (no install needed) |
| 184 | +codebread/ |
| 185 | + cli.py ← argparse CLI |
| 186 | + scanner.py ← .gitignore-aware recursive walker |
| 187 | + languages.py ← language detection / binary sniffing |
| 188 | + parsers/ |
| 189 | + python_parser.py ← ast-based Python extractor |
| 190 | + javascript_parser.py ← JS/TS/Vue/Svelte extractor |
| 191 | + generic_parser.py ← Java/C#/Go/PHP/Ruby + SQL + config |
| 192 | + classifier.py ← frontend/backend/database/config scoring |
| 193 | + connections.py ← call graph + API↔route + fn↔table matching + |
| 194 | + orphan/cycle detection |
| 195 | + analyzer.py ← pipeline orchestration |
| 196 | + diff.py ← compares two saved scans |
| 197 | + server.py ← stdlib local web server |
| 198 | + export.py ← JSON + single-file HTML export |
| 199 | + web/ ← the UI (vanilla JS + SVG, zero dependencies) |
| 200 | +assets/ ← logo (.svg source + .png for the README — |
| 201 | + GitHub blocks same-repo SVG <img> embeds) |
| 202 | +``` |
| 203 | + |
| 204 | +--- |
| 205 | + |
| 206 | +## Roadmap |
| 207 | + |
| 208 | +Already done as of v1.0: |
| 209 | + |
| 210 | +- [x] Orphaned-function and circular-dependency detection |
| 211 | +- [x] Diff mode between two scans |
| 212 | +- [x] Focus mode, orbit layout, right-click actions, minimap, breadcrumb |
| 213 | + |
| 214 | +Not yet, but planned: |
| 215 | + |
| 216 | +- [ ] "Explain this function" — a plain-language AI summary button |
| 217 | +- [ ] More precise multi-language parsing (currently structural regex for |
| 218 | + everything but Python) |
| 219 | +- [ ] An automated test suite |
| 220 | + |
| 221 | +Have an idea? Open an issue. |
| 222 | + |
| 223 | +## Contributing |
| 224 | + |
| 225 | +This is a young, actively-changing personal project, so keep that in mind — |
| 226 | +but contributions are genuinely welcome: |
| 227 | + |
| 228 | +- **Bugs / ideas** → open an issue with a repro or a description. |
| 229 | +- **Pull requests** → welcome, especially for language parser improvements |
| 230 | + or UI polish. Keep the zero-dependency philosophy: the core tool should |
| 231 | + keep running on nothing but the Python standard library, and the UI |
| 232 | + should keep running on vanilla JS with no build step. |
| 233 | +- No formal test suite yet, so please describe how you manually verified a |
| 234 | + change in your PR. |
| 235 | + |
| 236 | +## License |
| 237 | + |
| 238 | +[MIT](LICENSE) — use it, modify it, ship it, sell it. No attribution |
| 239 | +required beyond keeping the license file. See [LICENSE](LICENSE) for the |
| 240 | +full text. |
0 commit comments