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

@botim/mp-debug-sdk

v0.7.2

Published

Remote-debug SDK for BOTIM mini-programs — streams console, network, and error events to a BOTIM debug-relay for live inspection, with an AI-observable command channel.

Readme

@botim/mp-debug-sdk

Remote-debug your BOTIM mini-program. Stream console, network, and error events to a debug-relay you control; let humans tail live and let AI agents query, subscribe, and issue safe commands back to the device.

Why

Mini-programs run on user devices in environments you can't easily attach a debugger to. This SDK gives you:

  • Live logs of console.*, fetch, XMLHttpRequest, and uncaught errors.
  • AI-observable sessions — every event indexed by (miniProgramId, deviceId, sid) so resolver agents can pull errors and reproduce bugs without a human in the loop.
  • Safe AI command channel — agents can reload, dump-state, set-feature-flag, screenshot, ping, exec (default-on remote REPL), or any custom command you allow. Anything not registered is rejected.
  • Built-in redaction before the event ever enters the in-memory buffer.

Install

If your project's .npmrc pins the @botim scope to a private registry, override it for this package. This SDK is published to public npm. If your .npmrc contains a line like @botim:registry=<private-mirror-url>, plain npm install @botim/mp-debug-sdk will route to the private mirror, not find the package, and fail. Use:

npm install @botim/mp-debug-sdk --registry=https://registry.npmjs.org/

If your repo has no @botim scope override, the flag is harmless — npm uses registry.npmjs.org by default. Don't permanently re-pin the @botim scope to public npm in your .npmrc: it would shadow whatever private registry your other @botim/* packages come from.

1. Add the env config files

Each environment of your mini-program ships with one config file at the project root, in the standard BOTIM mini-program schema:

// botim.dev.json (real schema — abridged)
{
  "mp_id": "mbrx_p2p_dev",
  "app_id": "me.botim.rd.p2p",
  "version": "0.0.127",
  "app": {
    "version": "0.0.127",
    "md5": "fbd6b256d4961abe1cc7703984c31857"
  },
  "framework": { "version": "57.0.1" },
  "category": "Finance"
  // ...all other BOTIM platform fields are passed through untouched
}

Repeat for botim.uat.json, botim.beta.json, botim.prod.json. The plugin reads mp_id (the canonical mini-program id; the legacy miniProgramId field is also accepted) and derives a deterministic buildSignature from version + app.md5 so it correlates with each release rather than churning on platform-side metadata changes.

The plugin also auto-fills app.name (from app_id) and app.version (from version) so your enableRemoteDebug call doesn't have to repeat them.

2. Wire the Vite plugin

// vite.config.ts
import { botimDebug } from '@botim/mp-debug-sdk/vite';

// Pick the relay endpoint at build time. You control where logs go —
// the SDK never phones home to anything but this URL.
const RELAY_URL = process.env.RELAY_URL ?? 'http://localhost:8090';

export default (({ mode }: { mode: string }) => ({
  plugins: [botimDebug({ mode, relayUrl: RELAY_URL })],
}));

Switch envs by changing the build flag — no runtime branches:

vite build --mode dev      # picks botim.dev.json
vite build --mode uat      # picks botim.uat.json
vite build --mode beta     # picks botim.beta.json
vite build --mode prod     # picks botim.prod.json

If a matching botim.{mode}.json is missing or malformed, the build fails — wrong-env bundles can't ship.

Plugin options

| option | type | purpose | |---|---|---| | mode | string (optional) | Force a specific mode. When omitted, the plugin auto-reads mode from Vite's resolved config. | | mapMode | (mode) => env (optional) | Map a custom Vite mode name to a BOTIM env (defaults: development → dev, production → prod, others pass through). | | relayUrl | string (optional) | The relay endpoint the SDK will POST to. Baked into virtual:botim/config as botimConfig.relayUrl. Trailing slash stripped automatically. | | root | string (optional) | Project root for resolving botim.{mode}.json. Defaults to Vite's resolved root. |

3. (TypeScript) reference the virtual-module shim

