prodlint 0.9.4 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,329 +1,332 @@
1
- # prodlint
2
-
3
- [![npm version](https://img.shields.io/npm/v/prodlint.svg)](https://www.npmjs.com/package/prodlint)
4
- [![npm downloads](https://img.shields.io/npm/dm/prodlint.svg)](https://www.npmjs.com/package/prodlint)
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
-
7
- Production readiness for vibe-coded apps.
8
-
9
- Static 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.
10
-
11
- ```bash
12
- npx prodlint
13
- ```
14
-
15
- ```
16
- prodlint v0.9.4
17
- Scanned 148 files · 2 critical · 5 warnings · 1 info
18
-
19
- src/app/api/checkout/route.ts
20
- 12:1 INFO No rate limiting — anyone could spam this endpoint and run up your API costs rate-limiting
21
- 28:5 WARN Empty catch block silently swallows error shallow-catch
22
-
23
- src/actions/submit.ts
24
- 5:3 CRIT Server action uses formData without validation next-server-action-validation
25
- ↳ Validate with Zod: const data = schema.safeParse(Object.fromEntries(formData))
26
-
27
- src/lib/db.ts
28
- 1:1 CRIT Package "drizzle-orm" is imported but not in package.json hallucinated-imports
29
-
30
- Scores
31
- security 72 ████████████████░░░░ (8 issues)
32
- reliability 85 █████████████████░░░ (4 issues)
33
- performance 95 ███████████████████░ (1 issue)
34
- ai-quality 90 ██████████████████░░ (3 issues)
35
-
36
- Overall: 82/100 (weighted)
37
-
38
- 2 critical · 5 warnings · 4 info
39
- ```
40
-
41
- ## Why?
42
-
43
- Vibe 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.
44
-
45
- prodlint checks what TypeScript and ESLint don't: **whether your vibe-coded app is ready for production**.
46
-
47
- ## Install
48
-
49
- ```bash
50
- npx prodlint # Run directly (no install)
51
- npx prodlint ./my-app # Scan specific path
52
- npx prodlint --json # JSON output for CI
53
- npx prodlint --sarif # SARIF 2.1.0 for GitHub Code Scanning
54
- npx prodlint --summary # Quick pass/fail + top 3 blockers
55
- npx prodlint --profile startup # Only critical findings
56
- npx prodlint --profile strict # All findings including info
57
- npx prodlint --baseline .prodlint-baseline.json # Only new findings
58
- npx prodlint --ignore "*.test.ts" # Ignore patterns
59
- npx prodlint --min-severity warning # Only warnings and criticals
60
- npx prodlint --quiet # Suppress badge output
61
- ```
62
-
63
- Or install it:
64
-
65
- ```bash
66
- npm i -D prodlint # Project dependency
67
- npm i -g prodlint # Global install
68
- ```
69
-
70
- ## 52 Rules across 4 Categories
71
-
72
- ### Security (27 rules)
73
-
74
- | Rule | What it checks |
75
- |------|----------------|
76
- | `secrets` | API keys, tokens, passwords hardcoded in source |
77
- | `auth-checks` | API routes with no authentication |
78
- | `env-exposure` | `NEXT_PUBLIC_` on server-only secrets |
79
- | `input-validation` | Request body used without validation |
80
- | `cors-config` | `Access-Control-Allow-Origin: *`, wildcard + credentials escalated to critical |
81
- | `unsafe-html` | `dangerouslySetInnerHTML` with user data |
82
- | `sql-injection` | String-interpolated SQL queries (ORM-aware) |
83
- | `open-redirect` | User input passed to `redirect()` |
84
- | `rate-limiting` | API routes with no rate limiter |
85
- | `phantom-dependency` | Packages in node_modules but missing from package.json |
86
- | `insecure-cookie` | Session cookies missing httpOnly/secure/sameSite |
87
- | `leaked-env-in-logs` | `process.env.*` inside console.log calls |
88
- | `insecure-random` | `Math.random()` used for tokens, secrets, or session IDs |
89
- | `next-server-action-validation` | Server actions using formData without Zod/schema validation |
90
- | `env-fallback-secret` | Security-sensitive env vars with hardcoded fallback values |
91
- | `verbose-error-response` | Error stack traces or messages leaked in API responses |
92
- | `missing-webhook-verification` | Webhook routes without signature verification |
93
- | `server-action-auth` | Server actions with mutations but no auth check |
94
- | `eval-injection` | `eval()`, `new Function()`, dynamic code execution |
95
- | `next-public-sensitive` | `NEXT_PUBLIC_` prefix on secret env vars |
96
- | `ssrf-risk` | User-controlled URLs passed to fetch in server code |
97
- | `path-traversal` | File system operations with unsanitized user input |
98
- | `unsafe-file-upload` | File upload handlers without type or size validation |
99
- | `supabase-missing-rls` | `CREATE TABLE` in migrations without enabling RLS |
100
- | `deprecated-oauth-flow` | OAuth Implicit Grant (response_type=token) |
101
- | `jwt-no-expiry` | JWT tokens signed without an expiration |
102
- | `client-side-auth-only` | Password comparisons or auth logic in client components |
103
-
104
- ### Reliability (11 rules)
105
-
106
- | Rule | What it checks |
107
- |------|----------------|
108
- | `hallucinated-imports` | Imports of packages not in package.json |
109
- | `error-handling` | Async operations without try/catch |
110
- | `unhandled-promise` | Floating promises with no await or .catch |
111
- | `shallow-catch` | Empty catch blocks that swallow errors |
112
- | `missing-loading-state` | Client components that fetch without a loading state |
113
- | `missing-error-boundary` | Route layouts without a matching error.tsx |
114
- | `missing-transaction` | Multiple Prisma writes without `$transaction` |
115
- | `redirect-in-try-catch` | `redirect()` inside try/catch — Next.js redirect throws, catch swallows it |
116
- | `missing-revalidation` | Server actions with DB mutations but no `revalidatePath` |
117
- | `missing-useeffect-cleanup` | useEffect with subscriptions/timers but no cleanup return |
118
- | `hydration-mismatch` | `window`/`Date.now()`/`Math.random()` in server component render path |
119
-
120
- ### Performance (6 rules)
121
-
122
- | Rule | What it checks |
123
- |------|----------------|
124
- | `no-sync-fs` | `readFileSync` in API routes |
125
- | `no-n-plus-one` | Database calls inside loops |
126
- | `no-unbounded-query` | `.findMany()` / `.select('*')` with no limit |
127
- | `no-dynamic-import-loop` | `import()` inside loops |
128
- | `server-component-fetch-self` | Server components fetching their own API routes |
129
- | `missing-abort-controller` | Fetch/axios calls without timeout or AbortController |
130
-
131
- ### AI Quality (8 rules)
132
-
133
- | Rule | What it checks |
134
- |------|----------------|
135
- | `ai-smells` | `any` types, `console.log`, TODO comments piling up |
136
- | `placeholder-content` | Lorem ipsum, example emails, "your-api-key-here" left in production code |
137
- | `hallucinated-api` | `.flatten()`, `.contains()`, `.substr()` — methods AI invents |
138
- | `stale-fallback` | `localhost:3000` hardcoded in production code |
139
- | `comprehension-debt` | Functions over 80 lines, deep nesting, too many parameters |
140
- | `codebase-consistency` | Mixed naming conventions across the project |
141
- | `dead-exports` | Exported functions that nothing imports |
142
- | `use-client-overuse` | `"use client"` on files that don't use any client-side APIs |
143
-
144
- ## Smart Detection
145
-
146
- prodlint avoids common false positives:
147
-
148
- - **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
149
- - **Monorepo support** — npm/yarn/pnpm workspace dependencies resolved automatically
150
- - **Framework awareness** — Prisma, Drizzle, Supabase, Knex, and Sequelize whitelists prevent false SQL injection flags
151
- - **Middleware detection** — Clerk, NextAuth, Supabase middleware detected — auth findings downgraded
152
- - **Block comment awareness** — patterns inside `/* */` are ignored
153
- - **Path alias support** — `@/`, `~/`, and tsconfig paths aren't flagged as hallucinated imports
154
- - **Route exemptions** — auth, webhook, health, and cron routes are exempt from auth/rate-limit checks
155
- - **Test/script file awareness** — lower severity for non-production files
156
- - **Fix suggestions** — findings include actionable `fix` hints with remediation code
157
-
158
- ## Scoring
159
-
160
- Each category starts at 100. Deductions per finding:
161
-
162
- | Severity | Deduction | Per-rule cap |
163
- |----------|-----------|--------------|
164
- | critical | -8 | max 1 |
165
- | warning | -2 | max 2 |
166
- | info | -0.5 | max 3 |
167
-
168
- **Diminishing returns**: after 30 points deducted in a category, further deductions are halved; after 50, quartered.
169
-
170
- **Weighted overall**: security 40%, reliability 30%, performance 15%, ai-quality 15%. Floor at 0. Exit code `1` if any critical findings exist.
171
-
172
- ## GitHub Action
173
-
174
- Add to `.github/workflows/prodlint.yml`:
175
-
176
- ```yaml
177
- name: Prodlint
178
- on: [pull_request]
179
-
180
- jobs:
181
- scan:
182
- runs-on: ubuntu-latest
183
- steps:
184
- - uses: actions/checkout@v4
185
- - uses: prodlint/prodlint@v1
186
- with:
187
- threshold: 50
188
- ```
189
-
190
- Posts a score breakdown as a PR comment and fails the build if below threshold.
191
-
192
- | Input | Default | Description |
193
- |-------|---------|-------------|
194
- | `path` | `.` | Path to scan |
195
- | `threshold` | `0` | Minimum score to pass (0-100) |
196
- | `ignore` | | Comma-separated glob patterns to ignore |
197
- | `comment` | `true` | Post PR comment with results |
198
-
199
- | Output | Description |
200
- |--------|-------------|
201
- | `score` | Overall score (0-100) |
202
- | `critical` | Number of critical findings |
203
-
204
- ### SARIF + GitHub Code Scanning
205
-
206
- Upload prodlint results to GitHub's Security tab:
207
-
208
- ```yaml
209
- - name: Run prodlint
210
- run: npx prodlint --sarif > prodlint.sarif
211
-
212
- - name: Upload SARIF
213
- uses: github/codeql-action/upload-sarif@v4
214
- with:
215
- sarif_file: prodlint.sarif
216
- category: prodlint
217
- ```
218
-
219
- ### Baseline for Existing Projects
220
-
221
- Adopt prodlint gradually without drowning in pre-existing findings:
222
-
223
- ```bash
224
- # Save current state as baseline
225
- npx prodlint --baseline-save .prodlint-baseline.json
226
-
227
- # CI only fails on NEW findings
228
- npx prodlint --baseline .prodlint-baseline.json
229
- ```
230
-
231
- ## MCP Server
232
-
233
- Use prodlint inside Cursor, Claude Code, or any MCP-compatible editor:
234
-
235
- **Claude Code:**
236
- ```bash
237
- claude mcp add prodlint -- npx -y prodlint-mcp
238
- ```
239
-
240
- **Cursor / Windsurf:**
241
- ```json
242
- {
243
- "mcpServers": {
244
- "prodlint": {
245
- "command": "npx",
246
- "args": ["-y", "prodlint-mcp"]
247
- }
248
- }
249
- }
250
- ```
251
-
252
- Ask your AI: *"Run prodlint on this project"* and it calls the `scan` tool directly.
253
-
254
- ## Site Score
255
-
256
- Check 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.
257
-
258
- ```bash
259
- npx prodlint --web example.com
260
- npx prodlint --web example.com --json # JSON output
261
- ```
262
-
263
- ```
264
- prodlint site score
265
- example.com · 14 checks
266
-
267
- Score: 42 C ████████░░░░░░░░░░░░
268
-
269
- ✗ AI-Disclosure Header 0/10 No AI-Disclosure header found.
270
- ✗ Content-Usage Directives 0/10 No Content-Usage directives found.
271
- ✗ TDMRep 0/10 No TDMRep found.
272
- ✗ A2A AgentCard 0/5 No agent-card.json found.
273
- ✗ ai.txt 0/5 No ai.txt found at site root.
274
- ! llms.txt 2/5 llms.txt found but missing key sections.
275
- ✓ robots.txt 10/10 robots.txt found with 15 rules.
276
- ✓ Sitemap 10/10 Valid sitemap with 42 URLs.
277
- ✓ Structured Data 10/10 Found JSON-LD structured data.
278
- ✓ OpenGraph 10/10 Complete OpenGraph tags found.
279
- ✓ Page Speed 5/5 Loaded in 0.8s.
280
- ✓ AI Bot Directives 5/5 AI-specific bot rules found.
281
- ✓ WebMCP Tools 0/5 No WebMCP tools detected.
282
-
283
- 7 passed · 5 failed · 1 warnings
284
-
285
- Full results: https://prodlint.com/score?url=example.com
286
- ```
287
-
288
- Or check your score interactively at [prodlint.com/score](https://prodlint.com/score).
289
-
290
- ## For AI Tools
291
-
292
- - **LLM-friendly docs**: [prodlint.com/llms.txt](https://prodlint.com/llms.txt) — concise project summary for LLMs
293
- - **Full reference**: [prodlint.com/llms-full.txt](https://prodlint.com/llms-full.txt) — all 52 rules with details
294
- - **MCP setup guide**: [prodlint.com/mcp](https://prodlint.com/mcp) — detailed editor setup for Claude Code, Cursor, Windsurf
295
-
296
- prodlint is designed specifically for AI-generated code patterns. Every rule checks for production issues that AI coding tools consistently create — not style nits.
297
-
298
- ## Suppression
299
-
300
- Suppress a single line:
301
- ```ts
302
- // prodlint-disable-next-line secrets
303
- const key = "sk_test_example_for_docs"
304
- ```
305
-
306
- Suppress an entire file (place at top):
307
- ```ts
308
- // prodlint-disable secrets
309
- ```
310
-
311
- ## Programmatic API
312
-
313
- ```ts
314
- import { scan } from 'prodlint'
315
-
316
- const result = await scan({ path: './my-project' })
317
- console.log(result.overallScore) // 0-100
318
- console.log(result.findings) // Finding[]
319
- ```
320
-
321
- ## Badge
322
-
323
- ```md
324
- [![prodlint](https://img.shields.io/badge/prodlint-85%2F100-brightgreen)](https://prodlint.com)
325
- ```
326
-
327
- ## License
328
-
329
- MIT
1
+ # prodlint
2
+
3
+ [![npm version](https://img.shields.io/npm/v/prodlint.svg)](https://www.npmjs.com/package/prodlint)
4
+ [![npm downloads](https://img.shields.io/npm/dm/prodlint.svg)](https://www.npmjs.com/package/prodlint)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ Production readiness for vibe-coded apps.
8
+
9
+ Static 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.
10
+
11
+ ```bash
12
+ npx prodlint
13
+ ```
14
+
15
+ ```
16
+ prodlint v0.10.0
17
+ Scanned 148 files · 2 critical · 5 warnings · 1 info
18
+
19
+ src/app/api/checkout/route.ts
20
+ 12:1 INFO No rate limiting — anyone could spam this endpoint and run up your API costs rate-limiting
21
+ 28:5 WARN Empty catch block silently swallows error shallow-catch
22
+
23
+ src/actions/submit.ts
24
+ 5:3 CRIT Server action uses formData without validation next-server-action-validation
25
+ ↳ Validate with Zod: const data = schema.safeParse(Object.fromEntries(formData))
26
+
27
+ src/lib/db.ts
28
+ 1:1 CRIT Package "drizzle-orm" is imported but not in package.json hallucinated-imports
29
+
30
+ Scores
31
+ security 72 ████████████████░░░░ (8 issues)
32
+ reliability 85 █████████████████░░░ (4 issues)
33
+ performance 95 ███████████████████░ (1 issue)
34
+ ai-quality 90 ██████████████████░░ (3 issues)
35
+
36
+ Overall: 82/100 (weighted)
37
+
38
+ 2 critical · 5 warnings · 4 info
39
+ ```
40
+
41
+ ## Why?
42
+
43
+ Vibe 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.
44
+
45
+ prodlint checks what TypeScript and ESLint don't: **whether your vibe-coded app is ready for production**.
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ npx prodlint # Run directly (no install)
51
+ npx prodlint ./my-app # Scan specific path
52
+ npx prodlint --json # JSON output for CI
53
+ npx prodlint --sarif # SARIF 2.1.0 for GitHub Code Scanning
54
+ npx prodlint --summary # Quick pass/fail + top 3 blockers
55
+ npx prodlint --profile startup # Only critical findings
56
+ npx prodlint --profile strict # All findings including info
57
+ npx prodlint --baseline .prodlint-baseline.json # Only new findings
58
+ npx prodlint --ignore "*.test.ts" # Ignore patterns
59
+ npx prodlint --min-severity warning # Only warnings and criticals
60
+ npx prodlint --quiet # Suppress badge output
61
+ ```
62
+
63
+ Or install it:
64
+
65
+ ```bash
66
+ npm i -D prodlint # Project dependency
67
+ npm i -g prodlint # Global install
68
+ ```
69
+
70
+ ## 52 Rules across 4 Categories
71
+
72
+ ### Security (27 rules)
73
+
74
+ | Rule | What it checks |
75
+ |------|----------------|
76
+ | `secrets` | API keys, tokens, passwords hardcoded in source |
77
+ | `auth-checks` | API routes with no authentication |
78
+ | `env-exposure` | `NEXT_PUBLIC_` on server-only secrets |
79
+ | `input-validation` | Request body used without validation |
80
+ | `cors-config` | `Access-Control-Allow-Origin: *`, wildcard + credentials escalated to critical |
81
+ | `unsafe-html` | `dangerouslySetInnerHTML` with user data |
82
+ | `sql-injection` | String-interpolated SQL queries (ORM-aware) |
83
+ | `open-redirect` | User input passed to `redirect()` |
84
+ | `rate-limiting` | API routes with no rate limiter |
85
+ | `phantom-dependency` | Packages in node_modules but missing from package.json |
86
+ | `insecure-cookie` | Session cookies missing httpOnly/secure/sameSite |
87
+ | `leaked-env-in-logs` | `process.env.*` inside console.log calls |
88
+ | `insecure-random` | `Math.random()` used for tokens, secrets, or session IDs |
89
+ | `next-server-action-validation` | Server actions using formData without Zod/schema validation |
90
+ | `env-fallback-secret` | Security-sensitive env vars with hardcoded fallback values |
91
+ | `verbose-error-response` | Error stack traces or messages leaked in API responses |
92
+ | `missing-webhook-verification` | Webhook routes without signature verification |
93
+ | `server-action-auth` | Server actions with mutations but no auth check |
94
+ | `eval-injection` | `eval()`, `new Function()`, dynamic code execution |
95
+ | `next-public-sensitive` | `NEXT_PUBLIC_` prefix on secret env vars |
96
+ | `ssrf-risk` | User-controlled URLs passed to fetch in server code |
97
+ | `path-traversal` | File system operations with unsanitized user input |
98
+ | `unsafe-file-upload` | File upload handlers without type or size validation |
99
+ | `supabase-missing-rls` | `CREATE TABLE` in migrations without enabling RLS |
100
+ | `deprecated-oauth-flow` | OAuth Implicit Grant (response_type=token) |
101
+ | `jwt-no-expiry` | JWT tokens signed without an expiration |
102
+ | `client-side-auth-only` | Password comparisons or auth logic in client components |
103
+
104
+ ### Reliability (11 rules)
105
+
106
+ | Rule | What it checks |
107
+ |------|----------------|
108
+ | `hallucinated-imports` | Imports of packages not in package.json |
109
+ | `error-handling` | Async operations without try/catch |
110
+ | `unhandled-promise` | Floating promises with no await or .catch |
111
+ | `shallow-catch` | Empty catch blocks that swallow errors |
112
+ | `missing-loading-state` | Client components that fetch without a loading state |
113
+ | `missing-error-boundary` | Route layouts without a matching error.tsx |
114
+ | `missing-transaction` | Multiple Prisma writes without `$transaction` |
115
+ | `redirect-in-try-catch` | `redirect()` inside try/catch — Next.js redirect throws, catch swallows it |
116
+ | `missing-revalidation` | Server actions with DB mutations but no `revalidatePath` |
117
+ | `missing-useeffect-cleanup` | useEffect with subscriptions/timers but no cleanup return |
118
+ | `hydration-mismatch` | `window`/`Date.now()`/`Math.random()` in server component render path |
119
+
120
+ ### Performance (6 rules)
121
+
122
+ | Rule | What it checks |
123
+ |------|----------------|
124
+ | `no-sync-fs` | `readFileSync` in API routes |
125
+ | `no-n-plus-one` | Database calls inside loops |
126
+ | `no-unbounded-query` | `.findMany()` / `.select('*')` with no limit |
127
+ | `no-dynamic-import-loop` | `import()` inside loops |
128
+ | `server-component-fetch-self` | Server components fetching their own API routes |
129
+ | `missing-abort-controller` | Fetch/axios calls without timeout or AbortController |
130
+
131
+ ### AI Quality (8 rules)
132
+
133
+ | Rule | What it checks |
134
+ |------|----------------|
135
+ | `ai-smells` | `any` types, `console.log`, TODO comments piling up |
136
+ | `placeholder-content` | Lorem ipsum, example emails, "your-api-key-here" left in production code |
137
+ | `hallucinated-api` | `.flatten()`, `.contains()`, `.substr()` — methods AI invents |
138
+ | `stale-fallback` | `localhost:3000` hardcoded in production code |
139
+ | `comprehension-debt` | Functions over 80 lines, deep nesting, too many parameters |
140
+ | `codebase-consistency` | Mixed naming conventions across the project |
141
+ | `dead-exports` | Exported functions that nothing imports |
142
+ | `use-client-overuse` | `"use client"` on files that don't use any client-side APIs |
143
+
144
+ ## Smart Detection
145
+
146
+ prodlint avoids common false positives:
147
+
148
+ - **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
149
+ - **Monorepo support** — npm/yarn/pnpm workspace dependencies resolved automatically
150
+ - **Framework awareness** — Prisma, Drizzle, Supabase, Knex, and Sequelize whitelists prevent false SQL injection flags
151
+ - **Middleware detection** — Clerk, NextAuth, Supabase middleware detected — auth findings downgraded
152
+ - **Block comment awareness** — patterns inside `/* */` are ignored
153
+ - **Path alias support** — `@/`, `~/`, and tsconfig paths aren't flagged as hallucinated imports
154
+ - **Route exemptions** — auth, webhook, health, and cron routes are exempt from auth/rate-limit checks
155
+ - **Test/script file awareness** — lower severity for non-production files
156
+ - **Fix suggestions** — findings include actionable `fix` hints with remediation code
157
+
158
+ ## Scoring
159
+
160
+ Each category starts at 100. Deductions per finding:
161
+
162
+ | Severity | Deduction | Per-rule cap |
163
+ |----------|-----------|--------------|
164
+ | critical | -8 | max 1 |
165
+ | warning | -2 | max 2 |
166
+ | info | -0.5 | max 3 |
167
+
168
+ **Diminishing returns**: after 30 points deducted in a category, further deductions are halved; after 50, quartered.
169
+
170
+ **Weighted overall**: security 40%, reliability 30%, performance 15%, ai-quality 15%. Floor at 0. Exit code `1` if any critical findings exist.
171
+
172
+ ## GitHub Action
173
+
174
+ Add to `.github/workflows/prodlint.yml`:
175
+
176
+ ```yaml
177
+ name: Prodlint
178
+ on: [pull_request]
179
+
180
+ jobs:
181
+ scan:
182
+ runs-on: ubuntu-latest
183
+ steps:
184
+ - uses: actions/checkout@v4
185
+ - uses: prodlint/prodlint@v1
186
+ with:
187
+ threshold: 50
188
+ ```
189
+
190
+ Posts a score breakdown as a PR comment and fails the build if below threshold.
191
+
192
+ | Input | Default | Description |
193
+ |-------|---------|-------------|
194
+ | `path` | `.` | Path to scan |
195
+ | `threshold` | `0` | Minimum score to pass (0-100) |
196
+ | `ignore` | | Comma-separated glob patterns to ignore |
197
+ | `comment` | `true` | Post PR comment with results |
198
+
199
+ | Output | Description |
200
+ |--------|-------------|
201
+ | `score` | Overall score (0-100) |
202
+ | `critical` | Number of critical findings |
203
+
204
+ ### SARIF + GitHub Code Scanning
205
+
206
+ Upload prodlint results to GitHub's Security tab:
207
+
208
+ ```yaml
209
+ - name: Run prodlint
210
+ run: npx prodlint --sarif > prodlint.sarif
211
+
212
+ - name: Upload SARIF
213
+ uses: github/codeql-action/upload-sarif@v4
214
+ with:
215
+ sarif_file: prodlint.sarif
216
+ category: prodlint
217
+ ```
218
+
219
+ ### Baseline for Existing Projects
220
+
221
+ Adopt prodlint gradually without drowning in pre-existing findings:
222
+
223
+ ```bash
224
+ # Save current state as baseline
225
+ npx prodlint --baseline-save .prodlint-baseline.json
226
+
227
+ # CI only fails on NEW findings
228
+ npx prodlint --baseline .prodlint-baseline.json
229
+ ```
230
+
231
+ ## MCP Server
232
+
233
+ Use prodlint inside Cursor, Claude Code, or any MCP-compatible editor:
234
+
235
+ **Claude Code:**
236
+ ```bash
237
+ claude mcp add prodlint -- npx -y -p prodlint prodlint-mcp
238
+ ```
239
+
240
+ **Cursor / Windsurf:**
241
+ ```json
242
+ {
243
+ "mcpServers": {
244
+ "prodlint": {
245
+ "command": "npx",
246
+ "args": ["-y", "-p", "prodlint", "prodlint-mcp"]
247
+ }
248
+ }
249
+ }
250
+ ```
251
+
252
+ `-p prodlint` runs the MCP server straight from the `prodlint` package, so you always get
253
+ the current scanner.
254
+
255
+ Ask your AI: *"Run prodlint on this project"* and it calls the `scan` tool directly.
256
+
257
+ ## Site Score
258
+
259
+ Check 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.
260
+
261
+ ```bash
262
+ npx prodlint --web example.com
263
+ npx prodlint --web example.com --json # JSON output
264
+ ```
265
+
266
+ ```
267
+ prodlint site score
268
+ example.com · 14 checks
269
+
270
+ Score: 42 C ████████░░░░░░░░░░░░
271
+
272
+ ✗ AI-Disclosure Header 0/10 No AI-Disclosure header found.
273
+ ✗ Content-Usage Directives 0/10 No Content-Usage directives found.
274
+ ✗ TDMRep 0/10 No TDMRep found.
275
+ ✗ A2A AgentCard 0/5 No agent-card.json found.
276
+ ✗ ai.txt 0/5 No ai.txt found at site root.
277
+ ! llms.txt 2/5 llms.txt found but missing key sections.
278
+ ✓ robots.txt 10/10 robots.txt found with 15 rules.
279
+ ✓ Sitemap 10/10 Valid sitemap with 42 URLs.
280
+ ✓ Structured Data 10/10 Found JSON-LD structured data.
281
+ ✓ OpenGraph 10/10 Complete OpenGraph tags found.
282
+ ✓ Page Speed 5/5 Loaded in 0.8s.
283
+ ✓ AI Bot Directives 5/5 AI-specific bot rules found.
284
+ ✓ WebMCP Tools 0/5 No WebMCP tools detected.
285
+
286
+ 7 passed · 5 failed · 1 warnings
287
+
288
+ Full results: https://prodlint.com/score?url=example.com
289
+ ```
290
+
291
+ Or check your score interactively at [prodlint.com/score](https://prodlint.com/score).
292
+
293
+ ## For AI Tools
294
+
295
+ - **LLM-friendly docs**: [prodlint.com/llms.txt](https://prodlint.com/llms.txt) — concise project summary for LLMs
296
+ - **Full reference**: [prodlint.com/llms-full.txt](https://prodlint.com/llms-full.txt) — all 52 rules with details
297
+ - **MCP setup guide**: [prodlint.com/mcp](https://prodlint.com/mcp) — detailed editor setup for Claude Code, Cursor, Windsurf
298
+
299
+ prodlint is designed specifically for AI-generated code patterns. Every rule checks for production issues that AI coding tools consistently create — not style nits.
300
+
301
+ ## Suppression
302
+
303
+ Suppress a single line:
304
+ ```ts
305
+ // prodlint-disable-next-line secrets
306
+ const key = "sk_test_example_for_docs"
307
+ ```
308
+
309
+ Suppress an entire file (place at top):
310
+ ```ts
311
+ // prodlint-disable secrets
312
+ ```
313
+
314
+ ## Programmatic API
315
+
316
+ ```ts
317
+ import { scan } from 'prodlint'
318
+
319
+ const result = await scan({ path: './my-project' })
320
+ console.log(result.overallScore) // 0-100
321
+ console.log(result.findings) // Finding[]
322
+ ```
323
+
324
+ ## Badge
325
+
326
+ ```md
327
+ [![prodlint](https://img.shields.io/badge/prodlint-85%2F100-brightgreen)](https://prodlint.com)
328
+ ```
329
+
330
+ ## License
331
+
332
+ MIT