{"_id":"@alokraj68/plainspoken","_rev":"8-d9b29fc7bdf6aca46dff7bb99e01856d","name":"@alokraj68/plainspoken","dist-tags":{"latest":"1.1.1"},"versions":{"1.0.0":{"name":"@alokraj68/plainspoken","version":"1.0.0","keywords":["ai-detection","writing","linter","prose","slop","markdown","editorial","style-guide","claude-code","content-quality"],"author":{"url":"https://alokraj68.in","name":"Alok Rajasukumaran"},"license":"MIT","_id":"@alokraj68/plainspoken@1.0.0","maintainers":[{"name":"alokraj68","email":"alokraj68@gmail.com"}],"homepage":"https://github.com/alokraj68/plainspoken#readme","bugs":{"url":"https://github.com/alokraj68/plainspoken/issues"},"bin":{"plainspoken":"bin/plainspoken.mjs"},"dist":{"shasum":"b109c22fbf89cf7ab57a4c1e47d49967d3e2cd1d","tarball":"https://registry.npmjs.org/@alokraj68/plainspoken/-/plainspoken-1.0.0.tgz","fileCount":8,"integrity":"sha512-mVKPlc5pkTfTt45kudhW3e6pI2VYGQ+9J8P56h/CYBIyFRRTiX4KUpSNMuEv5izalkSYDs+KvFig7zQhlu8txg==","signatures":[{"sig":"MEYCIQCaGDD7YanTenDCND1F+852vwwtUCbqd6ULCgUv8C8ntAIhAJPh02b3ySj+JdqWyNot4rzgp4TJuQp6FhBT7qDXdqUV","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":39020},"type":"module","engines":{"node":">=18"},"exports":{".":"./src/lint.mjs","./rules":"./src/rules.mjs","./analyze":"./src/analyze.mjs"},"gitHead":"05c9fa12e71b85f896cdc473dcbc391104ad9fbe","scripts":{"test":"node test/run.mjs","lint:self":"node bin/plainspoken.mjs README.md"},"_npmUser":{"name":"alokraj68","email":"alokraj68@gmail.com"},"repository":{"url":"git+https://github.com/alokraj68/plainspoken.git","type":"git"},"_npmVersion":"11.13.0","description":"Fail the build when writing reads as machine-written. A prose linter for AI fingerprints, filler and abstraction, with zero dependencies.","directories":{},"_nodeVersion":"24.16.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/plainspoken_1.0.0_1787120584614_0.28937660522651787","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@alokraj68/plainspoken","version":"1.0.1","keywords":["ai-detection","writing","linter","prose","slop","markdown","editorial","style-guide","claude-code","content-quality"],"author":{"url":"https://alokraj68.in","name":"Alok Rajasukumaran"},"license":"MIT","_id":"@alokraj68/plainspoken@1.0.1","maintainers":[{"name":"alokraj68","email":"alokraj68@gmail.com"}],"homepage":"https://github.com/alokraj68/craftkit/tree/main/plugins/plainspoken#readme","bugs":{"url":"https://github.com/alokraj68/craftkit/issues"},"bin":{"plainspoken":"bin/plainspoken.mjs"},"dist":{"shasum":"95e92ea2c983e01c1ddb3f6a4f609d4720a4fd08","tarball":"https://registry.npmjs.org/@alokraj68/plainspoken/-/plainspoken-1.0.1.tgz","fileCount":8,"integrity":"sha512-kePbiOcVu2VTtdcCLwJYeVlVIvZj0DJKZx5unOVyU/9+VNBPHn+r8TyS/1kqhmIPyj7AeW2xRVH3qgldq0FUtw==","signatures":[{"sig":"MEQCIH1ngiZbmQS8/p4+7I/DHWF6ZCzUNlJXbtTVtdrOGudnAiBy9KF3zRwlswb8WX9W6yf2h06NXJbxn6cq6Ojs6RFxjA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alokraj68%2fplainspoken@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":39081},"type":"module","engines":{"node":">=18"},"exports":{".":"./src/lint.mjs","./rules":"./src/rules.mjs","./analyze":"./src/analyze.mjs"},"gitHead":"f5ee6e2d2130e235121dadd9bf5a9cedd81632ec","scripts":{"test":"node test/run.mjs","lint:self":"node bin/plainspoken.mjs README.md"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:28220664-cfcb-4b9f-bae1-44ef61fa6d0a"}},"repository":{"url":"git+https://github.com/alokraj68/craftkit.git","type":"git","directory":"plugins/plainspoken"},"_npmVersion":"12.0.2","description":"Fail the build when writing reads as machine-written. A prose linter for AI fingerprints, filler and abstraction, with zero dependencies.","directories":{},"_nodeVersion":"22.23.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/plainspoken_1.0.1_1787122963199_0.6177190961494747","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@alokraj68/plainspoken","version":"1.0.2","keywords":["ai-detection","writing","linter","prose","slop","markdown","editorial","style-guide","claude-code","content-quality"],"author":{"url":"https://alokraj68.in","name":"Alok Rajasukumaran"},"license":"MIT","_id":"@alokraj68/plainspoken@1.0.2","maintainers":[{"name":"alokraj68","email":"alokraj68@gmail.com"}],"homepage":"https://github.com/alokraj68/craftkit/tree/main/plugins/plainspoken#readme","bugs":{"url":"https://github.com/alokraj68/craftkit/issues"},"bin":{"plainspoken":"bin/plainspoken.mjs"},"dist":{"shasum":"dda43a3c8fb06ec16d1dec00fd8656eb0aa09c1a","tarball":"https://registry.npmjs.org/@alokraj68/plainspoken/-/plainspoken-1.0.2.tgz","fileCount":8,"integrity":"sha512-rBGPg+AVNI6ZygzV2r5poRU4HkBO+KUO9jUH8JSOnptu9fTovNiQzTNG0LdiqGyddiPwewc+PJrJC9pqhFmp2w==","signatures":[{"sig":"MEUCIFfIEePOO8kJbrSRvcR7afC2UUqFI/oOehDinP9Zwd0zAiEA5UGAzVCe8aN88Mllp7ztrVMuE8ybSzeAA3waqmoyE20=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alokraj68%2fplainspoken@1.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":39986},"type":"module","engines":{"node":">=18"},"exports":{".":"./src/lint.mjs","./rules":"./src/rules.mjs","./analyze":"./src/analyze.mjs"},"gitHead":"8daf28449d234ea33b996e4d9c1ce08eac72402e","scripts":{"test":"node test/run.mjs","lint:self":"node bin/plainspoken.mjs README.md"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:28220664-cfcb-4b9f-bae1-44ef61fa6d0a"}},"repository":{"url":"git+https://github.com/alokraj68/craftkit.git","type":"git","directory":"plugins/plainspoken"},"_npmVersion":"12.0.2","description":"Fail the build when writing reads as machine-written. A prose linter for AI fingerprints, filler and abstraction, with zero dependencies.","directories":{},"_nodeVersion":"22.23.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/plainspoken_1.0.2_1787143271264_0.16275370868487826","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@alokraj68/plainspoken","version":"1.0.3","keywords":["ai-detection","writing","linter","prose","slop","markdown","editorial","style-guide","claude-code","content-quality"],"author":{"url":"https://alokraj68.in","name":"Alok Rajasukumaran"},"license":"MIT","_id":"@alokraj68/plainspoken@1.0.3","maintainers":[{"name":"alokraj68","email":"alokraj68@gmail.com"}],"homepage":"https://github.com/alokraj68/craftkit/tree/main/plugins/plainspoken#readme","bugs":{"url":"https://github.com/alokraj68/craftkit/issues"},"bin":{"plainspoken":"bin/plainspoken.mjs"},"dist":{"shasum":"bb9266674ae7a959a12417b2709c53a48bb293c2","tarball":"https://registry.npmjs.org/@alokraj68/plainspoken/-/plainspoken-1.0.3.tgz","fileCount":8,"integrity":"sha512-JhqXV8RQDekFUzBrqnwVQj+bPjXEf0QieGwQNx//NhQQbESqpxBu7CNYXziQCB7GoXUgrIagxxmRg+u6yT0CMQ==","signatures":[{"sig":"MEUCIQDmmHNiEE9mlsalQEM4Pkxqr0nEOjlZwVn2tCXvFjPg2wIgOu/2gYlEhsXngoG2GSI7255guHkx6FNF+YfElcmtLxs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alokraj68%2fplainspoken@1.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":39986},"type":"module","engines":{"node":">=18"},"exports":{".":"./src/lint.mjs","./rules":"./src/rules.mjs","./analyze":"./src/analyze.mjs"},"gitHead":"6a104567001eecde56da879ba1c2b957654dc8b1","scripts":{"test":"node test/run.mjs","lint:self":"node bin/plainspoken.mjs README.md"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:28220664-cfcb-4b9f-bae1-44ef61fa6d0a"}},"repository":{"url":"git+https://github.com/alokraj68/craftkit.git","type":"git","directory":"plugins/plainspoken"},"_npmVersion":"12.0.2","description":"Fail the build when writing reads as machine-written. A prose linter for AI fingerprints, filler and abstraction, with zero dependencies.","directories":{},"_nodeVersion":"22.23.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/plainspoken_1.0.3_1787147474818_0.4901330435670548","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@alokraj68/plainspoken","version":"1.0.4","keywords":["ai-detection","writing","linter","prose","slop","markdown","editorial","style-guide","claude-code","content-quality"],"author":{"url":"https://alokraj68.in","name":"Alok Rajasukumaran"},"license":"MIT","_id":"@alokraj68/plainspoken@1.0.4","maintainers":[{"name":"alokraj68","email":"alokraj68@gmail.com"}],"homepage":"https://github.com/alokraj68/craftkit/tree/main/plugins/plainspoken#readme","bugs":{"url":"https://github.com/alokraj68/craftkit/issues"},"bin":{"plainspoken":"bin/plainspoken.mjs"},"dist":{"shasum":"9c6535fae4d64e12dd198818ada91dff6e8becb9","tarball":"https://registry.npmjs.org/@alokraj68/plainspoken/-/plainspoken-1.0.4.tgz","fileCount":8,"integrity":"sha512-Usd7ZSDuMM3nu3SFuBDmCIvpegJDCxsJVoB6htSoqD/uSOxTLlloyZNj0KI4zAmo3QoX742C8R0fE6vBtKbQxQ==","signatures":[{"sig":"MEUCIFMQkB/bvY5u5dZWCZ2+aQ6maAplF9NL8VyGj81vbqL0AiEA1h4iMyuyGcDJEfUU7yUGCv95EGw+LvuH2AM4cRn8x8s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alokraj68%2fplainspoken@1.0.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":40648},"type":"module","engines":{"node":">=18"},"exports":{".":"./src/lint.mjs","./rules":"./src/rules.mjs","./analyze":"./src/analyze.mjs"},"funding":[{"url":"https://github.com/sponsors/alokraj68","type":"github"},{"url":"https://buymeacoffee.com/alokraj68","type":"buymeacoffee"}],"gitHead":"3441a627b3328561f493710d37efd93a23066626","scripts":{"test":"node test/run.mjs","lint:self":"node bin/plainspoken.mjs README.md"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:28220664-cfcb-4b9f-bae1-44ef61fa6d0a"}},"repository":{"url":"git+https://github.com/alokraj68/craftkit.git","type":"git","directory":"plugins/plainspoken"},"_npmVersion":"12.0.2","description":"Fail the build when writing reads as machine-written. A prose linter for AI fingerprints, filler and abstraction, with zero dependencies.","directories":{},"_nodeVersion":"22.23.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/plainspoken_1.0.4_1787150853594_0.345741640618086","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@alokraj68/plainspoken","version":"1.0.5","keywords":["ai-detection","writing","linter","prose","slop","markdown","editorial","style-guide","claude-code","content-quality"],"author":{"url":"https://alokraj68.in","name":"Alok Rajasukumaran"},"license":"MIT","_id":"@alokraj68/plainspoken@1.0.5","maintainers":[{"name":"alokraj68","email":"alokraj68@gmail.com"}],"homepage":"https://github.com/alokraj68/craftkit/tree/main/plugins/plainspoken#readme","bugs":{"url":"https://github.com/alokraj68/craftkit/issues"},"bin":{"plainspoken":"bin/plainspoken.mjs"},"dist":{"shasum":"e730a326b48a1991ae8bb1e05fd2115051c18016","tarball":"https://registry.npmjs.org/@alokraj68/plainspoken/-/plainspoken-1.0.5.tgz","fileCount":8,"integrity":"sha512-3ZX9+rK5rhu4uDoZqpVHr2TRiyQFLm+OgpLI4GVr8NAD5B5P/XPSez7PeC7pLMlVcpTeM2kmfMAG2V77cqBH9A==","signatures":[{"sig":"MEQCIBzld4ImNyX3lbwlVr0EPiw6Cwk3z1LyuTc4UI64e0SyAiAWyUZSNg81HdOC3Qw1FuOGkrdEIXQ3UNIKAUWqXt4CnA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIGZd0SbNSIrRNwmlYFEwIKPJDpRtGZEAYW6sRlQIXRUsAiEAh4zHNG9R4Cr31PrraV8FG9Udd8EPMK9zzq4n6TwEEV0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alokraj68%2fplainspoken@1.0.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":40648},"type":"module","engines":{"node":">=18"},"exports":{".":"./src/lint.mjs","./rules":"./src/rules.mjs","./analyze":"./src/analyze.mjs"},"funding":[{"url":"https://github.com/sponsors/alokraj68","type":"github"},{"url":"https://buymeacoffee.com/alokraj68","type":"buymeacoffee"}],"gitHead":"95411314b7c02304acf9fb88813ef1a082a2d07c","scripts":{"test":"node test/run.mjs","lint:self":"node bin/plainspoken.mjs README.md"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:28220664-cfcb-4b9f-bae1-44ef61fa6d0a"}},"repository":{"url":"git+https://github.com/alokraj68/craftkit.git","type":"git","directory":"plugins/plainspoken"},"_npmVersion":"12.0.2","description":"Fail the build when writing reads as machine-written. A prose linter for AI fingerprints, filler and abstraction, with zero dependencies.","directories":{},"_nodeVersion":"22.23.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/plainspoken_1.0.5_1789916487901_0.6113497938674637","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@alokraj68/plainspoken","version":"1.1.0","keywords":["ai-detection","writing","linter","prose","slop","markdown","editorial","style-guide","claude-code","content-quality"],"author":{"url":"https://alokraj68.in","name":"Alok Rajasukumaran"},"license":"MIT","_id":"@alokraj68/plainspoken@1.1.0","maintainers":[{"name":"alokraj68","email":"alokraj68@gmail.com"}],"homepage":"https://github.com/alokraj68/craftkit/tree/main/plugins/plainspoken#readme","bugs":{"url":"https://github.com/alokraj68/craftkit/issues"},"bin":{"plainspoken":"bin/plainspoken.mjs"},"dist":{"shasum":"5ee1ed2e561e0b2406616d92f949ab1c818c8b2a","tarball":"https://registry.npmjs.org/@alokraj68/plainspoken/-/plainspoken-1.1.0.tgz","fileCount":8,"integrity":"sha512-u9fi04y+KN8WjLj4CouQiIVNl0mASphVfAg7wgVKbjEFQp25RnkKPCMC5YvWz7qOVahOQmFdWH+4BfbwFiIpYg==","signatures":[{"sig":"MEUCIQDlZ5vnK2ou9xHiSGECUy3gFpHoDctSMoHOrVTgl5pRcAIgbyYsWGLskZZIZZMmRCYFevuguYoi8Fw7F27S2r+lR8o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDV5iG0lGzzD6LFch1q9f9w3Bo1OPbjiHnl95nHDWPt5QIgX2Gu+9WcXP3fEVqnw0lzsdkjToXzzmS68yD5KqiAnEo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alokraj68%2fplainspoken@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":40648},"type":"module","engines":{"node":">=18"},"exports":{".":"./src/lint.mjs","./rules":"./src/rules.mjs","./analyze":"./src/analyze.mjs"},"funding":[{"url":"https://github.com/sponsors/alokraj68","type":"github"},{"url":"https://buymeacoffee.com/alokraj68","type":"buymeacoffee"}],"gitHead":"badfe0f536ce7f34416e0175537def1a6db8f767","scripts":{"test":"node test/run.mjs","lint:self":"node bin/plainspoken.mjs README.md"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:28220664-cfcb-4b9f-bae1-44ef61fa6d0a"}},"repository":{"url":"git+https://github.com/alokraj68/craftkit.git","type":"git","directory":"plugins/plainspoken"},"_npmVersion":"12.1.0","description":"Fail the build when writing reads as machine-written. A prose linter for AI fingerprints, filler and abstraction, with zero dependencies.","directories":{},"_nodeVersion":"22.23.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/plainspoken_1.1.0_1790269200784_0.9021475919980737","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"_id":"@alokraj68/plainspoken@1.1.1","bin":{"plainspoken":"bin/plainspoken.mjs"},"bugs":{"url":"https://github.com/alokraj68/craftkit/issues"},"dist":{"shasum":"64e56e7eb5987619c330fcde9098b6986a9b91ec","tarball":"https://registry.npmjs.org/@alokraj68/plainspoken/-/plainspoken-1.1.1.tgz","fileCount":8,"integrity":"sha512-3YA4Hd9QkcmEGWHCkTPEA2NMOJ+KArI5Julu5u+k7zEqmtUUoFkF45oWT3yDVT155lXxz8IrtZC9ezoylB/GEg==","signatures":[{"sig":"MEYCIQDh+XGKfolmwb0zOva3YgjIsA9RvyXPhapMLYoCatiyKgIhAM+XKjEcEbxG5PTOwUK6tZ4coE0vP3u0Y7Duiwa/sGlH","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDF491+db32wwYvhMh0hW7zvrSTnu8BdBYFgVVe5VNIVAiEAnUG2mfkHr0o9jsMslOawwgjRzwMAfxIggYK5ChpR65Y="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alokraj68%2fplainspoken@1.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":40651},"name":"@alokraj68/plainspoken","type":"module","author":{"url":"https://alokraj68.in","name":"Alok Rajasukumaran"},"engines":{"node":">=18"},"exports":{".":"./src/lint.mjs","./rules":"./src/rules.mjs","./analyze":"./src/analyze.mjs"},"funding":[{"url":"https://github.com/sponsors/alokraj68","type":"github"},{"url":"https://buymeacoffee.com/alokraj68","type":"buymeacoffee"}],"gitHead":"edcfb6387391328577f152c0b2ca84735fc19ac0","license":"MIT","scripts":{"test":"node test/run.mjs","lint:self":"node bin/plainspoken.mjs README.md"},"version":"1.1.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:28220664-cfcb-4b9f-bae1-44ef61fa6d0a"}},"homepage":"https://alokraj68.in/plainspoken","keywords":["ai-detection","writing","linter","prose","slop","markdown","editorial","style-guide","claude-code","content-quality","ai-slop","ai-writing-detection","technical-writing","documentation","readme","prose-lint","copywriting"],"repository":{"url":"git+https://github.com/alokraj68/craftkit.git","type":"git","directory":"plugins/plainspoken"},"_npmVersion":"12.1.0","description":"Fail the build when writing reads as machine-written. A prose linter for AI fingerprints, filler and abstraction, with zero dependencies.","directories":{},"maintainers":[{"name":"alokraj68","email":"alokraj68@gmail.com"}],"_nodeVersion":"22.23.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/plainspoken_1.1.1_1790298835481_0.5040767459543274"}}},"time":{"created":"2026-08-19T06:23:04.462Z","modified":"2026-09-25T01:13:55.941Z","1.0.0":"2026-08-19T06:23:04.743Z","1.0.1":"2026-08-19T07:02:43.423Z","1.0.2":"2026-08-19T12:41:11.440Z","1.0.3":"2026-08-19T13:51:15.016Z","1.0.4":"2026-08-19T14:47:33.711Z","1.0.5":"2026-09-20T15:01:27.987Z","1.1.0":"2026-09-24T17:00:00.864Z","1.1.1":"2026-09-25T01:13:55.586Z"},"bugs":{"url":"https://github.com/alokraj68/craftkit/issues"},"author":{"url":"https://alokraj68.in","name":"Alok Rajasukumaran"},"license":"MIT","homepage":"https://alokraj68.in/plainspoken","keywords":["ai-detection","writing","linter","prose","slop","markdown","editorial","style-guide","claude-code","content-quality","ai-slop","ai-writing-detection","technical-writing","documentation","readme","prose-lint","copywriting"],"repository":{"url":"git+https://github.com/alokraj68/craftkit.git","type":"git","directory":"plugins/plainspoken"},"description":"Fail the build when writing reads as machine-written. A prose linter for AI fingerprints, filler and abstraction, with zero dependencies.","maintainers":[{"name":"alokraj68","email":"alokraj68@gmail.com"}],"readme":"# plainspoken\n\nFail the build when writing reads as machine-written.\n\n[![CI](https://github.com/alokraj68/craftkit/actions/workflows/ci.yml/badge.svg)](https://github.com/alokraj68/craftkit/actions/workflows/ci.yml)\n[![npm version](https://img.shields.io/npm/v/%40alokraj68%2Fplainspoken.svg?logo=npm&color=0b7285)](https://www.npmjs.com/package/@alokraj68/plainspoken)\n[![install size](https://packagephobia.com/badge?p=@alokraj68/plainspoken)](https://packagephobia.com/result?p=@alokraj68/plainspoken)\n[![tests](https://img.shields.io/badge/tests-33-2EA043.svg)](#testing)\n[![runtime deps](https://img.shields.io/badge/runtime%20deps-0-2EA043.svg)](#)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n[![Node >=18](https://img.shields.io/badge/Node-%3E%3D18-339933.svg?logo=node.js&logoColor=white)](https://nodejs.org)\n[![Claude Code](https://img.shields.io/badge/Claude%20Code-plugin-D97757.svg)](https://github.com/alokraj68/craftkit)\n\nA prose linter with no dependencies, plus the judgement half as a Claude Code\nskill. It reads Markdown and plain text, not a schema, so it works on docs,\nREADMEs, release notes, landing copy and CVs alike.\n\n```\nnpx @alokraj68/plainspoken docs/\n```\n\n```\ndocs/architecture.md\n  error   14  ai-phrase        \"proven track record\" has no defensible use\n        We have a proven track record and are well-versed in scalable systems.\n  error   14  adjective-pair   \"scalable, secure\" - two generic adjectives in a row\n  error   31  vague-tail       trails off into a vague clause instead of landing on a result\n        Built the reporting layer, enabling improved efficiency\n  warn    22  ai-word          \"leverage\" - try: use, apply, draw on\n\n1 file(s): 3 error(s), 1 warning(s)\n```\n\n## Why another one\n\nMost tools in this space fall into two camps. Word-list checkers flag\n\"leverage\" and call it a day, which teaches you to write \"utilise\" instead.\nEssay-tuned catalogues flag everything, including facts.\n\nThat second failure is the interesting one. A ~980-line published de-slop rule\nset, run against a real corpus of technical writing, produced nine hits and\neight were false positives. It read \"ported from Java to C#\" as a false range\nand \"Australia, Europe and the US\" as tricolon abuse. Both are just true things.\n\n**A checker that fires on facts trains you to ignore it, which is worse than no\nchecker.** So the rules here were filtered the other way round: a pattern only\nships if it fires on writing built to trip it *and* stays silent on writing\nthat is merely factual. Both halves are asserted in the test suite.\n\nThree of the rules come from sentences a real AI detector flagged, and were\nturned into checks rather than notes.\n\n## The thing underneath\n\nDetectors flag **abstraction**, not vocabulary.\n\n> Managed extensive cloud infrastructure across the organisation.\n\n> Managed 80+ Azure servers and the team of interns who kept them patched.\n\nThe second is not better because the words are plainer. It is better because\nonly someone who was there could have written it. When a sentence trips a rule,\nthe fix is almost never a synonym.\n\n## Rules\n\nErrors are fixed phrases with no defensible use. Warnings are heuristics, and\nheuristics make bad gates.\n\n| Rule | Severity | Catches |\n|---|---|---|\n| `ai-phrase` | error | \"proven track record\", \"well-versed in\", \"at the forefront of\" |\n| `filler-phrase` | error | \"responsible for\", \"team player\", \"improved performance\" with no number |\n| `prose-tell` | error | throat-clearing, \"serves as a\", \"imagine a world\", stakes inflation |\n| `adjective-pair` | error | \"scalable, secure platforms\" |\n| `tech-list-tail` | error | sentences ending on a tool list instead of a result |\n| `vague-tail` | error | \"…, enabling improved efficiency\" (a tail with a number is fine) |\n| `abstraction` | warn | share of sentences naming no number and no proper noun |\n| `passive-voice` | warn | share of sentences in passive voice |\n| `ai-word` | warn | delve, harness, spearhead, cornerstone — with the plain word to use |\n| `flat-rhythm` | warn | three sentences of near-identical length in a row |\n| `repeated-opener` | warn | three list items opening on the same word |\n| `em-dash` | warn | more than two per document |\n| `filler-adjective` | warn | robust, seamless, world-class, mission-critical |\n\nCode fences, inline code, frontmatter, URLs, link targets, HTML tags and tables\nare never linted, and line numbers still point at the original file.\n\n## Presets\n\n```\nnpx @alokraj68/plainspoken docs/                    # docs (default) - ratios advise\nnpx @alokraj68/plainspoken cv.md --preset resume    # ratios become gates\nnpx @alokraj68/plainspoken . --preset strict        # everything fails\n```\n\n`docs` is deliberately forgiving: a short, factual README legitimately trips\n`abstraction`, and failing a build over that is how a linter gets deleted.\n\n## Config\n\n`plainspoken.config.json`, or `--config <path>`:\n\n```json\n{\n  \"preset\": \"docs\",\n  \"maxEmDashesPerDoc\": 2,\n  \"maxPassiveRatio\": 0.25,\n  \"maxAbstractRatio\": 0.5,\n  \"warnOnAiWords\": true,\n  \"allow\": [\"realm\"],\n  \"severity\": { \"flat-rhythm\": \"off\" }\n}\n```\n\n`allow` exists for words that are legitimate in your domain. Realm is a mobile\ndatabase before it is a metaphor. Use it rarely, and leave a reason beside it.\n\n## Suppression\n\nA document about banned phrases has to be able to quote them:\n\n```markdown\n<!-- plainspoken-disable-next-line -->\nBanned wording includes \"responsible for\" and \"team player\".\n\n<!-- plainspoken-disable -->\n...quoted slop...\n<!-- plainspoken-enable -->\n```\n\nA suppression with a reason is documentation. One without is a checker being\nswitched off.\n\n## As a Claude Code plugin\n\nThe linter catches phrases. The skill catches the thinking behind them — the\nplain-word table, the structural tells, and the rule that you change wording and\nnever facts.\n\n```\n/plugin marketplace add alokraj68/craftkit\n/plugin install plainspoken@craftkit\n```\n\n## In CI\n\n```yaml\n- run: npx @alokraj68/plainspoken docs/ README.md\n```\n\nExit code is 1 on any error, 0 otherwise. `--warnings-as-errors` tightens that,\nand `--json` gives machine-readable output.\n\n## As a library\n\n```js\nimport { lint } from '@alokraj68/plainspoken';\n\nconst { findings, stats } = lint(markdown, { preset: 'resume' });\n```\n\n\n## Credits\n\nThe AI-fingerprint rules build on\n[ARPeeketi/claude-resume-kit](https://github.com/ARPeeketi/claude-resume-kit).\nSeven prose patterns are distilled from the `deslop` skill in\n[every-app/open-seo](https://github.com/every-app/open-seo) — the seven that\nsurvived the false-positive filter described above. The rest of that catalogue\nis deliberately not imported.\n\n## 🧰 Part of craftkit\n\nOne of four tools in [craftkit](https://alokraj68.in/craftkit). Set all of\nthem up at once, picking only what you need:\n\n```bash\nnpx @alokraj68/craftkit\n```\n\n| | | |\n|---|---|---|\n| ✍️ **`plainspoken`** | you are here | prose that does not read as machine-written |\n| 📱 [`pagecheck`](https://www.npmjs.com/package/@alokraj68/pagecheck) | [docs](https://alokraj68.in/pagecheck) | pages that survive a phone: overflow, tiny text, tap targets, WCAG AA |\n| 📄 [`ats-resume`](https://www.npmjs.com/package/@alokraj68/ats-resume) | [docs](https://alokraj68.in/ats-resume) | a résumé an applicant tracking system can parse, and JD gap analysis |\n| 🧭 [`craft-setup`](https://github.com/alokraj68/craftkit/tree/main/plugins/craft-setup) | skill only | verify before claiming done; never commit unasked |\n\n### The skill ships with this package\n\n`skills/plain-writing/SKILL.md` is the judgement half: the calls a linter cannot make. It installs\nas a Claude Code skill via the marketplace, and it is also in the npm tarball at\n`node_modules/@alokraj68/plainspoken/skills/plain-writing/SKILL.md`, so an agent can read it without the marketplace.\n\n```\n/plugin marketplace add alokraj68/craftkit\n/plugin install plainspoken@craftkit\n```\n\n### Elsewhere\n\n- 🛡️ [`eslint-plugin-typeorm-enterprise`](https://alokraj68.in/eslint-plugin-typeorm-enterprise) — the same\n  principle pointed at TypeORM: block raw SQL, require transactions, guard multi-tenant\n  queries. Not part of craftkit; it fails a build the same way.\n  [docs](https://alokraj68.in/eslint-plugin-typeorm-enterprise)\n- 🌐 [alokraj68.in](https://alokraj68.in) — who writes these, and what they were built for.\n\n## Licence\n\nMIT\n","readmeFilename":"README.md"}