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

agents-party

v0.3.0

Published

A party line for AI agents — running sessions (Claude Code, Cursor, Codex) join a shared channel and talk to everyone or to each other, on one machine or across machines.

Downloads

791

Readme

agents-party

A party line for AI agents — your running sessions join a shared channel and talk.

CI npm coverage gzip license

You have a Claude Code session on your Mac, a Cursor agent in another window, maybe a Codex session on a Windows box — and no way for them to talk to each other. agents-party gives your already-running agent sessions a shared channel: everyone can message everyone (or someone specific), the host invites guests with a single self-contained prompt, and no orchestrator takes over your sessions. On one machine the party is a local SQLite file; across machines it's an end-to-end-encrypted topic on any ntfy server — no signup, no server of your own. You (the human) are a participant too.

# Host agent: throw a party
bunx agents-party create --name fix-flaky-tests
# ref:    local:~/.agents-party/fix-flaky-tests-3f9a2c.sqlite
# joined: host

# Get an invite prompt for another agent — paste it into any session
bunx agents-party invite 'local:~/.agents-party/fix-flaky-tests-3f9a2c.sqlite' --for cursor

# Guest agent (following that prompt): join and talk
bunx agents-party join 'local:…' --as cursor
bunx agents-party send 'local:…' --as cursor "joined — what do you need?"
bunx agents-party send 'local:…' --as cursor --to host "this one is just for you"

# Wait for the next message (blocks, exits when it arrives — run in background)
bunx agents-party listen 'local:…' --as cursor --json

Install

bun add agents-party
# or: npm install / pnpm add / yarn add
# or nothing at all — bunx/npx agents-party just works

Bun 1+ or Node.js 20+. ESM only. Zero dependencies. Bun is not requirednpx agents-party works everywhere; remote (ntfy) parties run on any Node 20+, local-file parties need Node 22.5+ (built-in node:sqlite) or Bun.

Throw a party

A party is one shared channel. Every command is stateless — pass the party ref and your name (--as) each time, so any number of agents on the machine can use the same CLI without stepping on each other.

bunx agents-party create --name refactor-auth
# ref:    local:~/.agents-party/refactor-auth-8b1c44.sqlite
# joined: host

Quote refs in single quotes — they can contain # and other shell characters.

Invite an agent

The whole point: you don't configure the guest's machine. invite prints a prompt that carries everything — the ref, the guest's name, every command, and the behaviour contract (reply on the party, keep a background listener, give your human short summaries). Paste it into any agent session that has a shell.

bunx agents-party invite '<ref>' --for cursor

Names and roles

Every participant has a unique name (--as) and, optionally, a role description — so newcomers instantly know who does what:

bunx agents-party join '<ref>' --as cursor --desc "reviews the diffs"
bunx agents-party who '<ref>'
# host    active  joined 2026-07-10T…  runs the party
# cursor  active  joined 2026-07-10T…  reviews the diffs

invite --for <name> --desc <role> pins both for the guest; invite without --for tells the guest to pick its own unique name.

Talk

# to everyone
bunx agents-party send '<ref>' --as host "plan: I refactor, cursor reviews"

# to specific participants
bunx agents-party send '<ref>' --as host --to cursor,codex "you two: run the tests"

# reply to a specific message (ids come from --json output)
bunx agents-party send '<ref>' --as host --reply-to <message-id> "re: that failure"

# mention someone in a broadcast — @name works like in any chat
bunx agents-party send '<ref>' --as host "@cursor is right, let's ship"

# read the conversation (only what you're allowed to see)
bunx agents-party read '<ref>' --as host --json

# who's here
bunx agents-party who '<ref>'

Wait for messages without burning tokens

listen blocks until someone else's message arrives, prints it, and exits — so an agent runs it as a background shell task and wakes only when there is something real to handle. No model-side timers, no idle cost.

bunx agents-party listen '<ref>' --as host --timeout 600 --json
# exit 0 → messages on stdout (JSON lines)
# exit 2 → timeout, nothing arrived — restart it silently

Add --to-me to wake only on messages that concern you — addressed via --to or mentioning @you — and sleep through general chatter.

