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-quiubo

v2.6.69

Published

OpenClaw Quiubo channel plugin — chat with AI assistants through Quiubo

Readme

openclaw-quiubo

OpenClaw channel plugin for Quiubo — chat with AI assistants through Quiubo's SDK API.

Installation

npm install openclaw-quiubo

Updating

openclaw plugins update openclaw-quiubo

Setup

openclaw channels add

The interactive wizard will:

  1. Prompt for your SDK API Key (starts with qub_)
  2. Authenticate against the Quiubo API
  3. List existing bot identities or create a new one
  4. Save the configuration

Prerequisites

| Item | Where to get it | |------|----------------| | SDK API Key | Quiubo app > Settings > Developer > API Keys | | Bot Identity | Created during setup wizard, or pre-create in Developer console |

Quick Start: Talking to your agent

Once setup completes, your agent is ready to chat:

  1. Open Quiubo — your agent appears as a contact with its own chat
  2. Send a message — the agent receives it and responds automatically
  3. Add to groups — invite the agent to any group, then @mention it to get its attention

How agents receive messages

| Context | How to trigger the agent | |---------|------------------------| | 1:1 chat (agent channel) | Just send a message — the agent always responds | | Group (agent is a member) | @mention the agent: @BotName do something | | Group (agent-only) | Every message triggers all agents (auto-broadcast) | | Group (directory agent) | @mention required — agents with triggerMode: "mention" only respond when mentioned |

@team shortcut

In groups with 2+ agents, type @Team to mention all agents at once. The @Team mention expands to individual agent mentions before delivery.

Scheduled messages

Agents can send messages on a schedule using cron jobs:

# Default agent — announce mode works
openclaw cron add --name "daily-report" --every 24h \
  --channel quiubo --to <group-uuid> --announce \
  --message "Generate and post the daily report."

# Named agent — use --no-deliver (agent sends the message itself)
openclaw cron add --name "standup" --agent my-agent --every 24h \
  --no-deliver --to <group-uuid> \
  --message "Post the daily standup to the group chat."

See Cron delivery for details on delivery modes.

Configuration

channels:
  quiubo:
    accounts:
      default:
        enabled: true
        apiUrl: https://api.quiubo.io
        apiKey: qub_...
        botIdentityId: <uuid>
        pollIntervalMs: 5000

| Field | Required | Default | Description | |-------|----------|---------|-------------| | apiKey | Yes | — | SDK API key (starts with qub_) | | botIdentityId | Yes | — | UUID of the bot's service identity | | enabled | No | true | Enable/disable this account | | apiUrl | No | https://api.quiubo.io | API base URL | | pollIntervalMs | No | 5000 | Polling fallback interval in ms |

Group context injection

The plugin injects group metadata (name, members, E2EE status, scopes) into agent prompts via the before_prompt_build hook. This lets agents know who's in the conversation without being told.

Required config — OpenClaw classifies before_prompt_build as a prompt injection hook and blocks it by default. You must explicitly allow it:

openclaw config set plugins.entries.openclaw-quiubo.hooks.allowPromptInjection true
openclaw gateway restart

Without this, the hook silently doesn't register — no error, no warning.

Multiple accounts

Run the setup wizard again and enter a different Account ID when prompted (e.g., support-bot, sales-bot). Each account gets its own gateway instance, cursor file, and bot config cache. For full multi-agent isolation (separate workspaces, models, cron jobs), see the Multi-Agent Setup guide.

Architecture

Message delivery

The plugin uses a dual-mode real-time gateway:

Pusher WebSocket (primary)  ─┐
                             ├──→ dedup ──→ onMessage() ──→ OpenClaw agent pipeline
Polling fallback (safety)   ─┘
  • Pusher WebSocket: Real-time push delivery via private-user-{botIdentityId} channel
  • Polling: Runs concurrently as a safety net (catches messages Pusher may silently miss)
  • Dedup: Both paths pass through cursor + in-memory dedup — no double-processing

Outbound messages are sent via the Quiubo SDK REST API.

Replay prevention

Four layers prevent old messages from being reprocessed on restart:

  1. Cursor persistence: Per-account cursor files at ~/.openclaw/cron/quiubo-cursors-{accountId}.json survive restarts
  2. seekToLatest(): On cold start (no cursor for a group), paginates to the latest message without processing — only subsequent messages are treated as new
  3. FIFO dedup set: In-memory dispatched set (capped at 500 entries with FIFO eviction) catches duplicates across Pusher and poll paths within a session
  4. Dedup guard on all delivery paths: Pusher plaintext, Pusher E2EE, and poll paths all check the dedup set before dispatching

