{
  "markdown": "# prodlint\n\n[![npm version](https://img.shields.io/npm/v/prodlint.svg)](https://www.npmjs.com/package/prodlint)\n[![npm downloads](https://img.shields.io/npm/dm/prodlint.svg)](https://www.npmjs.com/package/prodlint)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nProduction readiness for vibe-coded apps.\n\nStatic analysis for vibe-coded apps. Flags the security, reliability, performance, and AI quality issues that Cursor, v0, Bolt, and Copilot create — hallucinated imports, missing auth, hardcoded secrets, unvalidated server actions, and more. Zero config, no LLM, 52 rules.\n\n```bash\nnpx prodlint\n```\n\n```\n  prodlint v0.10.0\n  Scanned 148 files · 2 critical · 5 warnings · 1 info\n\n  src/app/api/checkout/route.ts\n    12:1  INFO  No rate limiting — anyone could spam this endpoint and run up your API costs  rate-limiting\n    28:5  WARN  Empty catch block silently swallows error  shallow-catch\n\n  src/actions/submit.ts\n    5:3   CRIT  Server action uses formData without validation  next-server-action-validation\n      ↳ Validate with Zod: const data = schema.safeParse(Object.fromEntries(formData))\n\n  src/lib/db.ts\n    1:1   CRIT  Package \"drizzle-orm\" is imported but not in package.json  hallucinated-imports\n\n  Scores\n  security        72 ████████████████░░░░  (8 issues)\n  reliability     85 █████████████████░░░  (4 issues)\n  performance     95 ███████████████████░  (1 issue)\n  ai-quality      90 ██████████████████░░  (3 issues)\n\n  Overall: 82/100 (weighted)\n\n  2 critical · 5 warnings · 4 info\n```\n\n## Why?\n\nVibe coding is the fastest way to build. Shipping fast means knowing your code is production-ready — not just that it compiles. Hardcoded secrets, hallucinated packages, missing auth, and XSS vectors pass type-checks and look correct — but they aren't ready for production.\n\nprodlint checks what TypeScript and ESLint don't: **whether your vibe-coded app is ready for production**.\n\n## Install\n\n```bash\nnpx prodlint                              # Run directly (no install)\nnpx prodlint ./my-app                     # Scan specific path\nnpx prodlint --json                       # JSON output for CI\nnpx prodlint --sarif                      # SARIF 2.1.0 for GitHub Code Scanning\nnpx prodlint --summary                    # Quick pass/fail + top 3 blockers\nnpx prodlint --profile startup            # Only critical findings\nnpx prodlint --profile strict             # All findings including info\nnpx prodlint --baseline .prodlint-baseline.json   # Only new findings\nnpx prodlint --ignore \"*.test.ts\"         # Ignore patterns\nnpx prodlint --min-severity warning       # Only warnings and criticals\nnpx prodlint --quiet                      # Suppress badge output\n```\n\nOr install it:\n\n```bash\nnpm i -D prodlint     # Project dependency\nnpm i -g prodlint     # Global install\n```\n\n## 52 Rules across 4 Categories\n\n### Security (27 rules)\n\n| Rule | What it checks |\n|------|----------------|\n| `secrets` | API keys, tokens, passwords hardcoded in source |\n| `auth-checks` | API routes with no authentication |\n| `env-exposure` | `NEXT_PUBLIC_` on server-only secrets |\n| `input-validation` | Request body used without validation |\n| `cors-config` | `Access-Control-Allow-Origin: *`, wildcard + credentials escalated to critical |\n| `unsafe-html` | `dangerouslySetInnerHTML` with user data |\n| `sql-injection` | String-interpolated SQL queries (ORM-aware) |\n| `open-redirect` | User input passed to `redirect()` |\n| `rate-limiting` | API routes with no rate limiter |\n| `phantom-dependency` | Packages in node_modules but missing from package.json |\n| `insecure-cookie` | Session cookies missing httpOnly/secure/sameSite |\n| `leaked-env-in-logs` | `process.env.*` inside console.log calls |\n| `insecure-random` | `Math.random()` used for tokens, secrets, or session IDs |\n| `next-server-action-validation` | Server actions using formData without Zod/schema validation |\n| `env-fallback-secret` | Security-sensitive env vars with hardcoded fallback values |\n| `verbose-error-response` | Error stack traces or messages leaked in API responses |\n| `missing-webhook-verification` | Webhook routes without signature verification |\n| `server-action-auth` | Server actions with mutations but no auth check |\n| `eval-injection` | `eval()`, `new Function()`, dynamic code execution |\n| `next-public-sensitive` | `NEXT_PUBLIC_` prefix on secret env vars |\n| `ssrf-risk` | User-controlled URLs passed to fetch in server code |\n| `path-traversal` | File system operations with unsanitized user input |\n| `unsafe-file-upload` | File upload handlers without type or size validation |\n| `supabase-missing-rls` | `CREATE TABLE` in migrations without enabling RLS |\n| `deprecated-oauth-flow` | OAuth Implicit Grant (response_type=token) |\n| `jwt-no-expiry` | JWT tokens signed without an expiration |\n| `client-side-auth-only` | Password comparisons or auth logic in client components |\n\n### Reliability (11 rules)\n\n| Rule | What it checks |\n|------|----------------|\n| `hallucinated-imports` | Imports of packages not in package.json |\n| `error-handling` | Async operations without try/catch |\n| `unhandled-promise` | Floating promises with no await or .catch |\n| `shallow-catch` | Empty catch blocks that swallow errors |\n| `missing-loading-state` | Client components that fetch without a loading state |\n| `missing-error-boundary` | Route layouts without a matching error.tsx |\n| `missing-transaction` | Multiple Prisma writes without `$transaction` |\n| `redirect-in-try-catch` | `redirect()` inside try/catch — Next.js redirect throws, catch swallows it |\n| `missing-revalidation` | Server actions with DB mutations but no `revalidatePath` |\n| `missing-useeffect-cleanup` | useEffect with subscriptions/timers but no cleanup return |\n| `hydration-mismatch` | `window`/`Date.now()`/`Math.random()` in server component render path |\n\n### Performance (6 rules)\n\n| Rule | What it checks |\n|------|----------------|\n| `no-sync-fs` | `readFileSync` in API routes |\n| `no-n-plus-one` | Database calls inside loops |\n| `no-unbounded-query` | `.findMany()` / `.select('*')` with no limit |\n| `no-dynamic-import-loop` | `import()` inside loops |\n| `server-component-fetch-self` | Server components fetching their own API routes |\n| `missing-abort-controller` | Fetch/axios calls without timeout or AbortController |\n\n### AI Quality (8 rules)\n\n| Rule | What it checks |\n|------|----------------|\n| `ai-smells` | `any` types, `console.log`, TODO comments piling up |\n| `placeholder-content` | Lorem ipsum, example emails, \"your-api-key-here\" left in production code |\n| `hallucinated-api` | `.flatten()`, `.contains()`, `.substr()` — methods AI invents |\n| `stale-fallback` | `localhost:3000` hardcoded in production code |\n| `comprehension-debt` | Functions over 80 lines, deep nesting, too many parameters |\n| `codebase-consistency` | Mixed naming conventions across the project |\n| `dead-exports` | Exported functions that nothing imports |\n| `use-client-overuse` | `\"use client\"` on files that don't use any client-side APIs |\n\n## Smart Detection\n\nprodlint avoids common false positives:\n\n- **AST parsing** — Babel-based analysis for 12 rules (imports, catch blocks, redirects, SSRF, path traversal, JWT, HTML injection, hydration, transactions, env leaks, loops, SQL) with regex fallback\n- **Monorepo support** — npm/yarn/pnpm workspace dependencies resolved automatically\n- **Framework awareness** — Prisma, Drizzle, Supabase, Knex, and Sequelize whitelists prevent false SQL injection flags\n- **Middleware detection** — Clerk, NextAuth, Supabase middleware detected — auth findings downgraded\n- **Block comment awareness** — patterns inside `/* */` are ignored\n- **Path alias support** — `@/`, `~/`, and tsconfig paths aren't flagged as hallucinated imports\n- **Route exemptions** — auth, webhook, health, and cron routes are exempt from auth/rate-limit checks\n- **Test/script file awareness** — lower severity for non-production files\n- **Fix suggestions** — findings include actionable `fix` hints with remediation code\n\n## Scoring\n\nEach category starts at 100. Deductions per finding:\n\n| Severity | Deduction | Per-rule cap |\n|----------|-----------|--------------|\n| critical | -8 | max 1 |\n| warning | -2 | max 2 |\n| info | -0.5 | max 3 |\n\n**Diminishing returns**: after 30 points deducted in a category, further deductions are halved; after 50, quartered.\n\n**Weighted overall**: security 40%, reliability 30%, performance 15%, ai-quality 15%. Floor at 0. Exit code `1` if any critical findings exist.\n\n## GitHub Action\n\nAdd to `.github/workflows/prodlint.yml`:\n\n```yaml\nname: Prodlint\non: [pull_request]\n\njobs:\n  scan:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: prodlint/prodlint@v1\n        with:\n          threshold: 50\n```\n\nPosts a score breakdown as a PR comment and fails the build if below threshold.\n\n| Input | Default | Description |\n|-------|---------|-------------|\n| `path` | `.` | Path to scan |\n| `threshold` | `0` | Minimum score to pass (0-100) |\n| `ignore` | | Comma-separated glob patterns to ignore |\n| `comment` | `true` | Post PR comment with results |\n\n| Output | Description |\n|--------|-------------|\n| `score` | Overall score (0-100) |\n| `critical` | Number of critical findings |\n\n### SARIF + GitHub Code Scanning\n\nUpload prodlint results to GitHub's Security tab:\n\n```yaml\n- name: Run prodlint\n  run: npx prodlint --sarif > prodlint.sarif\n\n- name: Upload SARIF\n  uses: github/codeql-action/upload-sarif@v4\n  with:\n    sarif_file: prodlint.sarif\n    category: prodlint\n```\n\n### Baseline for Existing Projects\n\nAdopt prodlint gradually without drowning in pre-existing findings:\n\n```bash\n# Save current state as baseline\nnpx prodlint --baseline-save .prodlint-baseline.json\n\n# CI only fails on NEW findings\nnpx prodlint --baseline .prodlint-baseline.json\n```\n\n## MCP Server\n\nUse prodlint inside Cursor, Claude Code, or any MCP-compatible editor:\n\n**Claude Code:**\n```bash\nclaude mcp add prodlint -- npx -y -p prodlint prodlint-mcp\n```\n\n**Cursor / Windsurf:**\n```json\n{\n  \"mcpServers\": {\n    \"prodlint\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"-p\", \"prodlint\", \"prodlint-mcp\"]\n    }\n  }\n}\n```\n\n`-p prodlint` runs the MCP server straight from the `prodlint` package, so you always get\nthe current scanner.\n\nAsk your AI: *\"Run prodlint on this project\"* and it calls the `scan` tool directly.\n\n## Site Score\n\nCheck any deployed website for AI agent-readiness — 14 checks covering emerging standards like llms.txt, TDMRep, AgentCard, AI-Disclosure, HTTP Signatures (RFC 9421), and more.\n\n```bash\nnpx prodlint --web example.com\nnpx prodlint --web example.com --json     # JSON output\n```\n\n```\n  prodlint site score\n  example.com · 14 checks\n\n  Score: 42 C  ████████░░░░░░░░░░░░\n\n  ✗ AI-Disclosure Header          0/10  No AI-Disclosure header found.\n  ✗ Content-Usage Directives      0/10  No Content-Usage directives found.\n  ✗ TDMRep                        0/10  No TDMRep found.\n  ✗ A2A AgentCard                  0/5  No agent-card.json found.\n  ✗ ai.txt                         0/5  No ai.txt found at site root.\n  ! llms.txt                       2/5  llms.txt found but missing key sections.\n  ✓ robots.txt                   10/10  robots.txt found with 15 rules.\n  ✓ Sitemap                      10/10  Valid sitemap with 42 URLs.\n  ✓ Structured Data              10/10  Found JSON-LD structured data.\n  ✓ OpenGraph                    10/10  Complete OpenGraph tags found.\n  ✓ Page Speed                    5/5   Loaded in 0.8s.\n  ✓ AI Bot Directives             5/5   AI-specific bot rules found.\n  ✓ WebMCP Tools                   0/5  No WebMCP tools detected.\n\n  7 passed · 5 failed · 1 warnings\n\n  Full results: https://prodlint.com/score?url=example.com\n```\n\nOr check your score interactively at [prodlint.com/score](https://prodlint.com/score).\n\n## For AI Tools\n\n- **LLM-friendly docs**: [prodlint.com/llms.txt](https://prodlint.com/llms.txt) — concise project summary for LLMs\n- **Full reference**: [prodlint.com/llms-full.txt](https://prodlint.com/llms-full.txt) — all 52 rules with details\n- **MCP setup guide**: [prodlint.com/mcp](https://prodlint.com/mcp) — detailed editor setup for Claude Code, Cursor, Windsurf\n\nprodlint is designed specifically for AI-generated code patterns. Every rule checks for production issues that AI coding tools consistently create — not style nits.\n\n## Suppression\n\nSuppress a single line:\n```ts\n// prodlint-disable-next-line secrets\nconst key = \"sk_test_example_for_docs\"\n```\n\nSuppress an entire file (place at top):\n```ts\n// prodlint-disable secrets\n```\n\n## Programmatic API\n\n```ts\nimport { scan } from 'prodlint'\n\nconst result = await scan({ path: './my-project' })\nconsole.log(result.overallScore) // 0-100\nconsole.log(result.findings)     // Finding[]\n```\n\n## Badge\n\n```md\n[![prodlint](https://img.shields.io/badge/prodlint-85%2F100-brightgreen)](https://prodlint.com)\n```\n\n## License\n\nMIT\n",
  "bytes": 12983,
  "sha": "8e0d6474d52dc98068f3425cd3079fbc5f6d996a9ac6cb848ad903421f84d441",
  "repo_slug": "prodlint/prodlint",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_prodlint_prodlint_2c258b9b/readme"
}