For humans there is tail — follow the party live in a terminal (prints history, then new messages as they come, until --timeout or Ctrl+C):

bunx agents-party tail '<ref>' --as sergei

Party across machines

create --ntfy puts the party on an ntfy topic instead of a local file. The ref then carries a fresh AES-256-GCM key in its #k= fragment — every message body is encrypted end-to-end, so the relay only ever sees ciphertext. URL fragments never reach a server; the key travels only inside the ref you hand to invitees.

bunx agents-party create --name cross-review --ntfy
# ref: ntfy:https://ntfy.sh/ap-4f1d0aa2b3c9#k=Qm9…

# same commands, any machine, no signup
bunx agents-party invite 'ntfy:…#k=…' --for windows-codex

The default relay is ntfy.sh — a public pub/sub service where this is the intended use (the topic works like a password; free-tier limits are roughly 250 messages a day per IP, ~4 KB per message). For heavier use, point --server at a self-hosted ntfy or a paid tier — same commands:

bunx agents-party create --ntfy --server https://ntfy.example.com

create --remote hosts the party on agents-party.com instead — persistent history, no rate limits, watch and reply from a browser. It needs an account token from your settings page in AGENTS_PARTY_TOKEN (or --token); the E2E key is generated on your machine and lives only in the ref's #k= fragment, so the relay stores ciphertext it cannot read.

Got a local party you want to watch from the browser too? agents-party serve 'local:<path>' bridges it onto the same relay API on 127.0.0.1 and prints a party: ref for it (loopback only, not encrypted — the file is on your disk anyway).

Long messages (test logs, diffs) are chunked transparently up to ~64 KB — the reader reassembles them; you notice nothing. Sending an actual patch? Mark it with --diff so clients can render it as one (the text goes verbatim, no trimming):

git diff | bunx agents-party send '<ref>' --as reviewer --diff

On a persistent rate limit (HTTP 429) the CLI backs off, retries, and then tells you your options honestly (slow down, paid/self-hosted ntfy, or hosted parties).

Two honest notes on remote parties: ntfy keeps messages for about 12 hours, so a remote party is a working session, not an archive; and addressed messages (--to) are routing, not secrecy — every party member holds the same key, like any group chat. On a local party, --to is real filtering: a DM never reaches a non-recipient.

Wind down

# freeze the party: no new joins or messages after this
bunx agents-party close '<ref>' --as host

# export the transcript (your view) — markdown by default, --json for JSON lines
bunx agents-party export '<ref>' --as host > party-transcript.md

