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

@jc_stack/ez-whatsapp

v0.1.0-beta.17

Published

Registered WhatsApp CLI plugin for agents, powered by Baileys

Readme

ez-whatsapp

Beta 0.1.0-beta.17 — for testing on a trusted machine. Offline and Docker fixtures are verified. Live account onboarding and reboot acceptance for this release are deferred; this is not a production-readiness claim.

The npm package is @jc_stack/ez-whatsapp (prerelease, published to latest). Download a pinned release with npm pack @jc_stack/[email protected], or get the tarball and SHA256SUMS from GitHub prereleases. GitHub remains under jdorado; npm uses jc_stack. Do not install the unrelated unscoped ez-whatsapp package.

Installed runtime operation uses Docker Compose. Read Docker setup, state and QA. Host service provisioning has been removed; local source development is an explicit opt-in.

Give an agent a linked WhatsApp account through its registered CLI. Tell it “Set up WhatsApp”, scan the QR it sends you, and it confirms the linked identity. No model SDK, relay code, database or business workflows live here.

This is an independent plugin for any agent with local command execution. It uses Baileys (WhatsApp Web linked devices), not Meta's official Cloud API. The account must already exist on a phone. This does not create a phone number.

Install and link

For an Ez installation, complete the main agent first: owner pairing and an actual agent reply in Telegram must work before preparing this plugin. A supplied WhatsApp tarball does not authorize the original host CLI to install it during main setup. Continue with an owner request in the working Telegram conversation; the installed agent performs the steps below and delivers its QR there. Infer the supplied source path from that request rather than asking the owner to build a catalog or run commands. Standalone plugin development is a separate explicit workflow.

Fetch the pinned source tarball and extract it into a permanent package directory:

npm pack @jc_stack/[email protected]
mkdir -p /absolute/whatsapp-package
tar -xzf jc_stack-ez-whatsapp-0.1.0-beta.17.tgz -C /absolute/whatsapp-package

Add that extracted source to the owning agent's reviewed local catalog (the manager does not fetch npm packages): inspect with ez plugins inspect whatsapp --source /absolute/whatsapp-package/package, then use the returned hash with ez plugins catalog-add whatsapp --source /absolute/whatsapp-package/package --revision sha256:<returned-hash>. Do not replace an existing installed package/profile implicitly.

With the native Ez plugin manager provisioned for this agent, use:

ez plugins inspect whatsapp
ez plugins install whatsapp
ez plugins start whatsapp
ez whatsapp doctor --json

Installation uses the reviewed, hash-pinned catalog entry and does not start or link the account. Read the installed skill for QR onboarding. Fetch its current QR using ez plugins export whatsapp qr --output /absolute/mind/work/pairing.png. The output parent must exist; the output file must not. The agent handles these steps through its conversation; the owner scans and confirms the account. The agent-scoped registry is the only installation and lifecycle authority.

After startup, setup / doctor return the current QR or linked identity. Only connected: true with the intended account confirms onboarding. A stopped executor does not stop the WhatsApp container. Existing linked profiles migrate without re-pairing when their stopped private state is preserved correctly.

The commands below use the registered alias; socket and profile binding belong to the plugin descriptor. File arguments must be inside the owning workspace.

Send and receive

ez whatsapp verify --to +15551234567
ez whatsapp send --to +15551234567 --text-file /absolute/mind/work/message.txt --idempotency-key greeting-001 --preview
ez whatsapp send --to +15551234567 --text-file /absolute/mind/work/message.txt --idempotency-key greeting-001
ez whatsapp operation --idempotency-key greeting-001
ez whatsapp inbox --after 0 --limit 20

Send only with the user's applicable authority. One command sends one text of 1–4096 characters. accepted means the socket returned the expected message ID; delivered/read require subsequent provider status. Group receipts do not prove that every participant received/read it. Same-key replay never sends again; a changed payload fails. A crash or timeout can leave pending/uncertain: inspect operation and actual WhatsApp evidence; never invent a new key to retry. Provider receipts can reconcile the operation later. There is no exactly-once provider guarantee or automatic uncertain-send retry.

