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

is-this-passive-aggressive

v0.1.0

Published

Paste an email, Slack message or text and see its passive-aggressive phrases decoded into what they actually mean — 'per my last email' → you ignored me, 'no rush, but' → rush, 'noted' → I disagree and I'm done. Venom scored 0–100, 100% local, rule-based,

Readme

is-this-passive-aggressive 😤

Paste an email, Slack message or text. Get its passive-aggressive phrases decoded into what they actually mean — with zero AI.

“Per my last email” → you ignored my last email. “No rush, but…” → rush. “Noted.” → I disagree and I’m done discussing it. “Looping in your manager” → I’m escalating because you didn’t respond.

A tiny, 100% local, rule-based tool that scans a message against a curated database of corporate passive-aggression, scores its venom 0–100, and tells you — for each phrase — what they really mean. No API key, no model, nothing leaves your machine.

🌐 Try it in your browser →

Paste a message, watch the venom light up. Nothing is uploaded — the whole engine runs client-side.

npx is-this-passive-aggressive "Per my last email, please advise. No rush, but I need this today."
  100/100 ████████████████████ Weapons-grade passive-aggressive ☠️
  3 passive-aggressive phrases in 12 words

  What they said → what they really mean
    “Per my last email” · Blame-shift
      ↳ You ignored my last email.
    “No rush but” · Fake “no rush”
      ↳ Rush. Definitely rush.
    “please advise” · Veiled threat
      ↳ Do something. This is now your problem.

Two ways to use it

  1. Before you send — paste your own draft and de-venom it. That “friendly reminder” lands harder than you think. Use --max-score to gate it in CI.
  2. After you receive — paste the message that made your eye twitch and get the subtext spelled out (and a laugh).

Why

Workplace messages have a second language running under the first. The polite surface (“just following up!”) carries a payload (“you’ve been ignoring me”). This decodes that payload: it highlights the phrases, groups them by type of passive-aggression, and translates each one.

It’s a decoder, not a mind-reader. Tone is context — a “friendly reminder” from a friend is friendly; from the person whose deadline you blew, less so. Read the clichés here; read the room yourself.

Install

npm i -g is-this-passive-aggressive     # then:  is-this-passive-aggressive draft.txt
# or zero-install:
npx is-this-passive-aggressive draft.txt

Usage

is-this-passive-aggressive "paste the message right here"   # a string
is-this-passive-aggressive draft.txt                        # a file
pbpaste | is-this-passive-aggressive                         # the clipboard (macOS)
is-this-passive-aggressive draft.txt --md > report.md        # Markdown table
is-this-passive-aggressive draft.txt --json                  # machine-readable

passagg is a shorter alias for the same command.

Flags

| Flag | What it does | | --- | --- | | --md [file] | Markdown table (What they said → what they really mean) | | --json [file] | Full report as JSON | | --max-score <n> | Exit 1 if venom exceeds n — a CI gate for de-venoming your own drafts | | --ignore <category> | Skip a category (repeatable) | | --quiet | No pretty output (use with --max-score) | | --no-color | Disable ANSI colors |

Lint your own outbox

is-this-passive-aggressive drafts/reply-to-dana.txt --max-score 20 --quiet

The categories

| Category | Signals | | --- | --- | | Blame-shift | “per my last email”, “as I mentioned”, “as previously discussed” | | The nudge | “just following up”, “circling back”, “bumping this”, “any update?” | | Fake-polite | “with all due respect”, “friendly reminder”, “thanks in advance” | | Condescension | “to be clear”, “as you may already know”, “for future reference” | | Veiled threat | “please advise”, “going forward”, “I’m sure it’s just an oversight” | | Cover-your-ass | “looping in your manager”, “adding for visibility”, “for the record” | | Fake “no rush” | “no rush, but”, “at your earliest convenience”, “whenever you have a moment” | | Dismissive | “noted”, “it is what it is”, “sure, that’s fine”, “k” |

Library

The core is pure and browser-safe (no node:*), so you can use it anywhere:

import { analyze } from "is-this-passive-aggressive";

const report = analyze("Per my last email, please advise.");
report.verdict.score;   // 100
report.verdict.band;    // "venom"
report.topFlags[0];     // { match: "Per my last email", category: "blame-shift", decode: "You ignored my last email.", count: 1 }

How the score works

Each phrase carries a weight; venom is the accumulated weight, scaled and capped at 100. We deliberately don’t normalize by length — “per my last email” is just as cutting in a one-liner as in a wall of text — so the score stays predictable and we can always show exactly which phrases produced it.

| Score | Band | | | --- | --- | --- | | 0–19 | Reads sincere | ✅ | | 20–44 | A little passive-aggressive | 🙂 | | 45–69 | Quite passive-aggressive | 😤 | | 70–100 | Weapons-grade passive-aggressive | ☠️ |

Privacy

Everything runs locally. The CLI reads your text, scores it in memory, and prints the result. The web playground runs the exact same engine compiled to the browser — open the network tab, you’ll see nothing leave. No telemetry, no account, no upload. Ever. (Which matters a lot when the thing you’re pasting is the email you’re furious about.)

Contributing

The most useful contribution is a new phrase — the corporate-speak, the category it belongs to, and an honest, funny-but-true decode. See CONTRIBUTING.md.

License

MIT © didrod205


A rule-based decoder, not a mind-reader. It reads the clichés — your judgment reads the room.