# Wechat Configure

> Set up the WeChat channel — scan QR code to login, check channel status. Use when the user asks to configure WeChat, login, or check channel status.

- Skill: `lc2panda/wechat-configure` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add lc2panda/wechat-configure`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lc2panda/wechat-configure/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: lc2panda (https://skillmd.com/u/lc2panda)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/lc2panda/wechat-configure

---

## Platform path detection

**Detect the platform before reading/writing any path:**

1. Check if `~/.pandacc` directory exists → **Codex environment**
   - Channel state: `~/.pandacc/channels/`
   - Plugin install dir: `~/.codex/plugins/cache/lc2panda-plugins/wechat/*/`
2. Otherwise → **Claude Code environment**
   - Channel state: `~/.claude/channels/`
   - Plugin install dir: `~/.claude/plugins/cache/lc2panda-plugins/wechat/*/`

**Once detected, use `<STATE_DIR>` to refer to the appropriate channel directory throughout this skill.**

# /wechat:configure — WeChat Channel Setup

Manages WeChat iLink Bot login and credential storage. Credentials live in
`<STATE_DIR>/credentials.json`.

Arguments passed: `$ARGUMENTS`

---

## Dispatch on arguments

### No args — status and guidance

Read both state files and give the user a complete picture:

1. **Credentials** — check `<STATE_DIR>/credentials.json` for
   `token` and `baseUrl`. Show set/not-set; if set, show token first 6 chars
   masked.

2. **Access** — read `<STATE_DIR>/access.json` (missing file
   = defaults: `dmPolicy: "pairing"`, empty allowlist). Show:
   - DM policy and what it means
   - Allowed senders: count and list
   - Pending pairings: count with codes and sender IDs

3. **What next** — concrete next step based on state:
   - No credentials → *"Run `/wechat:configure login` to scan QR code and connect."*
   - Credentials set, nobody allowed → *"Send a message to the bot on WeChat. It replies with a code; approve with `/wechat:access pair <code>`."*
   - Credentials set, someone allowed → *"Ready. Message the bot on WeChat to reach the assistant."*

### `login` — QR code login

This is a TWO-STEP process. The scripts are in the plugin install directory.
Find the plugin root by looking for the `channels/wechat/login-qr.ts` file:

```
<PLUGIN_DIR>/lc2panda-plugins/wechat/*/channels/wechat/login-qr.ts
```

Use `ls` to resolve the wildcard and get the actual path.

**Step 1: Fetch and display QR code**

```bash
bun <plugin-root>/channels/wechat/login-qr.ts
```

This script:
- Fetches a QR code from `https://ilinkai.weixin.qq.com/`
- Renders it in the terminal using `npx qrcode-terminal`
- Shows the direct link (user can open in WeChat)
- Outputs JSON as the last line: `{"qrcode":"...","url":"..."}`

**Wait for the user** after showing the QR code. Tell them:
*"用微信扫描二维码，或在微信中打开上面的链接。扫码完成后告诉我。"*

Extract the `qrcode` value from the last line of output — you'll need it
for step 2.

**Step 2: Poll for scan result**

After the user says they've scanned (or just proceed after showing the QR):

```bash
bun <plugin-root>/channels/wechat/login-poll.ts <qrcode>
```

This script polls the WeChat API for scan status. It outputs one line:
- `scaned` — user scanned, waiting for confirmation on phone
- `expired` — QR expired (exit code 1). Offer to re-run step 1.
- `timeout` — timed out (exit code 1). Offer to re-run step 1.
- `{"token":"...","baseUrl":"...","accountId":"...","userId":"..."}` — success!
  Credentials saved and scanner added to allowlist. (exit code 0)

On success, tell the user:
- *"✅ 微信连接成功！"*
- Credentials saved, user added to allowlist
- *"重启 Claude Code（Codex 用户：重启 Codex 会话）以启用微信频道"*

On `scaned`, tell the user *"已扫码，请在微信上点击确认..."* and note
the poll script is still running.

### `clear` — remove credentials

Delete `<STATE_DIR>/credentials.json`.

### `baseurl <url>` — set custom API base URL

For testing or alternative iLink endpoints. Read existing credentials.json,
update `baseUrl`, write back.

---

## Implementation notes

- The channels dir might not exist if the server hasn't run yet. Missing file
  = not configured, not an error.
- The server reads credentials.json once at boot. Credential changes need a
  session restart. Say so after saving.
- `access.json` is re-read on every inbound message — policy changes via
  `/wechat:access` take effect immediately, no restart.
- Default API base URL is `https://ilinkai.weixin.qq.com/`.
- The QR code URL is a WeChat mini-program link. It works when scanned with
  WeChat's QR scanner OR when opened in WeChat's built-in browser.

---

## FAQ

**Q: 通过 Task 工具派出的 sub-agent 调用 reply 时报错 "cannot send to WeChat" 或 "session timeout"，但主会话直接发就成功，为什么？**

A: 这是 MCP 协议的物理限制，不是 bug。Sub-agent 运行在独立的隔离上下文中，没有 MCP 传输句柄，无法直接调用 `reply` 工具。即使 sub-agent 拿到了 `context_token`，那也是任务派发时刻的字符串字面量，工作几分钟后已经过期。

**正确做法**：让 sub-agent 把要发送的内容作为返回值交还给主会话，由主会话调用 `reply` 工具。这样可以避免一次失败重试，节省 token 与时间。

新版插件（v2.1.3+）的 `reply` 工具已将 `context_token` 改为可选：主会话不传也能发送，服务端会自动取该用户最新缓存的 token。仅当用户从未发过消息（缓存为空）时才会要求"先让用户发一条 WeChat 消息"。

**Q: 为什么不能直接在 sub-agent 里向 iLink HTTP API 发送消息？**

A: 即使 sub-agent 直接 POST 到 iLink 后端的 `sendmessage` 端点，也需要有效的 `context_token`。该协议采用 last-wins 模型——服务端按用户缓存最新一个 token，旧 token 在用户发新消息后就不再保证可用。Sub-agent 手上的 token 来自任务派发时刻，几分钟后通常已不是最新。统一由主会话发送可以彻底规避这一时序问题。

**Q: 流式回复怎么配置？**

A: 流式回复：ACP 模式下默认开启实时打字机效果。如需关闭，设环境变量 `WECHAT_STREAMING=0`。

