nanocoai/add-wechat
Add WeChat (personal) channel integration via Tencent's official iLink Bot API. Uses long-polling and QR scan — no webhook, no ToS risk, no paid token.
npx skills add https://github.com/nanocoai/nanoclaw --skill add-wechat
Adds WeChat support via iLink Bot API — the first-party Tencent API for personal WeChat bots (different from WeCom / Official Account).
Why this is different from wechaty/PadLocal:
NanoClaw doesn't ship channels in trunk. This skill copies the WeChat adapter in from the channels branch.
Skip to Credentials if all of these are already in place:
src/channels/wechat.ts existssrc/channels/wechat-registration.test.ts existssrc/channels/index.ts contains import './wechat.js';wechat-ilink-client is listed in package.json dependenciesOtherwise continue. Every step below is safe to re-run.
git fetch origin channels
git show origin/channels:src/channels/wechat.ts > src/channels/wechat.ts
git show origin/channels:src/channels/wechat-registration.test.ts > src/channels/wechat-registration.test.ts
Append to src/channels/index.ts (skip if the line is already present):
import './wechat.js';
pnpm install [email protected]
pnpm run build
pnpm exec vitest run src/channels/wechat-registration.test.ts
Both must be clean before proceeding. wechat-registration.test.ts is the one integration test: it imports the real channel barrel and asserts the registry contains wechat. It goes red if the import './wechat.js'; line is deleted or drifts, if the barrel fails to evaluate (so the channel genuinely would not register), or if wechat-ilink-client isn't installed (the import throws) — so it also implicitly verifies the dependency from step 4. Importing is safe: the adapter opens its long-poll connection only in setup() (at host startup), never at import.
End-to-end message delivery against a real WeChat account is verified manually once the service is running — see Credentials and Wire your first DM above.
Unlike most channels, WeChat requires no pre-configured API keys. Auth happens via QR code scan from your phone.
Add to .env:
WECHAT_ENABLED=true
Restart NanoClaw.
Run from your NanoClaw project root:
source setup/lib/install-slug.sh
systemctl --user restart $(systemd_unit) # Linux
# or
launchctl kickstart -k gui/$(id -u)/$(launchd_label) # macOS
The adapter will print a QR URL to the logs and save it to data/wechat/qr.txt:
tail -f logs/nanoclaw.log | grep WeChat
# or
cat data/wechat/qr.txt
Open the URL in a browser (it renders a QR code), then:
data/wechat/auth.json — do not commit this fileThe bot is now connected as your WeChat account.
A successful QR login alone isn't enough — the adapter still needs to be wired to an agent group before it can respond.
Prerequisite: the host service must be running. The wire script creates the wiring through ncl, which talks to the running host over a Unix socket — there is no offline mode.
Have a different WeChat account send a message to the bot account. This auto-creates a messaging_groups row with the sender's platform_id and the unknown_sender_policy the WeChat adapter declares.
pnpm exec tsx .claude/skills/add-wechat/scripts/wire-dm.ts
Interactive flow: the script lists all unwired WeChat messaging groups, asks which agent group to wire it to, and runs ncl wirings create — engage mode/pattern and priority come from the WeChat adapter's declared channel defaults, so a wiring created here matches one created by /manage-channels or the approval-card flow.
With request_approval as the sender policy, the next DM from a stranger fires an approval card to the admin — admin taps Approve/Deny, approved users are added as members and their queued message replays through the agent.
Non-interactive:
pnpm exec tsx .claude/skills/add-wechat/scripts/wire-dm.ts \
--platform-id wechat:wxid_xxxxx \
--agent-group ag-xxxxx \
--non-interactive
Flags:
--platform-id <id> — wire a specific messaging group (default: most recent unwired)--agent-group <id> — target agent group (default: prompt; auto-picked when only one exists)--sender-policy public|strict|request_approval — override the messaging group's unknown_sender_policy (default: leave whatever the WeChat adapter declared when the row was auto-created)--session-mode shared|per-thread — default sharedEquivalent raw ncl invocation (host must be running):
ncl wirings create --messaging-group-id <mg-id> --agent-group-id <ag-id> --session-mode shared
Have the sender message the bot again — the agent should respond.
data/wechat/auth.json.WeChat: session expired in logs, delete data/wechat/auth.json and restart — you'll be asked to re-scan.data/wechat/sync-buf.txt holds the long-poll cursor. Deleting it replays recent history on next start; don't delete it in normal operation.If you're in the middle of /setup, return to the setup flow now.
Otherwise, restart the service to pick up the new channel and wiring.
wechatWeChat inbound platformId=wechat:<id>. Use wechat:<user_id> for DMs, wechat:<group_id> for rooms.init-first-agent.ts --admin-user-id) is saved to data/wechat/auth.json as operatorUserId after the QR scan. Read it with cat data/wechat/auth.json | jq -r .operatorUserId and prefix with wechat: (i.e. wechat:<operatorUserId>).shared session mode per messaging group (DM or room). Use strict sender policy if you want only specific users to reach the agent; public opens it to anyone who messages the bot.wire-dm.ts helper (see the "Wire your first DM" section above) if running this skill standalone. If running as part of bash nanoclaw.sh, init-first-agent.ts handles wiring — just pass the platform-id and admin-user-id captured above.Take nanocoai/add-wechat from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference npm.
Without those the skill loads but fails at the first command.