Resilience

  • Exponential backoff: Poll failures increase delay (5s > 10s > 20s > 40s > 60s cap), resets on success
  • Poll concurrency limiter: Groups polled in batches of 5 via Promise.allSettled to avoid API burst
  • Gateway lifecycle safety: startAccount() stops any existing gateway before creating a new one (prevents orphaned timers on config reload)
  • Pusher timeout management: 15s connection timeout is properly cancelled on stop/restart

End-to-end encryption (E2EE)

The plugin supports Quiubo's E2EE protocol for groups that require it:

  • Key generation: Deterministic Ed25519 + X25519 keypairs derived from a 32-byte seed (persisted to ~/.openclaw/cron/quiubo-keys-{accountId}.json)
  • Auto-enrollment: On first startup, generates keypair and enrolls via challenge-response (requestKeyChallenge > signChallenge > verifyKeyChallenge)
  • Inbound decryption: GroupEnvelopeV2 messages decrypted using XChaCha20-Poly1305 with epoch keys
  • Outbound encryption: Plaintext encrypted before sending when E2EE is granted for the group
  • Epoch key management: Dual-layer cache (active key + historical keys per epoch) with 30-min TTL and automatic refresh
  • Pusher events: Handles e2ee-granted, e2ee-revoked, epoch-rotated for real-time key lifecycle

Directory agents

Agents can be listed in Quiubo's public agent directory, allowing any group to add them:

  • Auto-registration: If no agent record exists for the bot identity, one is created automatically on startup
  • Directory groups: Discovered via listAgentGroups() (refreshed every 60s) and polled alongside partner groups
  • Mention filtering: In directory groups, polled messages are only processed if they contain an @mention of the agent (Pusher path is pre-filtered server-side by triggerMode)
  • Scope enforcement: Outbound messages check grantedScopes — agent won't attempt to send if send_messages isn't granted
  • Real-time membership: Pusher events agent:group-added and agent:group-removed update the cache immediately

Bot-enabled gating

Every incoming message passes through a multi-step gating pipeline:

  1. Self-echo skip — Bot's own messages ignored
  2. Agent channel bypassagent_channel groups always process (1:1 bot channels)
  3. Cache miss resolution — Unknown groups fetched via API with 5s timeout (fail-closed)
  4. Bot-enabled checksettings.bot.enabled must be true
  5. Security mode checkPLAINTEXT_SDK or E2EE-granted groups only
  6. Owner takeover — Owner sends a message > bot suppressed for suppressionMinutes
  7. Suppression check — Skipped while suppressed (stale entries evicted after 1 hour)

Inbound routing

Messages are routed through OpenClaw's agent pipeline:

finalizeInboundContext() → dispatchReplyWithBufferedBlockDispatcher()

Session keys: quiubo:{groupId} for the main agent, agent:{agentId}:quiubo:{groupId} for non-main agents.

Auto-provisioning

On first gateway startup, if the bot has no groups, the plugin automatically creates a welcome agent_channel group, adds the bot as a member, and sends a welcome message.

Multi-Agent Setup

Run multiple agents on a single gateway — each with its own chat, model, workspace, and cron jobs.

  1. openclaw channels add — create a new bot identity
  2. Add the agent and binding to ~/.openclaw/openclaw.json
  3. Create the agent's workspace
  4. openclaw gateway restart

All agents share one SDK API key (and its quota). Each gets fully isolated conversations, cursors, and session keys.

Full guide — architecture, config examples, cron setup, and troubleshooting.

Markdown Attachments

Agents can send .md file attachments alongside messages. Attachments appear as tappable cards in the Quiubo app with a full markdown viewer.

OpenClaw's MEDIA: token protocol is used: when an agent writes a file and includes MEDIA: /path/to/file.md in its response, the plugin reads the file and sends it as a structured attachment.

Supported: .md files (max 1MB) and images — .jpg, .jpeg, .png, .webp (max 5MB, uploaded via S3 presign). Source tracking distinguishes agent vs subagent attachments.

Add this to your agent's AGENTS.md:

## Sending File Attachments

When you want to attach a markdown file to your reply:
1. Write the file to disk (e.g. `/tmp/report.md`)
2. Include a `MEDIA:` token in your response text pointing to the file path

Example response:
  Here's your daily report:

  MEDIA: /tmp/daily-report.md

The file will be delivered as a tappable attachment card in the chat.
Supported: `.md` (max 1MB) and images `.jpg`/`.png`/`.webp` (max 5MB).

Operational Notes

Per-account state files

