Submitted for the **Side Quest · The Write-Up* — judged on insight, not audience size. This post covers, in order: what we reimplemented, what the standard library made genuinely painful, the package our own code made look unnecessary, and the specific edge case that cost us real debugging time.*
CodeIntel Doctor Zero — a single-file, offline codebase doctor that scores your repo's health, catches leaked secrets, finds duplicate code, and tells you exactly what to fix first. Built for Zero Dependency Hack 2026, Track A — Developer Tools & CLI, with zero third-party runtime dependencies, 87 passing tests, and a bit-for-bit reproducible build.
The local browser UI, rendered from the project's real ui.html against the repo's own published fixture data — no mockup tool, this is the actual product.
The one-line pitch
Point it at any repository. In under a second, it hands you a 0–100 health score you can actually audit line by line, a prioritized "fix this first" list, an offline secret scanner, a real duplicate-code detector, local search, and a self-contained HTML report — all from one Python file, running on nothing but the standard library.
git clone https://github.com/rajpriyanid-creator/codeintel-doctor
cd codeintel-doctor-zero
python3 build.py # verifies runtime, runs 87 tests, builds a deterministic artifact
python3 codeintel.py analyze .
No pip install. No Docker. No API key. No internet connection — ever.
The constraint that started it
Every dev-tool hackathon has the same shortcut available:
pip install click rich pygments radon chardet jinja2 pytest ...
Seven or eight battle-tested libraries, and you're 80% of the way to a polished CLI before lunch.
Zero Dependency Hack 2026 removed that shortcut on purpose. Track A's brief was blunt: build a real developer tool with zero third-party runtime dependencies.
That reframes the actual question. It's no longer:
Can Python scan a repository?
Obviously — yes. The real question is:
How much genuine repository intelligence can you build when the entire package ecosystem is off the table — and can you prove it, not just claim it?
That second half — prove it — is what separates a gimmick from an engineering submission. So the project treats "zero dependencies" as a claim with receipts, not a badge in a README. Running verify_zero_deps.py parses codeintel.py's actual import statements with Python's own ast module, checks every one against sys.stdlib_module_names, scans for subprocess calls, scans for network-capable imports, and scans for vendored packages. The real, generated output — captured in deps-proof.txt — ends with:
ZERO-DEPENDENCY CHECK: PASS
THIRD-PARTY RUNTIME DEPS: 0
Anyone can clone the repo and run that check themselves. That's the whole point.
What we would normally have installed
We didn't try to rebuild entire ecosystems — only the exact slice each capability needed.
| Capability | Typical dependency | Stdlib foundation | What we actually built |
|---|---|---|---|
| CLI parsing |
click / typer
|
argparse |
commands, flags, validation, CI-ready exit codes |
| Terminal styling |
rich / colorama
|
sys, os, raw ANSI SGR |
TTY-aware severity coloring + NO_COLOR fallback |
| Tables | tabulate |
strings + terminal I/O | deterministic table renderer |
| Repo traversal |
pathspec / glob
|
os.walk, fnmatch, pathlib
|
ignore rules, symlink-loop safety, depth limits |
| Encoding detection | chardet |
UTF-8 probing + fallback | text/binary classification |
| Language ID | pygments |
extensions + shebangs | heuristic language detection |
| Complexity |
radon / lizard
|
re |
estimated control-flow complexity |
| Duplicate detection | MinHash-style libs | hashlib |
sliding-window fingerprint + verify |
| Secret scanning | dedicated scanners | re |
pattern rules, confidence, masking, baselines |
| HTML reports | Jinja2 |
str.format |
self-contained, zero-asset HTML report |
| Test runner | pytest |
unittest |
87-test regression suite |
STDLIB.md documents 17 real substitutions, each with an honest note on where the hand-rolled version is not a drop-in replacement. Our terminal renderer, for instance, never tries to become rich — it only does severity colors, bold headers, TTY detection, and a plain fallback. That's all the product needed, so that's all we built.
What the standard library made genuinely painful
The table above makes it look like every substitution was a clean swap. It wasn't. This is the part most "we went dependency-free!" posts skip, and it's the actual insight:
-
Color support isn't just "print ANSI codes."
colorama/richquietly handle Windows for you. The standard library does not. Legacycmd.exeneedsSetConsoleModecalled on the console handle viactypesbefore ANSI escapes render at all — otherwise a Windows user sees literal\x1b[36mgarbage in their terminal instead of color. That's not in any stdlib color tutorial; you find it the first time someone runs your tool on a non-Windows-Terminal machine. -
fnmatchis not.gitignore.pathspecgives you real gitignore semantics for free: negation patterns (!keep-this.py), directory-only patterns (build/), and**globstars.fnmatchonly does flat shell globs. Reimplementing "ignore like git ignores" correctly — including negation overriding an earlier broad match — took noticeably longer than the actual file-walking logic around it. -
json.dumpsis not deterministic by default. Dict key order, float repr, and separator whitespace can all vary in ways that silently break a byte-for-byte reproducibility test. Getting the determinism suite to pass meant explicitly forcingsort_keys=True, pinning separators, and controlling float formatting everywhere a score or percentage got serialized. -
unittesthas nopytest.mark.parametrize. Every "run this same check against 10 fixture variations" test became a hand-rolled loop withself.subTest(...), which works but is far more ceremony than a decorator. -
There is no safe recursive directory walker built in.
os.walkwill happily follow a symlink into a loop unless you tell it not to — and even then, avoiding directory symlink loops specifically (as opposed to just not following symlinks at all) needs manual(st_dev, st_ino)tracking that a library likepathspecorscandir-based tools give you out of the box.
None of these are hard problems. They're just the fifty small taxes a package normally pays for you, silently, that become your problem the moment you remove it.
The package our own code made look unnecessary
If we had to name one: a dedicated secret-scanning tool — the detect-secrets / trufflehog category of product.
Those are real, well-built tools with entropy analysis, plugin architectures, and CI integrations. Ours is roughly 150 lines of re patterns, a confidence heuristic, and a masking function — and for the specific job of "tell a developer there might be a hardcoded credential before they commit it," it does the same practical job:
severity + confidence + file + line + masked evidence + suggested fix
We're not claiming feature parity — no entropy scoring, no plugin system, no maintained rule database that updates as new credential formats appear. But the honest finding is that for the 80% case a small team actually needs — "did someone just commit a password" — you don't need to install a scanning product. You need about a page and a half of regular expressions and the discipline to always mask what you find. That's a genuinely useful thing to know before your next pip install.
Show, don't tell: the actual output
This isn't a mockup. This is what doctor --explain-score prints on a deliberately messy fixture repo — every point lost, every finding, generated from a real scan:
That's the difference between analysis ("here's some data") and diagnosis ("here's what's wrong, why it matters, and what to do about it"). Every point lost is traceable to named, counted evidence — nothing is a magic number.
Compare that to the plain analyze summary on the same repo:
$ python3 codeintel.py analyze fixtures/messy-repo --plain
CODEINTEL DOCTOR ZERO
Repository: messy-repo
Health: 57/100
Files: 7
Lines: 1,014
Functions: 45
Classes: 0
Tests: 0
Languages
Python 99.5%
Markdown 0.5%
Top Risk Areas
01 src/api/routes.py 68
02 src/auth/login.py 10
03 src/auth/register.py 10
Findings
CRITICAL 0
HIGH 2
MEDIUM 24
LOW 2
And when you want it in a browser: the local UI
The CLI is the primary interface, but python3 codeintel.py ui . spins up the exact same analysis behind a single-page dashboard, served locally on 127.0.0.1 with zero network requests — nothing leaves your machine, and there's nothing to configure.
The sidebar mirrors the CLI one-to-one: Overview, Doctor, Security, Duplicates, Structure, Search, Explain file. Same data everywhere, just a different lens on it.
Overview — the health ring, per-dimension bars, the "needs attention" queue, and language mix, all from one scan:
Doctor — the same prioritized findings as doctor --explain-score, but as a sortable table with severity, location, and the suggested fix right next to it:
Security — masked evidence, confidence-scored signals, nothing phrased as a certainty:
Beyond these three, Duplicates shows the sliding-window fingerprint clusters with exact file:line ranges on both sides of every match, Structure surfaces likely entry points and a scanned-file table, Search does live client-side text/symbol lookup against the current scan, and Explain file drills into a single file's symbols, complexity, and findings.
The important architectural decision here isn't the UI polish — it's that the browser layer does not run a second analysis engine. It renders the exact same AnalysisReport object that the CLI and the JSON/HTML report use. That means:
CLI · JSON · HTML · Browser → one analysis model
instead of four independent implementations that could quietly disagree with each other. One Export JSON button, and the browser view and the CLI's --json output are byte-for-byte the same data.
The hardest problem: what even counts as "duplicate code"?
A naive duplicate detector compares blocks of text directly — slow, and noisy. CodeIntel's pipeline instead does:
source → normalize → tokenize → sliding windows → SHA-256 fingerprints
→ candidate matches → content verification → duplicate clusters
But the more interesting engineering decision isn't the algorithm — it's the honesty about its limits. The detector catches near-verbatim duplicates after normalization. It does not claim to catch semantically identical code with renamed variables, and it says so directly in its own docs. So the finding is phrased as:
"Possible duplicated block"
never:
"These two functions are semantically identical."
That restraint matters more than it sounds like it should. A tool that overclaims what it detects is a tool nobody trusts in CI.
Security scanning, without a security package
The scanner looks for the usual credential-shaped trouble: private keys, API-key-like strings, hardcoded passwords, credential-bearing URLs, JWT-like values, disabled TLS verification, debug configs left on. It's pure re pattern matching — no vulnerability database, no cloud lookup, and it never pretends otherwise. Every finding ships with severity, confidence, file, line, masked evidence, and a suggested fix — and the actual secret value is never written anywhere, in any output mode:
DB_PASSWORD = "hunt********rd2024"
Because it makes zero network calls (mechanically verified, not assumed), your source code never leaves your machine while it's scanned. That's a genuine privacy property — but the docs are careful to separate that from a security guarantee: offline means private, not automatically safe. Teams can accept known findings with --baseline so CI only flags what's actually new.
Reproducibility isn't a claim — it's a receipt
build.py produces a deterministic zipapp: fixed timestamps, fixed permissions, normalized metadata, sorted archive contents, then hashes the result. Here's an actual run, captured twice, from deps-proof.txt:
Build 1 SHA-256: 276c1dc98360db0d61295258a3f6ee4073b7148c36155636c90cea91dc21401
Build 2 SHA-256: 276c1dc98360db0d61295258a3f6ee4073b7148c36155636c90cea91dc21401
MATCH: yes
Same input, same bytes, twice. That's a stronger sentence than "the build is reproducible" — it's a claim you can rerun yourself in thirty seconds.
The determinism guarantee doesn't stop at the build. A dedicated test suite (test_determinism.py) checks byte-identical JSON across repeated runs, stable file ordering, stable finding ordering, deterministic HTML output, and bounded health scores — because a repo scanner that gives you a different answer every time is worse than useless in a CI pipeline.
CI-ready, not just demo-ready
This is the part that turns a hackathon toy into something a real team could adopt tomorrow:
python3 codeintel.py doctor . --fail-on high
python3 codeintel.py security . --baseline security-baseline.json --fail-on medium
| Exit code | Meaning |
|---|---|
0 |
success |
1 |
policy failure — a finding met/exceeded --fail-on
|
2 |
usage / argument error |
3 |
filesystem / path error |
4 |
internal error |
Drop it into a pipeline, gate merges on health regressions, and it never phones home. --json for machines, --plain/--no-color for logs, --baseline so a team only sees genuinely new security findings instead of re-litigating accepted ones every run.
The edge case that ate an afternoon
The test cases that matter aren't clean files — they're the ones that break naive assumptions: Unicode filenames, binary content, NUL bytes, invalid encodings, huge files, deeply nested directories, symlink loops, permission errors, empty repos, malformed baselines.
The one that actually cost real time was a symlink loop:
repo/
src/
link -> .
link points back at the repo root. A naive recursive walker — which is exactly what an early version of the scanner was — turns that into unbounded recursion: repo/link/link/link/link/... until Python hits its recursion limit or the process just hangs, depending on how the traversal was written. The failure mode is ugly precisely because it looks like the tool is doing real work — CPU pinned, no error, no output — right up until it isn't.
The fix wasn't "add a depth limit and call it done," because a depth limit just turns an infinite loop into a very slow, very wrong scan of the same directory a thousand times. The real fix was refusing to follow directory symlinks at all, which — as a side effect — also closes off a class of "read outside the intended tree" attacks for free. That one bug is the reason the traversal layer tracks visited directories instead of trusting the filesystem to behave.
It's now a permanent regression test, and it's the best argument in the whole project for why "the standard library gave us the primitives, not the product": os.walk will follow that symlink into the loop by default. Nothing warns you. You find out the hard way, once.
What we deliberately did not build
Scope discipline is part of the engineering, not a footnote:
- Not a compiler or a full AST analyzer for every language
- Not a CVE database
- Not a code-coverage engine
- Not a semantic vector-search system
- Not a language server or cloud platform
Symbol detection and complexity are regex/heuristic, and the output always says "estimated" or "probable" — never asserts certainty. We'd rather ship:
"A fast, explainable first-pass signal."
than:
"This understands your entire codebase."
That honesty is documented up front in STDLIB.md and the README's own limitations section — not buried, not discovered by a disappointed judge halfway through the demo.
Single file, real structure
The entire runtime lives in one file — codeintel.py, the single-file bonus target — but it's organized into 24 clearly delimited sections (# == SECTION) from constants and data models through the terminal/HTML renderers to main(). One shared AnalysisReport, produced once per scan, feeds every renderer — CLI, JSON, HTML, and the local browser UI shown above.
A single-file constraint changes the packaging model. It does not require abandoning engineering structure.
The scoreboard
Project: CodeIntel Doctor Zero
Track: A — Developer Tools & CLI
Runtime: Python 3.8+ (built/tested on 3.12)
Third-party deps: 0
Network requests: 0
Implementation: single codeintel.py (~2,500 lines, 24 sections)
Automated tests: 87 passing
STDLIB substitutions: 17, documented with honest limitations
Reproducible build: verified — identical SHA-256 across two builds
Commands: analyze · doctor · search · security · tree ·
duplicates · explain · report · ui · demo-color
Bonus targets hit: Package Killer (terminal engine) · STDLIB Log ·
single-file · reproducible build · CI exit codes
What zero dependencies actually taught us
Removing the package registry doesn't prove third-party packages are bad. It just forces you to see the layers sitting underneath them.
A table was a renderer we had to design. A duplicate was a definition we had to draw a line around. A health score was a model we had to make explainable. A security alert was a confidence threshold we had to choose and defend. Once the packages disappeared, every one of those decisions became ours to own — and to prove.
That's the actual submission for Zero Dependency Hack 2026: not "look, no packages," but a working, tested, reproducible developer tool where every design decision that would normally hide inside a pip install is visible, documented, and honest about its own limits.
Repo: https://github.com/rajpriyanid-creator/codeintel-doctor
Demo: https://youtu.be/W4I1-tRH7sE
Built for: Zero Dependency Hack 2026 — Track A, Developer Tools & CLI · Side Quest, The Write-Up
Tagging @HackathonRaptors — thanks for running Side Quest and rewarding the write-up over the vote count.
Tags: hackathonraptors· cli · opensource · showdev · hackathon · zerodependency · python




Top comments (2)
Very Good one
Bestt!!!