npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@alokraj68/plainspoken

v1.0.4

Published

Fail the build when writing reads as machine-written. A prose linter for AI fingerprints, filler and abstraction, with zero dependencies.

Readme

plainspoken

Fail the build when writing reads as machine-written.

CI npm version install size tests runtime deps License: MIT Node >=18 Claude Code

A prose linter with no dependencies, plus the judgement half as a Claude Code skill. It reads Markdown and plain text, not a schema, so it works on docs, READMEs, release notes, landing copy and CVs alike.

npx @alokraj68/plainspoken docs/
docs/architecture.md
  error   14  ai-phrase        "proven track record" has no defensible use
        We have a proven track record and are well-versed in scalable systems.
  error   14  adjective-pair   "scalable, secure" - two generic adjectives in a row
  error   31  vague-tail       trails off into a vague clause instead of landing on a result
        Built the reporting layer, enabling improved efficiency
  warn    22  ai-word          "leverage" - try: use, apply, draw on

1 file(s): 3 error(s), 1 warning(s)

Why another one

Most tools in this space fall into two camps. Word-list checkers flag "leverage" and call it a day, which teaches you to write "utilise" instead. Essay-tuned catalogues flag everything, including facts.

That second failure is the interesting one. A ~980-line published de-slop rule set, run against a real corpus of technical writing, produced nine hits and eight were false positives. It read "ported from Java to C#" as a false range and "Australia, Europe and the US" as tricolon abuse. Both are just true things.

A checker that fires on facts trains you to ignore it, which is worse than no checker. So the rules here were filtered the other way round: a pattern only ships if it fires on writing built to trip it and stays silent on writing that is merely factual. Both halves are asserted in the test suite.

Three of the rules come from sentences a real AI detector flagged, and were turned into checks rather than notes.

The thing underneath

Detectors flag abstraction, not vocabulary.

Managed extensive cloud infrastructure across the organisation.

Managed 80+ Azure servers and the team of interns who kept them patched.

The second is not better because the words are plainer. It is better because only someone who was there could have written it. When a sentence trips a rule, the fix is almost never a synonym.

Rules

Errors are fixed phrases with no defensible use. Warnings are heuristics, and heuristics make bad gates.

| Rule | Severity | Catches | |---|---|---| | ai-phrase | error | "proven track record", "well-versed in", "at the forefront of" | | filler-phrase | error | "responsible for", "team player", "improved performance" with no number | | prose-tell | error | throat-clearing, "serves as a", "imagine a world", stakes inflation | | adjective-pair | error | "scalable, secure platforms" | | tech-list-tail | error | sentences ending on a tool list instead of a result | | vague-tail | error | "…, enabling improved efficiency" (a tail with a number is fine) | | abstraction | warn | share of sentences naming no number and no proper noun | | passive-voice | warn | share of sentences in passive voice | | ai-word | warn | delve, harness, spearhead, cornerstone — with the plain word to use | | flat-rhythm | warn | three sentences of near-identical length in a row | | repeated-opener | warn | three list items opening on the same word | | em-dash | warn | more than two per document | | filler-adjective | warn | robust, seamless, world-class, mission-critical |

Code fences, inline code, frontmatter, URLs, link targets, HTML tags and tables are never linted, and line numbers still point at the original file.

Presets

npx @alokraj68/plainspoken docs/                    # docs (default) - ratios advise
npx @alokraj68/plainspoken cv.md --preset resume    # ratios become gates
npx @alokraj68/plainspoken . --preset strict        # everything fails

docs is deliberately forgiving: a short, factual README legitimately trips abstraction, and failing a build over that is how a linter gets deleted.

Config

plainspoken.config.json, or --config <path>:

{
  "preset": "docs",
  "maxEmDashesPerDoc": 2,
  "maxPassiveRatio": 0.25,
  "maxAbstractRatio": 0.5,
  "warnOnAiWords": true,
  "allow": ["realm"],
  "severity": { "flat-rhythm": "off" }
}

allow exists for words that are legitimate in your domain. Realm is a mobile database before it is a metaphor. Use it rarely, and leave a reason beside it.

Suppression

A document about banned phrases has to be able to quote them:

<!-- plainspoken-disable-next-line -->
Banned wording includes "responsible for" and "team player".

<!-- plainspoken-disable -->
...quoted slop...
<!-- plainspoken-enable -->

A suppression with a reason is documentation. One without is a checker being switched off.

As a Claude Code plugin

The linter catches phrases. The skill catches the thinking behind them — the plain-word table, the structural tells, and the rule that you change wording and never facts.

/plugin marketplace add alokraj68/craftkit
/plugin install plainspoken@craftkit

In CI

- run: npx @alokraj68/plainspoken docs/ README.md

Exit code is 1 on any error, 0 otherwise. --warnings-as-errors tightens that, and --json gives machine-readable output.

As a library

import { lint } from '@alokraj68/plainspoken';

const { findings, stats } = lint(markdown, { preset: 'resume' });

Credits

The AI-fingerprint rules build on ARPeeketi/claude-resume-kit. Seven prose patterns are distilled from the deslop skill in every-app/open-seo — the seven that survived the false-positive filter described above. The rest of that catalogue is deliberately not imported.

🧰 Part of craftkit

One of four tools in craftkit. Set all of them up at once, picking only what you need:

npx @alokraj68/craftkit

| | | | |---|---|---| | ✍️ plainspoken | you are here | prose that does not read as machine-written | | 📱 pagecheck | docs | pages that survive a phone: overflow, tiny text, tap targets, WCAG AA | | 📄 ats-resume | docs | a résumé an applicant tracking system can parse, and JD gap analysis | | 🧭 craft-setup | skill only | verify before claiming done; never commit unasked |

The skill ships with this package

skills/plain-writing/SKILL.md is the judgement half: the calls a linter cannot make. It installs as a Claude Code skill via the marketplace, and it is also in the npm tarball at node_modules/@alokraj68/plainspoken/skills/plain-writing/SKILL.md, so an agent can read it without the marketplace.

/plugin marketplace add alokraj68/craftkit
/plugin install plainspoken@craftkit

Elsewhere

  • 🛡️ eslint-plugin-typeorm-enterprise — the same principle pointed at TypeORM: block raw SQL, require transactions, guard multi-tenant queries. Not part of craftkit; it fails a build the same way. docs
  • 🌐 alokraj68.in — who writes these, and what they were built for.

Licence

MIT