← Projects

Slim

Slim is a TypeScript CLI that deletes your npm dependencies. You point it at a repo, it works out how you actually use a package, writes a dependency-free replacement, fuzzes the replacement against the original, and opens a PR with all the evidence attached. It has zero runtime dependencies of its own.

Role
Solo, start to finish
Timeline
August — September 2026
Stack
TypeScript, Node 22, the TypeScript compiler API, node:test, Vitest, GitHub Actions
Status
Open source, MIT · github.com/GSXRcoder159/slim

The problem

It's Friday afternoon and a CVE lands on a library you use for exactly two functions. Tree-shaking doesn't help you here; stock lodash uses Function(String) and gets rejected outright on Cloudflare and Vercel Edge. Rewriting it by hand is tedious, and then nobody trusts the rewrite.

I also think of it as the smallest possible version of the Transmute idea. The repo already contains the evidence of exactly what it needs from the package. Generating the code is cheap; the evidence is the actual product.

What I built

Slim reads every call site and input shape a package is used with, generates a replacement that covers exactly that envelope, and proves the two are equivalent by differential fuzzing before it proposes anything. The PR comes with an evidence file (what was used, byte delta, fuzz counts, residual risk, and it's never empty) and frozen-I/O tests that keep passing once the dependency is gone.

There's a verified catalog for lodash, moment, uuid, ms, nanoid and clsx. There's also an optional LLM generator, but it only ever sees the public .d.ts and README, and it has to pass the same AST, export-contract, fuzz and evidence gates as the catalog. The trace hooks for node:test and Vitest fail closed, so if the fuzzer can't reach a branch, the PR doesn't claim it. It also ships GitHub Actions for dependency checks, bloat and osv.dev advisory monitoring, with CI on Ubuntu, macOS and Windows.

docs/evidence.lodash.sample.md · checked-in receipt
$ cat docs/evidence.lodash.sample.md
package:       lodash@4.17.21
symbols:       get, debounce
call sites:    6 | unknowns: 0
catalog:       lodash.get, lodash.debounce
size:          71,000 B estimated min → 7,328 B measured replacement
fuzz:          30,023 cases / 30,043 comparisons
traces:        12 replayed | disagreements: 0
status:        EVIDENCE, NOT PROOF
holes:         debounce maxWait/leading/cancel unobserved
docs/evidence.lodash.sample.md · checked-in receipt

Results

The repository's 2026-08-30 lodash receipt covers 6 call sites with 0 unknowns. It records 30,023 fuzz cases, 30,043 comparisons, 12 replayed traces and 0 disagreements; the generated slice is 7,328 measured bytes versus a 71,000-byte estimated original minimum. The byte baseline is explicitly an estimate, and the fuzz result is evidence, not proof. The repo's own claims check now rejects this receipt because it is older than its seven-day freshness window, so these are historical measurements rather than a current release qualification.

Differential fuzzing is evidence, not proof, and that sentence is right there in the README. Honest refusals are part of the design too: react, prisma, native addons and anything that needs Function get refused with the same what / why / evidence / what-to-do explanation, rather than a half-working slice.

What I'd do differently

Fail-closed gating turned out to be worth more than any amount of prompt work. Next time I'd ship the GitHub Action first. The CLI was the fun part to build, but the Action is what people actually adopt.