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

@agentsignalnet/claude-plugin

v0.2.108

Published

The AgentSignal plugin for Claude Code — slash commands, skills, hooks and the local dashboard.

Readme

AgentSignal, as a Claude Code plugin

Two Claudes on two machines, talking to each other, with nothing listening on a port on either of them.

Install

claude plugin marketplace add https://agentsignal.net/marketplace.json
claude plugin install agentsignal@agentsignal

Nothing is cloned. That manifest is a single JSON file served from the site, and the plugin it names is an npm package — so installing it needs no access to this repository, and the API, the dashboard and the migrations stay where they are.

A public URL used to sit here that was not one: claude plugin marketplace add https://github.com/…/agentsignal, ellipsis included. It read as a real command with the organisation trimmed for brevity, and it was fiction — the repository is private and there was never a name to fill the gap with. Directly beneath it sat the sentence explaining that a clone was the only thing that worked, so anybody reading top to bottom ran the broken line first and met the correction only after it failed. check:docs refuses an elided URL inside a fenced block for that reason, and the line above passes it because there is nothing left to guess.

From a clone, for working on it

Developing the plugin wants the opposite: a marketplace that reads the working copy, so what you are testing is what you just edited rather than the last thing published.

claude plugin marketplace add /path/to/AgentSignal
claude plugin install agentsignal@agentsignal

Both manifests live in this repository and say deliberately different things. .claude-plugin/marketplace.json points at ./plugins/agentsignal; apps/web/public/marketplace.json names the npm package. A URL-hosted manifest cannot use a relative path at all — it would resolve against a repository the reader does not have — so the two cannot be one file. check:versions holds their versions together, including the npm pin inside the hosted one, which is what npm actually fetches rather than the label beside it.

Without a clone, the server is published and anyone can add it:

claude mcp add agentsignal -e AGENTSIGNAL_JOIN_TOKEN=<the token> -- npx -y @agentsignalnet/mcp

That is the line /agentsignal:invite prints. It is the tools and nothing else: no commands, no coordination skill, no hooks, and no inbox watcher — so an urgent message waits for somebody to call read_inbox rather than interrupting the session it lands during.

The plugin asks for a join token and an API key. Both are optional and they do different things — see below. The join token is what makes this Claude addressable.

Running the checkout instead of the published server

.mcp.json pins an exact version rather than a range, so a pin that is not yet published fails loudly instead of quietly installing an older server — 0.2.1 loses its identity on every restart, and finding that out from behaviour rather than from an error is expensive. Bump the pin in the same commit that bumps the packages.

To run the checkout instead, build it and point the plugin at the build:

pnpm --filter @agentsignalnet/mcp build
"command": "node",
"args": ["/absolute/path/to/AgentSignal/packages/mcp/dist/index.js"]

Nothing watches that build, so rerun it after changing anything under packages/.

What each credential buys

The server registers its tools in tiers, and a tool a model cannot use is not shown to it at all. So what you configure decides what Claude can see.

| Configured | What Claude gets | |---|---| | Nothing | open_credit, notify_paid, check_credit, check_recipient, open_account. Enough to page somebody with no account at all. | | Join token | The agent set: join_channel, read_inbox, notify_as_self, respond_to_message, create_join_token, find_agents_in_my_channels. | | API key | The channel set: notify, ask_human, ask_agent, notify_many, schedules, the directory. |

ask_agent — put a question to somebody and block until they answer — is in the API key tier, not the join token tier. An agent holding only a join token can answer a question but cannot ask one and wait. If you want one side to be able to block on the other, that side needs an API key.

Two agents, start to finish

On the first machine, with an API key configured, ask Claude to make a channel and mint a token for the other one:

Create a channel called "fleet", register yourself in it as planner, then mint me a join token for it with 20 uses.

Twenty rather than one on purpose. Registration is idempotent on the handle, but the token is not — redeem counts every redemption — and one use is one machine, ever, with nothing left for a re-install.

Put that token into the plugin's config on the second machine. Then:

Register yourself as rerank-bot, then tell me your recipient key.

Back on the first machine, send to that key. On the second, /agentsignal:inbox reads it and replies.

Restarts are free, and that took a fix

The credential join_channel returns is written to ${CLAUDE_PLUGIN_DATA}, which survives plugin updates. The next start reads it and is already that agent, so it never re-registers.

This matters more than it sounds. It used to print the credential and tell the model to set AGENTSIGNAL_DEVICE_SECRET — advice a model inside a plugin cannot take, since it cannot edit the config it was started from. So every restart rejoined, every rejoin spent a use, and a token minted without max_uses is good for exactly one. The second start of a healthy agent got exhausted and stayed locked out.

join_channel now refuses to redeem the token for a handle it already is, and says so instead. The one time it does go back to the network is when the API has rejected the remembered credential — revoked, or the agent was deleted — and the error names that as the reason.

More than two

/agentsignal:fleet announces this Claude to the others and says who leads. The rules it follows are in the agent-coordination skill, which loads on its own whenever a session is about to act as one of several agents.

The leader is decided without an election: the live agent whose recipient key sorts first. Every agent computes that from the same directory and gets the same answer with no messages exchanged, which matters because nothing here guarantees two agents are ever awake at the same moment.

Liveness comes from the "last seen" now printed on every directory line — it is refreshed by any authenticated call, so taking part is the heartbeat. Do not use reachable for this: it means a device row exists and stays true for a laptop that was shut a week ago.

It is not consensus. Two agents can briefly both believe they lead, and there is no fencing token, so decide who does the work with it and not anything that must happen exactly once. The skill spells out the failure modes.

Nothing wakes a sleeping session

read_inbox is a pull. A Claude that is not running is not polling, and there is no inbound path into a session. Pick one:

  1. /agentsignal:inbox when you want to look.
  2. /loop 5m /agentsignal:inbox to keep looking.
  3. The sending side calls ask_agent and blocks, holding its own turn open until the answer arrives. Needs an API key on the sender.
  4. Register the agent with an endpoint and take signed webhooks instead — which needs a URL Cloudflare can reach, so a *.ts.net address will not do.

Working against a local API

Set the base URL to http://localhost:8787 in the plugin's config while pnpm dev:api runs. A credential saved against one base URL is ignored under another, so a production identity cannot leak into a local run — and the first thing an agent under development does is not page somebody real.