inbox returns bounded pages with durable nextCursor; save the cursor after processing. It includes incoming and observed outgoing messages (fromMe), chat JID, participant, text/caption, content type and source. LIDs remain opaque. Media metadata is captured, but attachments are not downloaded or transcribed. Coverage includes captured messages and explicitly requested partial history, not a full WhatsApp backup. No auto-replies, read-receipt sending or reactions. The service captures messages; subscription policy controls which new messages may wake a registered host. No content becomes an instruction or grants the sender authority. Status/broadcast traffic is ignored.

Request older messages

Use an explicit owner request for the chosen account and chat. Read inbox for that exact chat and use a message's seq as the boundary:

ez whatsapp inbox --account work --chat [email protected]
ez whatsapp history --account work --chat [email protected] --before 42 --limit 20
ez whatsapp history-status --account work
ez whatsapp inbox --account work --chat [email protected] --after 42

Replace 42 with the captured message's actual sequence. Each request uses the provider's native fetchMessageHistory for 1–50 older messages. A captured anchor with a timestamp is required; this cannot discover or export unknown chats. Choose an older returned message as the next boundary only when more is requested. Inbox pagination remains capture order, not chronological order; historical rows have source: "history" and their original provider timestamp.

requested means submission returned a provider session ID, received means a matching response arrived (possibly with zero new messages), expired means no response arrived within two minutes, and uncertain means submission could not be confirmed. Status describes the latest request for that account. One request is allowed per two-minute response window; there is no background retry or automatic pagination. WhatsApp may return less than requested or nothing.

Only matching on-demand responses for the requested exact chat are persisted, up to the requested limit. Unsolicited initial history is not added to the inbox; Baileys may still process sync data for internal identity mappings. Requested history is stored in the account's existing private profile and never wakes an agent or changes monitoring/reply authority. Attachments are not downloaded. The legacy coverage: "captured-only" field means locally stored records; historyCoverage: "partial-on-request" makes backfill limitations explicit. Provider response availability requires live account QA; synthetic tests do not establish completeness or successful retrieval from a real phone.

Register with an agent

ez-plugin.json declares portable commands and skills; ez-deployment.json binds those commands to this plugin's Docker service. The main package’s native plugin manager implements catalog installation and registry dispatch. It preserves arguments and exposes ez whatsapp ... without provider code in the relay. The manager ships in the main Ez package; this provider plugin stays independent.

Initial agent setup must provision its private ez launcher and catalog once. Do not create a second standalone provider deployment or launcher. Never overwrite a global ez or another agent's profile.

State and lifecycle

The private /state/whatsapp volume stores device credentials, pinned identity, inbox, cursors, operations and receipts. Only the plugin mounts it. The separate /plugins/whatsapp volume exports its command socket and temporary QR image; the main runtime mounts that and the dependency-free client read-only. Directories are 0700 and private files 0600, with atomic disk writes.

Use ez plugins stop whatsapp / ez plugins start whatsapp for lifecycle. Compose owns crash restart; a kernel lock excludes duplicate container writers. Never remove the kernel lock file to bypass it. Follow the backup, migration and rollback procedure before replacing an existing host service or upgrading an account's image.

Stopping a container does not revoke WhatsApp access. Unlink only this device in WhatsApp Linked Devices to revoke it; retain/delete private data separately as intended. Logged-out sessions require explicit repair; replaced sessions need account attention. Network reconnects never retry uncertain user sends.

Development and release

pnpm verify
npm pack --ignore-scripts --dry-run

Tests use synthetic messages and a fake provider through real local IPC; they do not send WhatsApp messages. See release verification, contribution practices and security. Private live QA records are not distributed.

