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

@openclaw/crabline

v0.1.1

Published

Standalone CLI for deterministic messaging provider E2E tests

Readme

crabline

Crabline deterministic messaging-channel QA

Deterministic local messaging-channel mocks for OpenClaw QA.

crabline is config-driven, CI-friendly, and deliberately has no openclaw dependency. It can run fixture-level local mocks, and it can also serve fake provider APIs that OpenClaw live adapters can target during deterministic QA.

What It Provides

  • local mock providers for discord, feishu, googlechat, imessage, loopback, matrix, mattermost, msteams, slack, telegram, whatsapp, and zalo
  • a script bridge for channels that are still exercised by external commands
  • per-provider local webhook endpoints for inbound events
  • fake provider servers for live-adapter smoke tests, starting with Telegram and WhatsApp
  • JSONL recorder files for deterministic wait/watch behavior
  • nonce-based send, roundtrip, agent, probe, run, watch, and doctor commands
  • text output by default and stable --json output for automation

Crabline fake servers are not live-provider coverage. They let OpenClaw run its normal channel adapter code against a local provider-shaped API. Release lanes still need the live driver and real provider credentials.

Install

pnpm install
pnpm build
pnpm verify

Run locally:

pnpm dev fixtures --config fixtures/examples/crabline.example.yaml
pnpm dev roundtrip telegram-dm --config fixtures/examples/crabline.example.yaml

Quality Gate

pnpm verify

That enforces formatting, typecheck, type-aware lint, and Vitest coverage.

Config

Config file search order:

  1. --config <path>
  2. ./crabline.yaml
  3. ./crabline.yml
  4. ./crabline.json

Top-level shape:

configVersion: 1
userName: crabline
providers:
  telegram:
    adapter: telegram
    telegram:
      recorder:
        path: ./.crabline/recorders/telegram.jsonl
      webhook:
        host: 127.0.0.1
        port: 8790
        path: /telegram/webhook
fixtures:
  - id: telegram-dm
    provider: telegram
    mode: roundtrip
    target:
      id: "100000001"
      behavior: agent

Provider ids are local profile names. Fixtures reference them through provider. Built-in adapters infer their platform from adapter; platform is required only for adapter: script.

Built-in provider credentials are optional metadata only. doctor checks explicit env declarations, script command availability, and config shape; it does not require live Slack, Discord, Telegram, WhatsApp, Matrix, iMessage, or other platform secrets for local mocks.

Built-In Mock Channels

All built-in mock providers support:

  • probe
  • send
  • roundtrip
  • agent
  • watch

The built-in providers are:

  • discord
  • feishu
  • googlechat
  • imessage
  • loopback
  • matrix
  • mattermost
  • msteams
  • slack
  • telegram
  • whatsapp
  • zalo

The script adapter can bridge any other OpenClaw channel by running local commands for probe, send, waitForInbound, or watch.

Fake Provider Servers

serve starts provider-shaped HTTP APIs for OpenClaw live adapters. This is the preferred Smoke CI path because OpenClaw still uses its normal channel adapter, but the provider endpoint is local and deterministic.

Telegram:

crabline --json serve telegram --ready-file .crabline/telegram-server.json

The JSON manifest contains:

  • endpoints.apiRoot: set OpenClaw channels.telegram.apiRoot to this value
  • botToken: set OpenClaw channels.telegram.botToken to this value
  • adminToken: send this as the X-Crabline-Admin-Token header when posting test user messages
  • endpoints.adminInboundUrl: authenticated POST endpoint for test user messages; OpenClaw reads them through Telegram getUpdates
  • recorderPath: JSONL file of fake provider API/admin traffic

The admin token is generated randomly unless --admin-token <token> is provided. The inbound endpoint rejects requests without the matching admin header (or Authorization: Bearer <token>).

Implemented Telegram Bot API endpoints include getMe, sendMessage, editMessageText, deleteMessage, setMessageReaction, createForumTopic, editForumTopic, pinChatMessage, unpinChatMessage, getUpdates, deleteWebhook, setWebhook, setMyCommands, deleteMyCommands, sendChatAction, and answerCallbackQuery.

WhatsApp:

crabline --json serve whatsapp --ready-file .crabline/whatsapp-server.json

The JSON manifest contains:

  • endpoints.apiRoot: Crabline WhatsApp fake provider API root
  • accessToken: bearer token for fake provider requests
  • adminToken: send this as the X-Crabline-Admin-Token header when posting test user messages
  • selfJid: fake authenticated WhatsApp user JID
  • endpoints.adminInboundUrl: authenticated POST endpoint for test user messages; subscribed Baileys mock sockets receive them as messages.upsert
  • endpoints.messagesUrl: fake text send endpoint used by the Baileys-shaped mock
  • endpoints.presenceUrl: fake presence endpoint used by sendPresenceUpdate
  • recorderPath: JSONL file of fake provider API/admin traffic

The started WhatsApp fake server also exposes createBaileysMockSocket() so tests can exercise a Baileys-style WhatsApp sendMessage() / sendPresenceUpdate() surface while the fake server owns local provider simulation. The admin token is generated randomly unless --admin-token <token> is provided.

OpenClaw bridge callers should post injected user messages with the providerUrl, providerHeaders, and providerBody returned by createOpenClawCrablineInbound(). For WhatsApp, inbound messages.upsert delivery is an in-process Baileys mock socket behavior: create the fake server and Baileys mock socket in the same Node process when testing listener-driven inbound delivery. If the socket is created outside the started server, pass the same WhatsAppBaileysMockRegistry to the server and socket helper.

Target IDs

Built-in providers accept native channel identifiers. Crabline does not add telegram:, discord:, slack:, or other local prefixes.

target:
  id: "C1234567890"

Thread targets use the platform's native thread identifier:

target:
  channelId: "C1234567890"
  threadId: "1700000000.000100"

Examples:

  • Slack conversations: C1234567890, G1234567890, or D1234567890
  • Slack threads: 1700000000.000100
  • Telegram chats: -1001234567890 or @channelusername
  • Telegram topics: 42
  • WhatsApp users: [email protected]
  • WhatsApp groups: [email protected]
  • Discord channels and threads: Discord snowflake ids such as 123456789012345678

Webhooks

Each built-in provider starts a local webhook during probe, waitForInbound, or watch. Webhook requests can use the provider's native event shape, or this simple JSON shape with native thread ids:

{
  "id": "slack-inbound-1",
  "threadId": "C1234567890",
  "text": "reply nonce-123",
  "author": "assistant"
}

Nested message payloads are also accepted:

{
  "message": {
    "id": "slack-inbound-1",
    "threadId": "C1234567890",
    "text": "reply nonce-123"
  }
}

Malformed webhooks return 400, and non-JSON requests return 415.

Evidence Flow

send records an outbound user event in the provider recorder. For roundtrip and agent modes, the local mock also records a deterministic assistant reply:

[telegram mock] hello nonce-123

waitForInbound reads the recorder until it finds a matching non-user event. watch streams matching recorder events. This gives CI channel coverage without live service latency, external credentials, webhooks exposed to the internet, or provider SDK state.

More Setup Detail

See Channel Setup for the provider matrix, webhook paths, and OpenClaw live-vs-mock guidance.