English | 简体中文

wxpilot logo

wxpilot

A CLI for automating WeChat Mini Programs, built for AI Agents.
Lets an Agent drive the WeChat DevTools like a browser — page navigation, element interaction, state reading, network capture & mocking.

License Platform Rust Version PRs Welcome

--- ## Table of Contents - [Features](#features) - [How It Works](#how-it-works) - [Prerequisites](#prerequisites) - [Installation](#installation) - [Quick Start](#quick-start) - [Core Concepts](#core-concepts) - [Command Reference](#command-reference) - [Network Proxy & Mocking](#network-proxy--mocking) - [Low-Token Output Design](#low-token-output-design) - [Architecture](#architecture) - [Development](#development) - [AI Agent Integration](#ai-agent-integration) - [MCP Integration](#mcp-integration) - [dsh Integration](#dsh-integration) - [Contributing](#contributing) - [License](#license) ## Features - **Built for Agents**: All command output is compact by default and uniformly truncated to 4000 characters, minimizing context consumption. - **Ref mechanism**: After `view`, interactive elements are auto-numbered `%N`; the Agent taps/types by number, with no need to maintain selectors. - **Low-token lookup**: `find ` locates elements by text/class/placeholder/tag and returns `%N` directly — no need to read the whole page. - **Auto project detection**: Omit the path and it auto-scans for `dist/project.config.json` under the current directory; prompts interactively when multiple candidates exist. - **Built-in proxy capture**: `--proxy` spins up an HTTP/HTTPS MITM proxy in one command, supporting request mocking and body inspection. - **JSON mode**: `--json` emits structured results for easy parsing by programs/Agents. - **Managed daemon**: The CLI auto-spawns a background daemon on first call, communicating over a Unix socket, and auto-exits after 30 min idle. - **Recommended Agent integration**: Use the Skill + CLI workflow as the primary integration path; an optional MCP stdio adapter is available for MCP-based hosts. ## How It Works ``` ┌─────────┐ JSON-RPC ┌──────────┐ WebSocket ┌─────────────────────┐ │ wxpilot │ ────────────► │ daemon │ ────────────► │ WeChat DevTools │ │ (CLI) │ ◄──────────── │ (bg) │ ◄──────────── │ (automator + page) │ └─────────┘ Unix Socket └────┬─────┘ └─────────────────────┘ │ ├── proxy HTTP/HTTPS MITM capture + mock ├── snapshot WXML → element tree + interaction detection └── ref-store %N temporary refs + expiry validation ``` The CLI and daemon are decoupled: the CLI only parses arguments and formats output, while the daemon handles the actual automation, proxy, and state. They communicate over `~/.wxpilot/rust-daemon.sock`. ## Prerequisites - **macOS** (currently only macOS binaries are provided; Linux/Windows are not yet supported) - **WeChat DevTools** installed and running - Building from source requires the **Rust stable** toolchain (`rustup show`) ## Installation ### One-line install (macOS) ```bash curl -fsSL https://raw.githubusercontent.com/wuliLiuyue/wxpilot/main/install.sh | bash ``` Install a specific version: ```bash curl -fsSL https://raw.githubusercontent.com/wuliLiuyue/wxpilot/main/install.sh | bash -s -- --version v0.1.0 ``` Custom install directories: ```bash curl -fsSL https://raw.githubusercontent.com/wuliLiuyue/wxpilot/main/install.sh | bash -s -- \ --install-dir ~/.local/bin --daemon-dir ~/.wxpilot/bin ``` After install: - `wxpilot` → `~/.local/bin/wxpilot` - `wxp-daemon` → `~/.wxpilot/bin/wxp-daemon` If `~/.local/bin` is not in PATH, append it as prompted: ```bash echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc ``` ### Build from source ```bash cd rust cargo build -p wxp-cli --bin wxpilot cargo build -p wxp-daemon --bin wxp-daemon ./target/debug/wxpilot --version ``` > `packages/web` is the website source, unrelated to the CLI — you can ignore it when building from source. ## Quick Start ```bash # 1. Start automation (auto-detect dist/project.config.json, or pass a path explicitly) wxpilot start wxpilot start /path/to/miniprogram wxpilot start /path/to/miniprogram --proxy # capture: auto-spawns a proxy on 8899 wxpilot start /path/to/miniprogram --appid wxYourAppID # 2. Connect wxpilot connect # 3. View the page to get interactive element refs %N wxpilot view wxpilot find submit # low-token lookup, returns matching %N directly # 4. Interact wxpilot tap %1 wxpilot type %2 "13800138000" wxpilot goto /pages/order/index # 5. Refs become invalid after navigation — re-fetch wxpilot view # 6. Read state / assert / screenshot wxpilot state cart.total # read only the sub-field you need wxpilot assert %3 "Submitted successfully" wxpilot shot /tmp/result.png ``` ## Core Concepts ### Ref mechanism After running `wxpilot view` or `wxpilot find`, interactive elements on the page are assigned temporary numbers `%N` (starting from %1). - Numbers are regenerated on each `view` / `find`. - After `goto` / `back` / `reload`, numbers are **invalidated** — re-run `view`. - Using an expired ref errors with: `ref_expired: %N`. **Interactive node detection** (dual signal): the `outerWxml()` snapshot from DevTools does not preserve event attributes like `bindtap`, so two signals are used: 1. `data-*` attributes — preserved in the snapshot, used as a proxy signal for bindtap (~80% coverage). 2. Source-file fingerprints — read the `.wxml` sources, extract `tag:sorted-classes` fingerprints of nodes that have bindtap, and recover nodes missed by the `data-*` heuristic. ### Project path auto-detection The `projectPath` argument of `wxpilot start` is optional: - When omitted, scans up to 2 levels of subdirectories under CWD for `dist` directories containing `project.config.json`. - Single candidate: used automatically. - Multiple candidates: interactive selection. - No candidate: error, prompting you to pass it manually. ## Command Reference ### Connection management ```bash wxpilot start # auto-detect dist/project.config.json wxpilot start # start automation (cli auto, wait for ready) wxpilot start --appid # specify when appid is a placeholder wxpilot start --cli-path # path to the DevTools CLI wxpilot start --auto-port 9421 # automation port (default 9420) wxpilot start --proxy # auto-start a 127.0.0.1:8899 proxy wxpilot start --proxy --https # HTTPS MITM capture (install CA first) wxpilot connect # connect (using the endpoint recorded by start) wxpilot connect --ws # specify a ws endpoint directly wxpilot disconnect wxpilot status ``` ### Navigation ```bash wxpilot goto # e.g. /pages/order/index wxpilot back wxpilot reload ``` ### View ```bash wxpilot view # compact interactive summary (compact, depth=5, limit=50) wxpilot view --full # full tree (incl. non-interactive nodes, depth=20) wxpilot view --depth wxpilot view --limit wxpilot find # match text/class/placeholder/tag, interactive nodes only by default wxpilot find --all # include non-interactive nodes wxpilot find --limit wxpilot wait %N [--timeout 5000] ``` ### Interaction ```bash wxpilot tap %N wxpilot type %N wxpilot scroll %N ``` ### Read ```bash wxpilot read %N # read element text wxpilot assert %N # assert text (exit code 1 on mismatch) wxpilot state # top-level key summary (type + size) wxpilot state [path] # a specific sub-path, e.g. cart.items wxpilot state --full # full page data wxpilot shot [path] # screenshot, save file and return the path wxpilot shot [path] --base64 # screenshot with a base64 payload ``` ### Network proxy ```bash wxpilot net start [--port 8899] [--https] # start the proxy standalone (--https decrypts HTTPS) wxpilot net stop wxpilot net log [--filter ] [--limit 20] # summary, without bodies wxpilot net log [--filter ] --with-body # incl. request/response bodies (truncated to 2000 chars) wxpilot net mock wxpilot net unmock wxpilot net clear wxpilot net install-ca # install the CA into the keychain (first HTTPS use) ``` ### Execution ```bash wxpilot run # run JS in the page VM (no Node.js API access) wxpilot wx [args...] # invoke a wx API ``` ### Daemon ```bash wxpilot daemon stop wxpilot daemon restart ``` ### Global options ``` --timeout default 10000ms --verbose verbose logging --json JSON-formatted output ``` ## Network Proxy & Mocking For capture, prefer `wxpilot start --proxy [--https]`, which ensures the proxy is up within the same session. ### HTTP mode ```bash wxpilot start --proxy wxpilot connect wxpilot net clear wxpilot goto /pages/xxx/index sleep 3 wxpilot net log --filter api.example.com ``` ### HTTPS MITM mode (install the certificate the first time) ```bash # One-time setup wxpilot net start --https # generate the CA certificate wxpilot net install-ca # install it into the system keychain # Fully quit and restart WeChat DevTools (a restart is required) # DevTools: Settings → Proxy → Manual → 127.0.0.1:8899 # Each capture session wxpilot start --proxy --https wxpilot connect wxpilot net log --filter api.example.com --with-body ``` ### Mock ```bash wxpilot net mock https://api.example.com/order ./mock-order.json ``` `mock-order.json` format: ```json { "status": 200, "body": { "code": 0, "data": { "items": [] } } } ``` ### Notes - Once you set a proxy in DevTools, **the tool's own internal requests also go through the proxy**; when the proxy isn't running, the page may report `TypeError: Failed to fetch`. - After `net install-ca`, you must **fully restart** DevTools for it to take effect. - In HTTP mode, HTTPS requests are transparently tunneled (not recorded); to record HTTPS traffic you must use `--https`. - Port fallback: default is `9420`. If `connect` succeeds but `status` is abnormal, run `wxpilot daemon stop`, then restart with `--auto-port 9421`, trying 9422/9423 next. ## Low-Token Output Design The default output of each command is optimized for AI context consumption: | Command | Default behavior | Full output | |---------|------------------|-------------| | `view` | Compact interactive summary (compact, depth=5, limit=50) | `--full` | | `find` | Minimal summary of matched elements (interactive only, limit=10) | `--all` | | `state` | Top-level key summary (type + size) | `--full` or a specific `path` | | `shot` | Save a file, return the path | `--base64` | | `net log` | Summary fields, limit=20, no body | `--with-body` | All command output is uniformly truncated to 4000 characters; when truncated, a `[truncated, originalLength=X]` hint is appended. ## Architecture | Module | Responsibility | |--------|----------------| | `wxp-cli` | Argument parsing, daemon detection/spawn, RPC calls, output formatting | | `wxp-daemon` | JSON-RPC server, runtime state, automator, proxy and storage | | `wxp-rpc` + `wxp-common` | RPC protocol and shared constants | | `wxp-snapshot` + `wxp-ref-store` | WXML → element tree, interaction detection, %N ref storage | | `wxp-proxy` + `wxp-store` | HTTP/HTTPS proxy, network log storage | Default runtime files: - `~/.wxpilot/rust-daemon.sock` — daemon communication socket - `~/.wxpilot/rust-daemon.pid` — daemon PID lock (ensures a single instance) ## Development ```bash # Build cd rust && cargo build --workspace # Test make rust-test # equivalent to cd rust && cargo test --workspace # Local build & install loop (macOS arm64 / x86_64) make local-build # artifacts in dist/local// make local-install # install to ~/.local/bin and ~/.wxpilot/bin make local-install-all # build + install in one go # Release packaging (generates GitHub Releases archives) make public-release-package VERSION=v0.1.0 # → dist/public-release/v0.1.0/wxpilot-darwin-{arm64,x64}.tar.gz + checksums ``` Upload the three files under `dist/public-release//` (two tar.gz archives + `wxpilot-checksums.txt`) to GitHub Releases, and users can install via the one-line script. ## AI Agent Integration The repo ships [`skills/wxpilot/SKILL.md`](skills/wxpilot/SKILL.md), a complete usage guide for AI Agents, covering: - Agent decision logic for project path detection - A typical Agent workflow (start → find → interact → assert → screenshot) - JSON-mode output format - Port-fallback troubleshooting - Low-token usage guidelines Reference this file directly as a skill description when integrating with an Agent. For new Agent integrations, prefer Skill + CLI: the Skill provides the workflow guidance and the CLI remains the stable execution interface. This path has the smallest integration surface and keeps the full CLI behavior available. ## MCP Integration MCP is supported as an optional integration layer for hosts that already manage tools through MCP. Build the adapter from the repository root: ```bash pnpm install pnpm --filter @wxpilot/mcp build ``` Example MCP client configuration: ```json { "mcpServers": { "wxpilot": { "command": "node", "args": [ "/absolute/path/to/wxpilot/packages/mcp/dist/index.js" ], "env": { "WXPILOT_BIN": "/absolute/path/to/wxpilot/rust/target/debug/wxpilot", "WXPILOT_CWD": "/absolute/path/to/miniprogram" } } } } ``` The adapter exposes one tool, `wxpilot_execute`, and supports the existing connection, navigation, interaction, state, screenshot, JavaScript, wx API, and network operations. `start` requires an explicit `projectPath`; daemon stop and restart are intentionally not exposed. See [`packages/mcp/README.md`](packages/mcp/README.md) and [`packages/mcp/README.zh-CN.md`](packages/mcp/README.zh-CN.md) for the complete configuration and development guide. ## dsh Integration A native [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`) bundle plugin exposes wxpilot as one model-facing `wxpilot` tool: it drives the Rust CLI directly through the `ctx.subprocess` seam, with typed schemas, a canonical JSON result, and a terminal card. ```sh pnpm dsh:build dsh plugin --profile demo add ./packages/dsh ``` The plugin shares its argv whitelist with the MCP adapter through `@wxpilot/shared`; JS-evaluating operations (`run`, `wx`) stay hidden unless `enableJsEval: true` is configured. See [`packages/dsh/README.md`](packages/dsh/README.md) and [`packages/dsh/README.zh-CN.md`](packages/dsh/README.zh-CN.md) for loading, configuration, and development. ## Contributing Issues and Pull Requests are welcome. - The main implementation language is **Rust**; by default, modify `rust/crates/wxp-cli` and `rust/crates/wxp-daemon`. - Make sure `make rust-test` passes before submitting. - There is no CI configured — please run tests locally before committing. ## License This project is open-sourced under the [GNU Affero General Public License v3.0 or later](LICENSE) (AGPL-3.0-or-later) © wuliLiuyue. - ✅ Personal study, research, internal use, modification, and redistribution are all allowed (you must keep the copyright notice and likewise open-source under AGPL-3.0-or-later). - ✅ Commercial use is also allowed, but **derivative works and services provided over a network must be open-sourced under AGPL-3.0-or-later** (i.e. "copyleft"). - ❌ You may not distribute this project or its derivatives in closed-source/proprietary form, or provide them as closed-source services. - 💼 To embed this project into a closed-source/proprietary commercial product or service, please contact the author for a commercial license. Third-party dependencies (such as tokio, clap, etc.) remain under their respective MIT/Apache-2.0 licenses.