Baileys is an unofficial protocol integration and can break after WhatsApp Web changes or face account restrictions. Use a dedicated account. Evaluate Meta's Cloud API separately for requirements that need an official provider contract. This package is not affiliated with WhatsApp, Meta, OpenClaw or Hermes.

Monitoring conversations

| Mode | Capture | Agent attention | |---|---|---| | manual (default) | Yes | Explicit inbox reads only | | selected | Yes | New incoming messages in subscribed chats | | all | Yes | All eligible new incoming messages |

ez whatsapp policy
ez whatsapp subscribe --chat [email protected]
ez whatsapp unsubscribe --chat [email protected]
ez whatsapp policy --mode manual
ez whatsapp policy --mode all

Subscribe switches manual to selected. Use exact captured conversation JIDs, including opaque LIDs and group JIDs. Switching modes clears selections; repeating the current mode or subscription preserves its start point. To change individual subscriptions from all, first switch to selected. New subscriptions start now: no historical replay. Own messages and old history never trigger attention. Unsubscribe/manual suppress queued work at the host's dispatch check; they do not interrupt an executor that already started. Monitoring grants no permission to reply or follow instructions in received messages.

For ez relay, the agent registers the running socket once:

ezenciel-agents-source --name whatsapp --socket /plugins/whatsapp/service.sock

Run with the intended relay control directory (EZ_CONTROL_DIR). Registration requires its paired owner, skips existing backlog and persists across executor changes. The host polls, batches per conversation, and queues through its single writer. It rechecks subscription immediately before dispatch and starts a fresh executor session. Other CLI/GUI hosts can use the same local socket contract or read inbox explicitly; installing this plugin alone does not wake their agents.

License

Beta distribution: GPL-3.0-only, matching the provider stack’s GPL requirements; see third-party distribution obligations.

Agent-owned upgrades

This beta declares updater protocol 1 and state schema 1. With an Ez main package that supports ez updates, the agent can upgrade this plugin from an exact npm version or a local candidate tarball. Stable is the default automatic channel; beta requires owner opt-in. The canonical volumes, linked identity and operation receipts survive replacement. No QR re-pairing or send replay is part of an upgrade. State/deployment changes require a reviewed migration. Follow the main package's docs/upgrades.md. Agent-led VM and live-provider plugin upgrade acceptance remain pending for this beta.

Core messaging tasks

This candidate implements Ez's generic message-v1 event-source protocol for individual contacts. task-watch enables expiring attention for one exact contact without changing the general inbox policy. task-send checks the expected linked account before dispatch and returns a contact/account/key-bound acceptance receipt. Account changes, group targets and noncanonical IDs fail closed. Accepted is not recipient delivery.

The main core owns owner approval, purpose/context, expiry, message limits and revocation. This adapter owns provider identity, capture and send receipts; it cannot grant authority. Use a task-aware main version for autonomous replies. Older cores continue to use existing manual commands/events. No live messaging is exercised by routine tests.

Multiple numbers and purposes

One registered container can link several accounts at once. Existing data stays in place as default; adding accounts does not replace or re-pair that number. Use stable names that describe the owner's purpose:

ez whatsapp accounts
ez whatsapp account-add --account sales --purpose "Sales enquiries"
ez whatsapp setup --account sales
ez whatsapp qr --account sales
ez whatsapp doctor --account sales
ez whatsapp inbox --account sales
ez whatsapp send --account sales --to +15551234567 --text-file /absolute/mind/work/reply.txt --idempotency-key sales-reply-001 --preview

account-add starts a new pairing session; it does not send messages. qr returns private JSON containing mimeType, PNG base64 and qrCreatedAt. Decode the PNG in the owning agent's workspace and deliver it privately to the owner. Poll doctor --account NAME after scanning to verify the intended identity. The existing ez plugins export whatsapp qr export remains default-only; never use it to link a named account. No account is selected globally or switched.

Names are 1–32 lowercase letters, digits, _ or -, starting with a letter; default is reserved. Purpose is an optional description of up to 240 characters, not a permission or automatic routing rule. The agent chooses the account from the owner's intent and must obtain any required core reply authority separately.