Each account persists its own state files under ~/.openclaw/cron/:

| File | Purpose | Safe to delete? | |------|---------|-----------------| | quiubo-cursors-{accountId}.json | Message cursor positions | Yes — gateway will seekToLatest() on next start (no replay) | | quiubo-keys-{accountId}.json | E2EE key seed (32 bytes) | No — deleting forces re-enrollment, may break E2EE for existing conversations |

Heartbeat

If an agent is registered, the gateway sends a heartbeat every 60s to report connectionStatus: online. Heartbeat stops on Pusher disconnect and resumes on reconnect.

Typing indicators

A typing indicator is sent immediately when processing begins, then repeated every 4s until the response is delivered.

Scheduled messages / Cron delivery

Cron jobs that deliver to Quiubo groups must include --to <groupId>:

openclaw cron add --name "team-checkin" --every 30m --channel quiubo --to 7868cc21-... "Check in with the team"

Without --to, the extension cannot determine which group to deliver to. Unlike 1:1 sessions (which have a single bound chat), group sessions are multi-tenant — the target must be explicit.

Note: The --to value is the Quiubo group UUID, visible in the group detail screen or conversation URL.

Named agent crons

The --announce delivery mode does not work reliably with --agent <id> (see openclaw/openclaw#32432). The workaround is --no-deliver — the agent sends the message itself using the message tool:

openclaw cron add --name "giskard-standup" --agent giskard --every 24h \
  --no-deliver \
  --to 7868cc21-... \
  --message 'Post the daily standup summary to the Quiubo group chat.'

With --no-deliver, the cron skips the announce pipeline entirely. The agent receives the prompt and sends messages through its own account binding, which correctly resolves identity and group routing.

Why this works: Announce delivery resolves targets using a different code path that lacks proper account resolution for named agents. With --no-deliver, the agent uses the standard message tool path, which goes through the agent's own channel binding (quiubo:accountId).

Delivery mode comparison

| Mode | Flag | How it works | Named agent support | |------|------|-------------|-------------------| | Announce | --announce (default) | Cron delivers output via channel adapter | ❌ Fails for --agent | | No deliver | --no-deliver | Agent sends messages itself via message tool | ✅ Works | | Webhook | --webhook --to <url> | Cron POSTs to your endpoint | ✅ Works |

See #84 for a planned improvement to auto-resolve the target from the session bound group.

Managing Accounts

openclaw channels disable --channel quiubo  # Disable
openclaw channels add      # Re-configure

Development

npm run build       # Compile TypeScript
npm run typecheck   # Type-check without emitting
npm run release     # Bump version + publish

Project structure

index.ts             # Entry point + exports
src/
  api.ts             # REST API client (QuiuboApiClient)
  channel.ts         # Channel plugin (config, setup, onboarding, outbound, gateway)
  realtime-gateway.ts  # Pusher WebSocket + polling fallback + replay prevention
  crypto.ts          # E2EE: key generation, envelope decrypt/encrypt, Ed25519 signing
  key-manager.ts     # Dual-layer epoch key cache with auto-fetch
  runtime.ts         # Plugin runtime singleton
  types.ts           # TypeScript type definitions

API coverage

| Category | Methods | |----------|---------| | Auth | authenticate() | | Messages | sendMessage(), listMessages(), sendTypingIndicator() | | Groups | createGroup(), listGroups(), getGroup(), addMembers(), removeMembers(), listGroupMembers(), updateGroupSettings() | | Identities | createIdentity(), listIdentities(), deleteIdentity() | | Join Tokens | createJoinToken(), listJoinTokens(), deleteJoinToken() | | Agents | listAgents(), createAgent(), updateAgent(), sendHeartbeat(), listAgentGroups(), getGroupAgent() | | E2EE | requestKeyChallenge(), verifyKeyChallenge(), getEpochKey(), getEpochKeys() | | Pusher | pusherAuth() | | OpenClaw | sendOpenclawResponse() | | Webhooks | configureWebhook() |

Known Security Scanner Warnings

When installing, OpenClaw's plugin scanner may flag two patterns. Both are false positives:

  • "Shell command execution detected (child_process)" — From pusher-js's bundled XMLHttpRequest polyfill. This sync code path is never executed by the plugin.
  • "Environment variable access combined with network send" — The plugin reads process.env.HOME to locate ~/.openclaw/cron/ for persisting cursors and keys. No credentials flow through environment variables.

To suppress the auto-load warning, add the plugin to your allowlist in ~/.openclaw/openclaw.json:

{
  "plugins": {
    "allow": ["openclaw-quiubo"]
  }
}

License

MIT