# prodlint > Production readiness for vibe-coded apps. 52 checks to make sure your AI-generated code is ready to ship. prodlint is a zero-config static analysis tool for JavaScript and TypeScript projects. It checks for security, reliability, performance, and AI quality issues commonly found in code from tools like Claude Code, Cursor, v0, Bolt, and Copilot — hardcoded secrets, missing auth, hallucinated imports, unvalidated server actions, and more. ## Quick Start ``` npx prodlint ``` No install, no config, no account. Scans your project and outputs a score from 0–100 across four categories. Other ways to run: ``` npx prodlint ./my-app # Scan specific path npx prodlint --json # JSON output for CI npx prodlint --ignore "*.test.ts" # Ignore patterns npx prodlint --min-severity warning # Only warnings and criticals npx prodlint --quiet # Suppress badge output ``` ## Site Score Free site scoring at prodlint.com/score. Enter any URL and get a prodlint score out of 100 across 14 AI agent standards: 1. robots.txt exists and is accessible 2. AI-specific user-agent directives (GPTBot, ClaudeBot, Google-Extended, PerplexityBot, CCBot, Bytespider, Applebot-Extended, Grok) 3. Content-Usage directives (IETF aipref draft) 4. llms.txt at site root 5. ai.txt at site root (Spawning spec) 6. TDMRep well-known file or headers (W3C) 7. AI-Disclosure HTTP header 8. A2A AgentCard at /.well-known/agent-card.json 9. WebMCP tool registration (Chrome 146+) 10. HTTP Message Signatures (RFC 9421) — agent identity verification via cryptographic signatures 11. Structured data (JSON-LD, Schema.org) 12. OpenGraph and meta description 13. sitemap.xml exists and is valid 14. Page load time Scoring: Normalized to 0-100 scale. Grade A (80+), B (60-79), C (40-59), D (20-39), F (<20). Rate-limited to 5 scans/min. ## Free Generator Tools 7 free tools at prodlint.com/tools. All run client-side with live preview, copy, and download: - robots.txt AI Directives (prodlint.com/tools/robots-txt): Per-bot AI crawler access control for GPTBot, ClaudeBot, Google-Extended, PerplexityBot, CCBot, Bytespider. Preserves existing robots.txt content. - llms.txt Generator (prodlint.com/tools/llms-txt): LLM-optimized site summary with name, URL, description, topics, and key pages. - ai.txt Generator (prodlint.com/tools/ai-txt): AI training permissions per the Spawning spec. Toggles for training, synthesis, summarization, search index, and commercial use. - Content-Usage Directives (prodlint.com/tools/content-usage): IETF aipref per-path AI usage rules. Outputs robots.txt directives and HTTP headers. - TDMRep Generator (prodlint.com/tools/tdmrep): W3C text & data mining reservations. Outputs well-known JSON, HTTP headers, and HTML meta tags. - A2A AgentCard Generator (prodlint.com/tools/agent-card): Agent discovery with identity, skills, auth requirements, and capabilities. - AI-Disclosure Header Generator (prodlint.com/tools/ai-disclosure): AI content transparency headers with 4 modes (none, ai-modified, ai-originated, machine-generated). Outputs ready-to-use middleware for Next.js, Express, and Nginx. ## Key Facts - 52 rules across 4 categories (security, reliability, performance, AI quality) - Zero config — no setup, no plugins, no accounts - Fast — scans 100+ files in under 100ms - MIT licensed, free and open source - AST-powered analysis (Babel) with regex fallback - Framework-aware: Next.js, Prisma, Drizzle, Supabase, Knex, Sequelize - Monorepo support: npm, yarn, pnpm workspaces - TypeScript path alias support (@/, ~/, tsconfig paths) ## All 52 Rules ### Security (27 rules) | Rule ID | Name | Description | Severity | |---------|------|-------------|----------| | secrets | Hardcoded Secrets | Hardcoded API keys (Stripe, AWS, Supabase, OpenAI, GitHub) | critical | | auth-checks | Missing Auth Checks | API routes without authentication (middleware-aware) | critical | | env-exposure | Env Exposure | Server env vars in client components, .env not in .gitignore | critical | | input-validation | Missing Input Validation | Request body used without validation | critical | | cors-config | Permissive CORS | Access-Control-Allow-Origin: *, cors() with no config, wildcard + credentials escalated to critical | warning | | unsafe-html | Unsafe HTML Injection | dangerouslySetInnerHTML, direct innerHTML assignment | critical | | sql-injection | SQL Injection | SQL queries built with template literals or string concat (ORM-aware) | critical | | open-redirect | Open Redirect | User input passed directly to redirect() | warning | | rate-limiting | Missing Rate Limiting | API routes with no rate limiter | warning | | phantom-dependency | Phantom Dependency | Packages in node_modules but missing from package.json | warning | | insecure-cookie | Insecure Cookie | Session cookies missing httpOnly, secure, or sameSite | critical | | leaked-env-in-logs | Leaked Env in Logs | process.env.* leaked inside console.log() calls | warning | | insecure-random | Insecure Random | Math.random() used for tokens, secrets, or session IDs | critical | | next-server-action-validation | Server Action Validation | Server actions using formData without Zod/schema validation | critical | | env-fallback-secret | Env Fallback Secret | Secret env vars with hardcoded fallback values | critical | | verbose-error-response | Verbose Error Response | Error stack traces leaked in API responses | warning | | missing-webhook-verification | Missing Webhook Verification | Webhook routes without signature verification | critical | | server-action-auth | Server Action Auth | Server actions with mutations but no auth check | critical | | eval-injection | Eval Injection | eval(), new Function(), dynamic code execution | critical | | next-public-sensitive | NEXT_PUBLIC_ Sensitive | NEXT_PUBLIC_ prefix on secret env vars | critical | | ssrf-risk | SSRF Risk | User-controlled URLs passed to fetch in server code | critical | | path-traversal | Path Traversal | File system operations with unsanitized user input | critical | | unsafe-file-upload | Unsafe File Upload | File uploads without type or size validation | warning | | supabase-missing-rls | Supabase Missing RLS | CREATE TABLE in migrations without enabling RLS | critical | | deprecated-oauth-flow | Deprecated OAuth Flow | OAuth Implicit Grant (response_type=token) | warning | | jwt-no-expiry | JWT No Expiry | JWT tokens signed without an expiration | warning | | client-side-auth-only | Client-Side Auth Only | Password comparisons or auth logic in client components | critical | ### Reliability (11 rules) | Rule ID | Name | Description | Severity | |---------|------|-------------|----------| | hallucinated-imports | Hallucinated Imports | Imports of packages not in package.json (AI hallucinations) | critical | | error-handling | Missing Error Handling | Async operations without try/catch | warning | | unhandled-promise | Unhandled Promise | Floating promises with no await or .catch | warning | | shallow-catch | Shallow Catch | Empty catch blocks that swallow errors silently | warning | | missing-loading-state | Missing Loading State | Client components that fetch without a loading state | info | | missing-error-boundary | Missing Error Boundary | Route layouts without a matching error.tsx | warning | | missing-transaction | Missing Transaction | Multiple Prisma writes without $transaction | warning | | redirect-in-try-catch | Redirect in Try-Catch | redirect() inside try/catch — Next.js redirect throws, catch swallows it | warning | | missing-revalidation | Missing Revalidation | Server actions with DB mutations but no revalidatePath | info | | missing-useeffect-cleanup | Missing useEffect Cleanup | useEffect with subscriptions/timers but no cleanup return | warning | | hydration-mismatch | Hydration Mismatch | window/Date.now()/Math.random() in server component render path | warning | ### Performance (6 rules) | Rule ID | Name | Description | Severity | |---------|------|-------------|----------| | no-sync-fs | Sync File System | readFileSync in API routes blocks the event loop | warning | | no-n-plus-one | N+1 Query | Database calls inside loops | warning | | no-unbounded-query | Unbounded Query | .findMany() / .select('*') with no limit | warning | | no-dynamic-import-loop | Dynamic Import in Loop | import() inside loops | warning | | server-component-fetch-self | Server Component Fetch Self | Server components fetching their own API routes | info | | missing-abort-controller | Missing Abort Controller | Fetch/axios calls without timeout or AbortController | info | ### AI Quality (8 rules) | Rule ID | Name | Description | Severity | |---------|------|-------------|----------| | ai-smells | AI Code Smells | any types, console.log spam, TODOs, commented-out code piling up | info | | placeholder-content | Placeholder Content | Lorem ipsum, example emails, "your-api-key-here" left in production | warning | | hallucinated-api | Hallucinated API | .flatten(), .contains(), .substr() — methods AI invents | warning | | stale-fallback | Stale Fallback | localhost:3000 hardcoded in production code | warning | | comprehension-debt | Comprehension Debt | Functions over 80 lines, deep nesting, too many parameters | info | | codebase-consistency | Codebase Consistency | Mixed naming conventions across the project | info | | dead-exports | Dead Exports | Exported functions that nothing imports | info | | use-client-overuse | use client Overuse | "use client" on files that don't use any client-side APIs | info | ## Smart Detection prodlint avoids common false positives with context-aware analysis: - **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 for other rules - **Monorepo support** — npm, yarn, and pnpm workspace dependencies resolved automatically - **Framework awareness** — Prisma, Drizzle, Supabase, Knex, and Sequelize whitelists prevent false SQL injection flags - **Middleware detection** — Clerk, NextAuth, Supabase middleware detected — auth findings downgraded - **Block comment awareness** — patterns inside /* */ are ignored - **Path alias support** — @/, ~/, and tsconfig paths aren't flagged as hallucinated imports - **Route exemptions** — auth, webhook, health, and cron routes exempt from auth/rate-limit checks - **Test/script file awareness** — lower severity for non-production files - **Fix suggestions** — every finding includes an actionable fix hint ## Scoring Each category starts at 100. Deductions per finding: | Severity | Deduction | Per-rule cap | |----------|-----------|--------------| | critical | -8 | max 1 | | warning | -2 | max 2 | | info | -0.5 | max 3 | Diminishing returns: after 30 points deducted in a category, further deductions halved; after 50, quartered. Weighted overall score: security 40%, reliability 30%, performance 15%, AI quality 15%. Floor at 0. Exit code 1 if any critical findings exist. ## Integrations ### CLI ``` npx prodlint # Run directly (no install) npx prodlint --web example.com # Get your site's prodlint score npx prodlint --web example.com --json # Site score with JSON output npm i -D prodlint # Or install as dev dependency npm i -g prodlint # Or install globally ``` ### GitHub Action Add to `.github/workflows/prodlint.yml`: ```yaml name: Prodlint on: [pull_request] jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: prodlint/prodlint@v1 with: threshold: 50 ``` Posts a score breakdown as a PR comment and fails the build if below threshold. ### MCP Server Use prodlint inside AI code editors via the Model Context Protocol. **Claude Code:** ``` claude mcp add prodlint npx prodlint-mcp ``` **Cursor:** Add to `.cursor/mcp.json`: ```json { "mcpServers": { "prodlint": { "command": "npx", "args": ["-y", "prodlint-mcp"] } } } ``` **Windsurf:** Add to MCP config: ```json { "mcpServers": { "prodlint": { "command": "npx", "args": ["-y", "prodlint-mcp"] } } } ``` The MCP server exposes a `scan` tool. Ask your AI: "Run prodlint on this project" and it calls the tool directly. - Uses stdio transport — runs locally, no data sent externally - Same analysis engine as the CLI - Results returned as structured data the AI can act on ### Programmatic API ```typescript import { scan } from 'prodlint' const result = await scan({ path: './my-project' }) console.log(result.overallScore) // 0-100 console.log(result.findings) // Finding[] ``` ## Suppression Suppress a single line: ``` // prodlint-disable-next-line secrets const key = "sk_test_example_for_docs" ``` Suppress an entire file (place at top): ``` // prodlint-disable secrets ``` ## Links - [Homepage](https://prodlint.com): Overview, terminal demo, and quick start - [All 52 Rules](https://prodlint.com/rules): Complete rule reference with code examples - [MCP Server Setup](https://prodlint.com/mcp): Editor setup for Claude Code, Cursor, Windsurf - [Site Score](https://prodlint.com/score): Free AI agent-readiness scoring - [Free Tools](https://prodlint.com/tools): 7 AI agent policy file generators - [GitHub](https://github.com/prodlint/prodlint): Source code, issues, and GitHub Action - [npm](https://www.npmjs.com/package/prodlint): Package page with install instructions - License: MIT