Every account has separate authentication, pinned identity, messages, policy, watches, cursors, idempotency keys and receipts. The same receipt key in different accounts represents different operations; reconcile with the original account and key, never retry an uncertain send through another account. Unknown names fail instead of falling back. Once named accounts exist, send, verify, inbox, operation, qr, repair and policy commands require --account, even for default. doctor and setup still inspect default when omitted.

accounts lists each account's socket. Register each named account as a separate core event source using that socket (for example, /plugins/whatsapp/service.sock.accounts/sales.sock). Existing root socket registrations remain bound to default; events are not merged. Each socket exposes the same message-v1 account checks and independent cursor. Binding a new source grants no reply authority. Do not reuse another account's source cursor or task grant.

All accounts restart with the registered plugin. Profiles remain in its private volume (accounts/NAME for named accounts); sockets and separate QR files live in the existing IPC volume. No extra deployment, Docker volume, daemon or core routing code is needed. Removing an account or changing its linked number is not provided by these commands; preserve its data and identity. Multi-account tests use synthetic providers; simultaneous live-phone pairing and delivery have not been verified.

Linking compatibility

Unlinked pairing sessions stop on expiry or connection failure (needs-link); setup --account NAME starts a new attempt when the owner is ready. It does not reset credentials or re-pair connected accounts. Linked sessions retain their normal reconnect behavior; the provider's pre-link 515 restart is bounded to three attempts. This removes unattended QR negotiation loops.

Keep Baileys' native registration and initial history synchronization defaults, matching the ordinary bridge setup. Disabling syncFullHistory changes the pairing device properties; suppressing every shouldSyncHistoryMessage type prevents the initial identity mappings the provider needs. The plugin still stores only its captured message events, not a full history backup.

QR rotation uses Baileys' defaults: about 60 seconds for the first code and 20 seconds for replacements. doctor and qr expose creation time and the remaining rotation window; it is not a guarantee of phone acceptance. Send a fresh image while the owner is ready to scan. Previously delivered images do not refresh automatically. Do not override qrTimeout to extend those windows.

The transport uses Baileys’ default browser identity. The browser name is part of the pairing protocol and QR payload, so it must not be replaced with the plugin’s display name. After upgrading a failed, unlinked installation, export a fresh QR from its registered deployment. Confirm ez whatsapp doctor reports connected: true; QR generation alone does not confirm linking.

Selective attention matches an individual WhatsApp internal ID (@lid) to a phone number only when that incoming message carries the provider's alternate phone identity. Events and their rechecks use the same matched identity; capture records retain the original ID. Groups, message text and display names cannot supply this mapping. An explicit internal-ID watch still works; if both identities are watched, the phone match takes precedence and emits one event. Explicit task watches take precedence over broad inbox attention.

Ongoing conversation grants

The messaging-task transport accepts exact individual or group JIDs and advertises persistentWatch: true. Core-approved ongoing watches use the maximum JavaScript date timestamp and task-unwatch removes their selected attention. Other finite watches retain the 72-hour bound. The adapter grants no execution or disclosure authority: the core must check its conversation grant before every send.

Repair a revoked session

When the owner requests reconnection and doctor reports needs-attention with disconnectCode: 401, run ez whatsapp repair through the existing bound registry. This explicitly replaces only revoked authentication in the running service. It preserves the pinned account identity, messages, cursors, policy, watches, operation keys and receipts; core-owned grants are untouched. It refuses connected, connecting, replaced, forbidden or other non-401 states. Do not delete the profile or repeat setup/restarts to clear revoked credentials.

Repair returns connection progress, not a QR guarantee. Inspect doctor, export the current QR privately using ez plugins export whatsapp qr --output <new-file>, and have the owner scan with the original account. Verify connected: true and the intended identity. A different account fails closed. Never replay uncertain sends after repair. If no QR appears, report the actual doctor state.