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

iops-rollcall

v0.1.4

Published

Every AI process running on this machine, and what a stop could not reach. Zero dependencies.

Readme

rollcall

Every AI process running on this machine, and what a stop could not reach.

Published as iops-rollcall, and the command it installs is rollcall. The unprefixed name is refused by npm as too similar to an existing roll-call, which is worth saying out loud rather than leaving as a puzzle — and iops-rooms already uses the same shape.

npx [email protected]

Zero dependencies. Check it rather than believe it:

npm i [email protected] && npm ls
[email protected]
`-- [email protected]

Nothing beneath it. That is the whole tree.

npm view iops-rollcall dependencies prints nothing at all, which looks like a failed command and is not — npm omits the field entirely when a package has none, so blank is the answer. It is a poor way to learn something, which is why the check above is the one on this page.

This tool exists partly because of dependency-level attacks through npm, so shipping on npm is only defensible if you can verify that claim before you run anything. The version is pinned in every example here on purpose: a bare npx iops-rollcall resolves whatever was published most recently, at run time, which is the attack shape this is about.

What a first run looks like

$ npx [email protected]

22 processes matched, of 599 running — 1 application and 5 others.

  · Claude — pid 1296, plus 16 helper processes
      an application, so a stop reports it and leaves it running
      it can start agents again
      this command runs inside it
  · Codex — pid 10451
  · Claude Code — pid 18284
  · llama-server — pid 53492

Read 599 processes against 8 signatures, last checked on a real machine 2026-09-11.
6 processes report a name and no path, so no signature can be applied to them: Core Audio
Driver (MSTeamsAudioDevice.driver), autofsd, automountd, and more.
Not looked for: anything running on another machine, any request already in flight, any agent
these signatures do not name, and any work that has not started yet. Those are outside the
numbers above rather than counted as zero.

Most people cannot say what AI processes are running on their machine right now. That is the everyday reason this exists, and it needs no incident.

Stopping

npx [email protected] stop --dry-run   # what it would signal
npx [email protected] stop             # signal it, verify each one, write a record

No confirmation prompt. A switch that asks are you sure during an incident is broken, and the safety is in the targeting instead: it signals only what it can attribute to a signature it carries, and it prints exactly what it did.

It writes the record before it prints one. Run this during an incident, scroll the terminal, and the evidence is a buffer. The file holds what was stopped, what survived, what was refused and the "not looked for" section, which is the part somebody needs three days later.

Applications are reported and never quit. The conversation, the diff and the tool calls live inside the editor, and closing it destroys the record at the moment the record matters. A surviving application that can start agents again says so, because otherwise the count above it is not a final state.

A process owned by another user is reported and left alone. There is no suggestion to re-run with sudo. A switch that tells you to escalate privilege in order to kill things is the thing this is trying not to be.

What has not started yet

A process list answers what is running. It says nothing about the launchd agent that will start an agent at login, or the timer that will run one at three in the morning.

npx [email protected] schedules

It reads and changes nothing. Disabling a schedule is reversible and is deliberately not here: reporting has to be used for a while before anything acts on it.

Coverage is stated per source rather than as one number, because launchd, cron and systemd disagree about where truth lives and who may read them, and one figure across three sources of different reliability is a denominator made of parts that do not agree.

A schedule that exists and a schedule that is enabled are different facts, and a schedule whose state could not be read is a third. It reports whichever it has and never folds one into another. A scheduled command that names no absolute path yields nothing rather than a guess, because inventing one is how a registry starts matching text again.

What is in scope, and it is a boundary rather than a filter

AI processes, and terminal sessions those processes started. Nothing else.

A shell you opened is never listed, never stopped, never counted. The rule that decides is ancestry, not the executable, because the executable is identical either way: the same /bin/zsh is in scope under an agent and out of scope under your login window.

How it decides what is an agent

It matches the resolved executable path, never the command line.

That is not a preference. On the machine this was written on, four processes matched the text "cursor" and none of them was the Cursor editor — CursorUIViewService is the macOS text input service, and stopping it breaks typing. A grep searching for the word "claude" carries every name this tool looks for inside its own arguments. Both are negative test cases in the registry.

The registry is signatures.json — a data file you can open, audit and extend, and the shipped rows load through the same function --registry uses, so nothing built in follows looser rules than something you write. Every row validates itself when it is built: it refuses to exist unless it matches its own worked example and matches none of its own negative cases, so a careless row fails at load rather than in a test somebody might not write. A root match must end in a separator so it cannot swallow a neighbour, and a leaf match is an exact basename so llama-server cannot swallow llama-server-bench.

Every path in it was read off a running process on a real machine. A guessed path is a signature that matches nothing, behind a test that proves nothing, in a report silently missing a program it claims to cover. Programs that could not be confirmed are listed below rather than added.

Each row carries its own provenance — when it was confirmed and on which platform — and the report prints the age of the oldest row, because the weakest one speaks for the list. Run it somewhere none of them was checked and it says so:

Read 725 processes against 8 signatures, last checked on a real machine 2026-09-11.
None of them was confirmed on linux — 8 on darwin. A path that is right on one
system is usually wrong on another, so this list is shorter here than the count
suggests.

That sentence exists because a short result on an unfamiliar system otherwise reads as a quiet machine, and it is not one.

| recognised | not yet | |---|---| | Claude, Claude Code, Claude Code CLI | LM Studio | | Cursor, Cursor Agent | VS Code and its extensions | | Codex | Windsurf, Continue, aider | | Ollama, llama-server | MCP servers spawned by npx |

The gap is stated rather than closed with guesses, and closing it is the most useful thing an outside contributor can do here — it needs machines the maintainers do not have. You do not need to write any code: open an issue with the output of ps -axo pid=,comm= (macOS) or readlink -f /proc/<pid>/exe (Linux, where ps gives a truncated name rather than a path) and somebody can add the row from it. CONTRIBUTING.md has the evidence a pull request must show, and how rows are trusted once there are more of them than one person checked.

You can also point it at your own list without waiting for that:

npx [email protected] --registry ./my-agents.json

A file is an array of rows in the same shape as the built-in ones, and it goes through the same constructor — so it still cannot be a bare substring, still needs a worked example it matches and at least one case it must not, and still fails loudly rather than matching nothing quietly.

What it will not say

It reports what is running and what it could not reach. It does not tell you whether any of it should be, does not rank anything, and does not recommend an action. That is not a verdict withheld; it is a verdict this tool does not have.

It is also not a defence against hostile software. Anything that re-spawns itself, resists a signal or hides from ps is outside what this does, and it says so rather than implying a fight it never had. This is for work you started and want to stop.

Verbs

| | | |---|---| | rollcall | list what is running. The default, and it reads only | | rollcall list | the same, said out loud | | rollcall stop | signal what it can attribute, verify each one, write a record | | rollcall stop --dry-run | what stop would signal, without signalling it | | rollcall schedules | what will start later: launchd, cron, systemd timers. Reads only | | --registry <file> | use your own signatures instead of the built-in ones | | --json | machine-readable, for either verb |

Exit codes differ by verb, because the verbs answer different questions.

| | | |---|---| | list, schedules | 0 — they read something and told you. Finding agents is the normal case, and exiting non-zero on it would make these unusable in a shell | | stop | 0 when everything it recognised is stopped, 1 when something survived, was refused, or is an application it left running | | stop --dry-run | 1 when there is something it would signal | | any of them | 2 when it could not run: no such registry file, a manifest it cannot parse, a process table it cannot read |

stop exiting 1 is not a failure, it is the honest answer to "is this machine quiet now" when part of it is not.

macOS and Linux, and they are not equally covered — which the output says on every run rather than leaving in a footnote.

macOS gives a full executable path for every process, including other users'. Linux gives a truncated command name instead, so the path comes from /proc/<pid>/exe, and reading that for a process you do not own needs ptrace access. Running as yourself on Linux, processes belonging to another user are counted and named as unreadable rather than silently skipped. Kernel threads are counted apart from both, because they run no executable at all and calling them unreachable would overstate the gap.

Windows is not supported, and this says so rather than half-working there.

Contributing

CONTRIBUTING.md has the two rules and the setup, which is node --test test/*.test.js and nothing else — no build step, no dependencies, and it stays that way.

The registry is eight signatures and every path in it was confirmed on a Mac. Confirming a Linux path is the most useful thing an outside contributor can do here, because it needs a machine the maintainers do not have — see the good first issues. Pasting ps -axo pid=,comm= and readlink -f /proc/<pid>/exe for a program you want covered is enough on its own; someone else can add the row from that.

Please do not guess a path. A guessed signature matches nothing, behind a test that proves nothing, in a report silently missing a program it claims to cover.

Apache-2.0. Part of I-Ops.