gangvy 6d9ba6da4e update 4 달 전
..
scripts 4e7d8200f5 update 插件 4 달 전
src 6d9ba6da4e update 4 달 전
.gitignore 4e7d8200f5 update 插件 4 달 전
README.md 4e7d8200f5 update 插件 4 달 전
package-lock.json 4e7d8200f5 update 插件 4 달 전
package.json 6d9ba6da4e update 4 달 전
tsconfig.json 4e7d8200f5 update 插件 4 달 전

README.md

@fmode/wechat-cli (wecli)

Local CLI wrapping the third-party wechat-agent HTTP backend for use by the wechat OpenClaw skill (out-of-band WeChat operations: search contacts, look up conversation history, message a third party, etc.).

This CLI is the non-channel half of the WeChat integration. The real-time inbound/outbound auto-reply path belongs to the channel-plugin/ sibling (@fmode/openclaw-wechat-agent, currently at 0.1.1). See design notes.

| | Channel plugin (../channel-plugin) | CLI + skill (this) | |-|-|-| | Lives in | OpenClaw gateway, always on | Spawned per agent tool call | | Handles | "Someone DM'd the bot, auto-reply" | "User asks agent to actively do something" | | Uses | 3 endpoints (check-online, /messages, /send-text) | ~8 endpoints today; growing | | Deployed as | .tgz via openclaw plugins install | local binary + SKILL.md |

Status

  • v0.1.0 — local-only (not published to npm). Covers check-online, contacts list|search|detail, messages send|history, conversations list. Zero runtime dependencies (Node 20+ fetch + util.parseArgs only).

Quick start

# One-time
cd cli
npm install
npm run build

# Option A — run directly
node dist/wecli.js --help
node dist/wecli.js check-online --api-base http://8.138.37.248/api/wechat-agent

# Option B — make `wecli` a global command on this machine
npm link
wecli --help
wecli check-online

npm link is reversible with npm unlink -g @fmode/wechat-cli. On Windows it writes a .cmd shim into %APPDATA%\npm; on Unix it symlinks into the active Node's bin dir.

Config resolution

Every command resolves the backend apiBase using this priority chain; the first hit wins:

  1. --api-base <url> CLI flag
  2. WECHAT_API_BASE environment variable
  3. ~/.wecli/config.json{ "apiBase": "..." }
  4. ~/.openclaw/wechat-credentials.json{ "wechatApiBase": "..." } (legacy; pre-dates this CLI; shared with the v1.x skill pack so existing OpenClaw installs keep working without extra setup)

If none of the above yield an apiBase, the command errors out with a multi-line message pointing at all four locations.

To make things explicit for this machine, the simplest setup is:

mkdir -p ~/.wecli
printf '{"apiBase":"http://8.138.37.248/api/wechat-agent"}\n' > ~/.wecli/config.json
wecli check-online     # should print `online    yes`

Subcommand reference

wecli check-online

apiBase   http://8.138.37.248/api/wechat-agent
source    flag
online    yes
selfWxid  -
  • Exit code 0 when online, 3 when reachable but offline, 1 on error.
  • --json{"ok":true,"online":bool,"selfWxid":string|null,"apiBase":...,"apiBaseSource":...}.

wecli contacts list [--cache]

Pulls all contacts (POST /contacts/list or /contacts/list-cache when --cache is given). Output is a simple table (wxid | nickName | remark | alias). Use --json for agent consumption.

wecli contacts search <query>

Keyword search via POST /contacts/search. The query string is sent as both keyword and query fields because the upstream GEWE variant differs between backend builds.

wecli contacts detail <wxid>

Single-contact detail via POST /contacts/detail. Prints nickName, remark, alias, signature, type. --json returns the raw backend record so the agent can grab any extra fields the terminal view drops.

wecli messages history [--wxid W] [--since ISO] [--direction D] [--limit N]

Server-side filtered & deduped via GET /messages.

| flag | maps to | default | |-|-|-| | --limit N | limit=N (capped at 200 server-side) | 50 | | --direction received\|sent\|all | direction=... | received | | --wxid wxid_xxx | wxid=... | (all contacts) | | --since 2026-04-21T16:00:00Z | since=... | (no lower bound) |

--since is the recommended way to poll: backend returns only messages newer than that timestamp and already deduplicates by NewMsgId/MsgId. The human-format footer also reports server total=N, server dropped K dup so you can see how much filtering happened upstream.

wecli messages send --to <wxid> --text "<content>" [--at wxid1,wxid2]

Active send via POST /message/send-text. Use this only for messaging a third party — replies in an ongoing DM with the bot are handled by the channel plugin automatically; you do NOT need to call messages send from the agent to reply to incoming inbound. If you do, the channel plugin will still also reply and the contact will see duplicates.

--at fills the backend's ats field (comma-separated wxids) for group @mention replies.

wecli conversations list

GET /conversations. Returns the backend's per-contact "last message" summary grouped by wxid. Useful as a pre-check for "who have I been talking to lately".

Why a CLI and not more skills

OpenClaw's canonical pattern (see imsg, wacli SKILL.md under node_modules/openclaw/skills/) is:

  • One binary (imsg / wacli / wecli) does the HTTP / RPC.
  • One SKILL.md tells the LLM when to use which subcommand.

The alternative — one SKILL.md per endpoint with inline curl examples, as this repo's v1.x wechat/wechat-* folders still do — creates a maintenance tax: every command re-derives apiBase from a JSON file inline (node -e "console.log(JSON.parse(fs.readFileSync...))"), LLMs have to hand-escape JSON / query strings, and adding a feature means creating a new skill directory. wecli replaces that boilerplate with one stable arg-parsing surface the agent can learn once.

Development

npm run typecheck    # tsc --noEmit, strict TS
npm run build        # esbuild single-file bundle -> dist/wecli.js (~80 KiB)

Adding a new subcommand

  1. Pick the matching backend endpoint from e:\workspace\wechat-agent\wechat-agent-api\src\routes\wechat-agent.ts.
  2. Add a typed method to WechatAgentClient in src/client.ts.
  3. Create src/commands/<name>.ts following the shape of check-online.ts (resolveConfig → client → render human / --json).
  4. Register the command in the switch in src/index.ts and add a line to the USAGE string.
  5. npm run build && node dist/wecli.js <name> --api-base <url> to smoke test.

Out of scope (on purpose)

The wechat-agent backend exposes 116 endpoints. wecli intentionally does not wrap:

  • Moments / /sns/* (19 endpoints) — social ops, separate product surface.
  • Video-channel / /finder/:name — niche.
  • /contacts/corp-* (企微) — enterprise WeChat, distinct channel.
  • /contacts/phone-* — privacy / compliance.
  • Destructive group ops (/group/create, /disband, /admin-operate, /remove-member) — need human-in-the-loop.
  • Profile management (/profile/update, /profile/head-image/upload, /profile/safety-info) — belongs to the web UI, not agent tooling.

If you genuinely need one of these from the agent, package a separate skill + binary (e.g. wecli-moments) rather than bloating the core tool.