In any .d.ts your tsconfig picks up (or in tsconfig.json#compilerOptions.types):

/// <reference types="@botim/mp-debug-sdk/vite/virtual-shim" />

Now import { botimConfig } from 'virtual:botim/config' type-checks (botimConfig.relayUrl included).

4. Enable remote debug at the entry point

import { enableRemoteDebug } from '@botim/mp-debug-sdk';
import { botimConfig } from 'virtual:botim/config';

const handle = await enableRemoteDebug({
  // The relay URL the plugin baked in. Falls back to same-origin if you
  // didn't pass `relayUrl` to the plugin (e.g. you're using a dev proxy).
  endpoint: botimConfig.relayUrl ?? location.origin,
  config: botimConfig,
  // app is optional — plugin auto-fills from app_id + version in
  // botim.{env}.json. Override only when you want a different name/version
  // reported in events.
  // app: { name: 'checkout-mp', version: '1.4.0' },

  // dev/uat/beta builds: consent is implicit
  // prod builds: provide a hostToken or set userOptIn after a privacy dialog
  consent: { userOptIn: true },

  // Optional host hooks the AI command channel can invoke
  builtins: {
    reload: () => location.reload(),
    getState: () => app.snapshot(),
    setFeatureFlag: (key, value) => app.flags.set(key, value),
    screenshot: async () => await canvas.toBase64PNG(),
  },

  onError: (err) => console.warn('[debug-sdk]', err),
});

That's it — console.*, network calls, and uncaught errors now stream to the relay.

Cross-origin setup

The SDK posts directly to endpoint — there's no proxy required. Your relay must allow the page's origin via CORS. A reference debug-relay implementation typically defaults to CORS_ORIGINS=* for development; tighten via env when going to production:

CORS_ORIGINS=https://my-mp.example.com,https://staging.example.com

5. Remote REPL (exec) — default-on

Once enableRemoteDebug returns, an attached agent can send a JS snippet to the device and read back the value, captured console.* output, or thrown error. No host wiring needed.

# From any terminal that can reach your relay:
curl -sX POST "<RELAY_URL>/v1/mp/<MP_ID>/devices/<DEVICE_ID>/commands" \
  -H 'content-type: application/json' \
  -d '{"name":"exec","args":{"code":"console.log(\"hi\"); return window.location.href"}}'

Result event:

{
  "type": "command-ack",
  "payload": {
    "command": "exec",
    "ok": true,
    "result": {
      "value": "https://my-mp.example.com/page",
      "logs": [{"method":"log","args":["hi"],"ts": 1735324800123}],
      "durationMs": 2
    }
  }
}

Inside the snippet, BOT, window, and document are bound as locals (with BOT resolved best-effort from window.BOT or Angular DI; null if unavailable). Top-level await works. Code is capped at 8 KB and 30 s.

To opt out (e.g. you ship a non-debug release that still uses the SDK for telemetry only):

await enableRemoteDebug({
  // ...,
  builtins: { exec: false },
});

To inject extra locals for your app:

await enableRemoteDebug({
  // ...,
  builtins: { exec: { globals: { app: myApp, store: myStore } } },
});
// agent can then call: { code: "return store.getState().user" }

Pre-buffer redaction (headers, JWT/long-token regex) is applied to result.value and result.logs before they leave the device buffer. The existing prod consent gate (hostToken or userOptIn) gates whether attach happens at all. See docs/recipes/exec.md for deeper notes.

6. Custom commands (optional)

Any AI agent with the right scope can request a command. The SDK only runs commands registered via registerCommand:

handle.registerCommand('clear-cart', async () => {
  await store.clearCart();
  return { cleared: true };
});

handle.registerCommand('set-locale', async (args) => {
  if (typeof args.locale !== 'string') throw new Error('args.locale required');
  i18n.setLocale(args.locale);
  return { locale: args.locale };
});

Anything not registered gets a command-rejected event with reason unknown-command.

7. Lifecycle

await handle.flush();    // force-send buffered events
await handle.stop();     // uninstall interceptors + drain queue
console.log(handle.sid); // server-issued session id

Production safety

  • No-op on disable: enableRemoteDebug({ enabled: false, ... }) returns an inert handle. No I/O, no globals wrapped.
  • Synchronous validation: bad config or missing consent throws immediately, before any interceptor is installed.
  • No-throw runtime: once attached, transport/network/redaction errors only surface via onError. Your app never observes a thrown error from the SDK.
  • Defense-in-depth redaction: header denylist + JWT/long-token regex + body byte cap, applied before events enter the buffer.
  • Single in-flight long-poll: at most one outbound request per device for the AI command channel.
  • Self-event suppression: the SDK captures fetch reference at import time and routes its own ingest/poll calls through that pre-interception fetch — no risk of the SDK observing itself and creating a feedback loop.

Debugging a live mini-program

Once your build is wired and shipped, see docs/live-debugging.md for the end-to-end runbook against your debug-relay deployment. It covers:

  • pointing the Vite plugin at the live relay URL,
  • pulling errors and tailing sessions from the admin UI,
  • a dedicated For AI agents section with curl recipes for /v1/mp/{mpId}/events, the SSE live-tail, and command POSTs.

API reference

| Symbol | Purpose | |---|---| | enableRemoteDebug(options) | Boot the SDK; returns a RemoteDebugHandle. | | botimDebug({ mode?, relayUrl?, mapMode? }) | Vite plugin; wire in vite.config.ts. | | resolveBotimConfig(mode, root) | Pure resolver, for non-Vite bundlers. | | BotimConfig | Type of botim.{env}.json after resolution. | | BotimConfigError | Synchronous throw on bad/missing config. | | BotimConsentError | Synchronous throw on missing consent in prod. | | RemoteDebugHandle.registerCommand(name, handler) | Allow an AI command. | | RemoteDebugHandle.flush() | Force-flush the in-memory buffer. | | RemoteDebugHandle.stop() | Uninstall and drain the queue. |

AI debug skill (Claude Code)

A Claude Code skill that teaches AI agents how to wire and consume this SDK lives at .claude/skills/botim-debug-relay/SKILL.md. Open Claude Code from this repo and the skill auto-loads — no setup needed. To use it from anywhere on your machine:

cp -r .claude/skills/botim-debug-relay ~/.claude/skills/

The file in this repo is a mirror. The canonical copy lives in botim-debug-relay/.claude/skills/botim-debug-relay/SKILL.md. Do not edit the SDK-side copy directly — your changes will be overwritten by the next sync. Edit in the relay repo, then run bash bin/sync-skill.sh from that repo to propagate here.

License

ISC © BOTIM