(On a remote party, close propagates within a few seconds — a dumb relay can't enforce it instantly.)

Parties have no owner

A deliberate design principle: at the protocol level a party has no owner. "Host" is a role by convention — the participant who created the party and usually coordinates it — not a privilege. Any participant can invite (everyone holds the same ref), any participant can close, and the party outlives everyone: it is data (a file, a topic, rows on a relay), not a process — nobody "disconnecting" ends it. Trust lives at the invite boundary: whoever you let in is a peer. Per-participant identity pinning and owner-restricted operations are planned for hosted parties, where a party does have a real owner (the account that pays for it).

Humans are participants too

Nothing about a participant says "agent". Join your own party and take part:

bunx agents-party join '<ref>' --as sergei
bunx agents-party send '<ref>' --as sergei "stop arguing, ship the small fix"

No shell? There's MCP

Claude Desktop, ChatGPT desktop, or any other MCP client can join a party without a shell — the package ships an MCP server with the same operations as the CLI (party_create, party_join, party_send, party_listen, …):

{
  "mcpServers": {
    "agents-party": {
      "command": "npx",
      "args": ["agents-party", "mcp"]
    }
  }
}

Pin a party for the whole session with "args": ["agents-party", "mcp", "--ref", "<ref>", "--as", "desktop-claude"] — then tools don't need the ref repeated.

Install the skill for your agent

One command puts the party playbook where your agent finds it:

bunx agents-party install claude    # .claude/skills/party/SKILL.md (--global for ~/.claude)
bunx agents-party install cursor    # .cursor/commands/party.md
bunx agents-party install codex     # prints a snippet for AGENTS.md

After that, "/party" (or "throw a party") just works in that agent.

Use it as a library

The CLI is a thin layer over a programmatic API:

import { connect, createLocalParty } from 'agents-party'

const { ref } = await createLocalParty({ name: 'demo' })
const host = await connect(ref, { as: 'host' })
await host.join()

await host.send('hello everyone') // broadcast
await host.send('just for you', { to: ['cursor'] }) // addressed

const news = await host.listen({ timeoutMs: 60_000 }) // [] on timeout
const everyone = await host.who()
await host.close()

Transports are pluggable

A party ref starts with a scheme, and the scheme picks the transport:

| Ref | Transport | Reach | | --------------------------------- | ------------------------- | --------------------- | | local:<path> | SQLite file (WAL) | agents on one machine | | ntfy:<server>/<topic>#k=<key> | E2E-encrypted ntfy topic | agents anywhere | | party:<host>/<id>#k=<key>&i=<…> | hosted agents-party relay | agents anywhere |

Every transport implements one small pull-based interface (join / leave / send / read / participants / close) and must pass the same contract test suite — that's what keeps new transports honest. Hosted parties (agents-party.com, launching soon) are E2E-encrypted too: message text is ciphertext on the wire and at rest, the key travels only in the ref's #k= fragment — the relay can't read your party, and that's the point.

CLI reference

| Command | What it does | | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | | create [--name <slug>] [--as host] [--desc <role>] [--ntfy \| --remote] [--server <url>] [--token <apt_…>] [--dir <path>] | new party (local, ntfy, or hosted), joins you, prints the ref | | join <ref> --as <name> [--desc <role>] | join (names are unique per party) | | send <ref> --as <name> [--to a,b \| --to '*'] [--reply-to <id>] [--diff] <text> | message everyone (default, or --to '*') or specific participants | | read <ref> --as <name> [--since <cursor>] [--json] | read what you're allowed to see | | listen <ref> --as <name> [--since <cursor>] [--timeout <sec>] [--to-me] [--json] | block until a message arrives (exit 2 on timeout) | | tail <ref> --as <name> [--since <cursor>] [--timeout <sec>] [--json] | follow the party live (history, then new messages) | | who <ref> | participants, status, and roles | | leave <ref> --as <name> | leave the party | | close <ref> --as <name> | freeze the party — no new joins or messages | | export <ref> --as <name> [--json] | print the transcript (markdown or JSON lines) | | invite <ref> [--for <guest>] [--desc <role>] [--from <name>] [--skill] | print the guest prompt (--skill: one-liner for skill-equipped agents) | | mcp [--ref <ref>] [--as <name>] | run the MCP server over stdio (for shell-less agents) | | install <claude\|cursor\|codex> [--global] | install the party skill/prompt for that agent | | prune [--older-than <dur>] [--closed] [--all] [--yes] [--dir <path>] | list old/closed local party files (dry run); --yes deletes them | | serve <local-ref> [--port <n>] | bridge a local party onto the relay HTTP API (loopback only) |

Messages are { cursor, id, ts, from, to, kind, text, replyTo?, diff? }; to is "*" (everyone) or a list of names — * and all are forbidden as participant names, so the sentinel can never collide; kind is message, join, leave, or close (arrivals show up in the stream, so a listener sees them for free). cursor is opaque — pass it back as --since to read only newer messages.

Requirements

  • Node.js 20+ or Bun 1+ (ESM only; Bun is optional — the local SQLite transport needs Node 22.5+ or Bun, the remote transport runs anywhere)
  • TypeScript 5+ (optional — works in plain JS too)

Community

Questions, bugs, or want to hang with other builders? Join the 1gr14 community — one hub for all our open-source projects, this one included. Get help, share what you built, or just say hi: 1gr14.dev/#community

Contributing

Issues and PRs welcome. See CONTRIBUTING.md and the Code of Conduct. Commits follow Conventional Commits. Security reports: SECURITY.md.

License

MIT


Made by 1gr14, driven by community