From cheese-flow
Scan a codebase for custom code that duplicates what open-source libraries already do, then recommend which libraries to adopt. Detects hand-rolled utility functions, custom retry logic, manual validation, DIY date handling, home-grown argument parsers, and other reinvented wheels. Cross-checks against installed dependencies and open specs. Returns scored migration recommendations with effort estimates. Use when the user mentions reinventing the wheel, asks if there is a library for something they built, wants a build-vs-buy audit, asks "should we just use lodash for this", or wants to find dependency opportunities.
npx claudepluginhub paulnsorensen/cheese-flowThis skill is limited to using the following tools:
Find code reinventing the wheel. Recommend libraries. Score with evidence.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Guides code writing, review, and refactoring with Karpathy-inspired rules to avoid overcomplication, ensure simplicity, surgical changes, and verifiable success criteria.
Share bugs, ideas, or general feedback.
Find code reinventing the wheel. Recommend libraries. Score with evidence.
/nih-audit [scope] — scope defaults to repo root.
Find dependency manifests anywhere in scope, excluding node_modules/,
vendor/, .git/, build artefacts:
package.json, Cargo.toml, pyproject.toml, go.mod, Gemfile,
requirements.txt, composer.json, build.gradle, pom.xml, mix.exs.Extract dependency names per ecosystem:
| Manifest | Extract |
|---|---|
package.json | jq -r '(.dependencies + .devDependencies) // {} | keys[]' |
Cargo.toml | parse [dependencies] table |
pyproject.toml | [project.dependencies] or [tool.poetry.dependencies] |
go.mod | require block module paths |
requirements.txt | line-by-line package names |
Build a depManifest:
{
"workspaces": [
{ "root": ".", "ecosystem": "node", "deps": ["express", "zod"] }
],
"primaryLanguages": ["typescript"]
}
If no manifest is found anywhere in scope, abort with a clear message — without an installed-deps list there is nothing to cross-reference.
Spawn the nih-scanner sub-agent:
inputs:
languages = primaryLanguages from Phase 0
scope = $ARGUMENTS or repo root
depManifest = JSON from Phase 0
slug = <derived slug>
The scanner returns a JSON candidate list inline plus a one-paragraph summary. Parse the candidates from the response. If 0 candidates, report clean and stop.
Group candidates by category (RETRY, UUID, VALIDATION, DATE, DEBOUNCE,
CLONE, ARGPARSE, STRING, HTTP, SERIALIZATION, ERROR, CRYPTO, SECURITY,
FORMAT, COMPARE).
For each category, dispatch /research with a focused question shape:
/research "best <category> library for <language>; must be MIT/Apache/BSD;
list weekly downloads or crates.io downloads, GitHub stars, last commit
date, contributor count; flag if functionality is in the standard library"
Cap: max 5 parallel research dispatches. If /research is unavailable,
emit candidates with recommendation: null and a note.
For each library returned, capture:
Drop recommendations whose name is already in depManifest. Stdlib
alternatives (no new dep) are the highest-value class — keep them
prioritized.
See references/categories.md for the canonical category-to-library map.
Find spec directories within scope: **/specs/*.md, .cheese/specs/*.md.
Filter out node_modules/, vendor/, .git/.
For each candidate, look for signals that the NIH choice was deliberate:
intentionally, deliberately,
we chose, NOTE:, DECISION:, instead of, rather than.Apply scoring modifiers:
| Signal | Modifier |
|---|---|
| Spec explicitly chose NIH | -30 |
| Code comment explains NIH choice | -20 |
| Library covers planned spec features | +10 |
For every candidate with a library recommendation, run the 4-step confidence chain:
| Type | Base | Cap |
|---|---|---|
REPLACE_WITH_STDLIB | 55 | 100 |
REPLACE_WITH_MICRO_LIB | 45 | 95 |
REPLACE_WITH_FRAMEWORK | 35 | 85 |
EXTRACT_TO_EXISTING_DEP | 50 | 95 |
| Evidence | Modifier |
|---|---|
| Caller count grounded in cheez-search | +15 |
| Library has >10K weekly downloads + permissive licence | +20 |
| ast-grep pattern + code read confirms NIH | +15 |
| NIH code has recent bug fixes (git log) | +10 |
| NIH code >100 LOC for what library does in 1 call | +10 |
| Generic pattern, code does more than pattern suggests | -15 |
| Library unmaintained (last commit >1 yr) | hard cap at 40 |
Apply Phase 3 modifiers (spec intent, code comments, planned features) plus:
| Signal | Modifier |
|---|---|
| NIH code in git hotspot (many recent changes) | +10 |
| NIH code isolated (1 file, clear boundary) | +5 |
| NIH code deeply coupled (referenced from >10 files) | -5 |
For every candidate, score independently from the first pass:
AMBIGUOUS, still emit.| Criteria | Size |
|---|---|
| 1 file, <50 LOC, ≤3 call sites | S |
| 2-5 files, <200 LOC, ≤10 call sites | M |
| >5 files, >200 LOC, or >10 call sites | L |
Write the full report to .cheese/nih/<slug>.md. Render every candidate
above the threshold; do not silently filter. Each finding follows the
template in references/finding-template.md.
Top of the report:
# NIH Audit — <scope>
## Summary
- Files scanned: N
- Candidates found: N
- Already using best option: N (filtered)
- Ambiguous (passes diverge >20): N
## All findings (sorted by score, descending)
| # | Score | P1 | P2 | Category | NIH Code | Replace With | Effort |
|---|-------|----|----|----------|----------|--------------|--------|
| 1 | 92 | 90 | 94 | UUID | src/utils/uuid.ts:12 | crypto.randomUUID() (stdlib) | S |
After the table, render every ### Finding #N block inline.
Print the report path. Do not auto-invoke any follow-up:
NIH report: .cheese/nih/<slug>.md
Next steps (manual):
• Pick the highest-scored finding and migrate.
• For S-effort stdlib swaps, /cook is usually the right next step.
• For L-effort framework swaps, run /mold first to lock down the
migration interface.
clearTimeout + setTimeout
combo isn't always a debounce. Step 2's "generic pattern, code does
more" modifier (-15) catches false positives.crypto.randomUUID()
replacing a hand-rolled UUID is a no-brainer. Always score these
highest (REPLACE_WITH_STDLIB, base 55, cap 100).deepClone may have done so for bundle
size reasons. The spec/comment check (Phase 3) catches this.packages/api/ may be NIH in
that workspace but the library is installed in packages/web/. Each
workspace's depManifest is independent.