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

@peng272/dsh-wechat-ilink

v0.10.2

Published

WeChat ClawBot (Tencent iLink) channel for DeepSeek Harness 0.2.0-rc.2 — talk to DSH from WeChat.

Readme

@peng272/dsh-wechat-ilink

WeChat ClawBot (Tencent iLink) channel for DeepSeek Harness 0.2.0-rc.2 — talk to DSH from your WeChat chat window.

WeChat ──→ iLink gateway ──→ outbound long poll ──→ DSH session ──→ reply ──→ WeChat
                              (no public IP, no domain, no port forwarding)

Install

dsh plugin --profile <profile> add @peng272/dsh-wechat-ilink

The package name is scoped. The unscoped dsh-wechat-ilink on npm is a different, older package (0.6.5) by another maintainer — installing that one does not install this code.

The bundle inserts one row (wechat-clawbot) and its patch carries the default config. Nothing else is required: on first start, with no account bound, the channel requests a login QR code. The credential is stored under <DSH_HOME>/clawbot/ and reused on every later start.

Where the login QR appears

No window opens. The QR is delivered two ways, and both are files rather than a popup:

| Where | What | | --- | --- | | <DSH_HOME>/clawbot/login-qr.png | the scannable image — open it and scan with WeChat | | <DSH_HOME>/clawbot/channel.log | the same code as terminal ASCII art (QR ▀▄… lines), plus the raw login URL |

So a first run that "does nothing" has almost always already written login-qr.png. Check that file first. If the QR rendering itself fails, the raw login URL is still logged — rendering failure never blocks login.

To drive the login by hand instead:

dsh-wechat-ilink login

It prints the QR to the terminal as well, so it works even when nothing is watching the log.

Upgrading from 0.6.x

Nothing to do. The runtime identities are unchanged, so an in-place upgrade keeps your config, your bound account, and your message cursor. See CHANGELOG.md for the one list that matters: which config keys are currently accepted-but-inert (typing, acceptImages).

CLI

dsh-wechat-ilink login     # scan a QR code to bind a WeChat account
dsh-wechat-ilink status    # binding state and cursor
dsh-wechat-ilink logs [n]  # durable log tail
dsh-wechat-ilink logout    # unbind all accounts

Runs standalone — no DSH runtime needed. Equivalent long form: node lib/cli.js status.

Configuration

- id: wechat-clawbot
  name: '@peng272/dsh-wechat-ilink'
  config:
    enabled: true
    sessionId: 'wechat-clawbot'
    cwd: 'C:\path\to\your\workspace'
    allowedUserIds: []
    typing: true
    typingKeepaliveMs: 5000
    maxMessageChars: 2000
    acceptImages: true
    progressNotice: true
    turnTimeoutMs: 300000
    selfTestOnStart: false
    selfTestDelayMs: 3000
    logLevel: info

| Key | Default | Meaning | | --- | --- | --- | | enabled | true | Master switch. false loads the bundle without connecting. | | sessionId | wechat-clawbot | The DSH session the conversation is bound to; reused across restarts. | | cwd | workspace default | Working directory for the bound session. | | provider / model / reasoningEffort | DSH default | Accepted; currently the headless profile decides the route. | | allowedUserIds | [] | Extra WeChat ids allowed to drive the agent. Empty means only the account that scanned the QR may talk to the bot. | | typing / typingKeepaliveMs | true / 5000 | Accepted but not implemented in 0.7.0. | | maxMessageChars | 2000 | Outbound chunk size in characters. | | acceptImages | true | Accepted but not implemented in 0.7.0; image messages are ignored. | | progressNotice | true | Send a short "received, working on it" notice while a turn runs. | | turnTimeoutMs | 300000 | Abort a turn that runs longer than this. | | selfTestOnStart | false | Run one synthetic turn at startup and log the outcome. | | logLevel | info | silent | error | info | debug. debug logs inbound text. |

Extensions beyond the 0.6.x schema: baseUrl, stateDir, outgoingMaxPerSec, outgoingBurst, disableBridge.

Where state lives

<DSH_HOME>/clawbot/
  accounts.json                    index of bound account ids
  accounts/<accountId>.json        token, baseUrl, bound userId
  accounts/<accountId>.sync.json   get_updates_buf cursor
  channel.log                      durable log
  bridge.lock                      single-instance guard
  login-qr.png                     last rendered login QR (transient)

DSH_HOME defaults to %USERPROFILE%\.dsh.

Design notes

Single-instance guard

Two pollers on one bot steal messages from each other, silently. The channel takes a lock at <stateDir>/bridge.lock recording the holder's pid:

  • holder alive → this instance refuses to poll and logs the holder's pid;
  • holder gone → stale lock, this instance takes over.

The failure this prevents is real: a bridge is typically a supervisor chain (scheduled task → .cmd → node), and stopping the supervisor kills the outer layers while the node grandchild survives as an orphan and keeps polling. A fresh start then runs alongside it.

Shutdown removes only its own lock, so a successor's lock is never deleted.

Conversation driving

Each message runs dsh --profile headless --json --session-id <id> "<prompt>" and parses the NDJSON it emits (session / final / status.turn_end). --session-id gives the thread continuity.

One process per message, in exchange for not touching the in-process agent path at all — which also means this plugin declares no inject and cannot be blocked from activating by a missing service.

QR rendering

The gateway returns only a login URL, never an image:

https://liteapp.weixin.qq.com/q/xxxx?qrcode=<32 hex>&bot_type=3

lib/qr.js renders it in-package: byte mode, versions 1–10, ECC L/M, its own PNG encoder (1-bit greyscale, zlib), and a half-block terminal renderer. No runtime dependency on a QR library, and no third-party service ever receives the login credential.

Rendering failure never blocks login — the raw URL is always printed.

Known limits

  • The gateway throttles sends: roughly 5–6 messages in a burst earns ret=-2 for about an hour, and retrying during the penalty makes it worse. The channel paces outbound sends (outgoingMaxPerSec, default 0.5/s) and chunks long replies to stay under it. Re-scanning resets the penalty but changes the bot identity.
  • Config is read at startup: restart the bridge after editing the profile patch.
  • typing and acceptImages are accepted but inert in 0.7.0.

License

MIT