Token导航 LogoToken导航

Agent Skill · 开发

wechat-automation(微信自动化)

wechat-automation 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

wechat-automation 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描有未通过项,按安装量在开发类的 21,746 个 Skill 里排第 4,307。

总安装 8,536周安装 342GitHub Stars 1下载 2,763核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:wechat-automation(微信自动化)
来源仓库:https://github.com/cacr92/wereply
仓库路径:skills/wechat-automation
安装命令:
npx skills add https://github.com/cacr92/wereply --skill wechat-automation
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/cacr92/wereply --skill wechat-automation

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

wechat-automation 提供跨平台微信消息监听与输入框控制的自动化方案,支持 Windows 与 macOS。适用于需要实时监控聊天内容并自动回复的应用场景,如客服或通知系统。

基于 wxauto(Windows)和 Accessibility API(macOS)实现 UI 自动化,通过 JSON 协议通信。使用前请确认系统权限允许辅助功能访问,并安装对应平台的依赖库。涉及隐私数据时务必遵守当地法规,禁止滥用自动化功能发送垃圾信息。

来源仓库内路径:skills/wechat-automation

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/cacr92/wereply --skill wechat-automation;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

wechat-automation 怎么安装?

在终端执行 npx skills add https://github.com/cacr92/wereply --skill wechat-automation。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

wechat-automation 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

wechat-automation 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

wechat-automation 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

wechat-automation 用的人多吗?

公开数据是累计安装 8,536 次,近一周安装 342 次,下载 2,763 次,GitHub 1 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

wechat-automation 安全吗?

第三方扫描有未通过项,风险较高。除非你确认过源码,否则不建议直接安装到常用环境。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
wechat-automation

微信自动化 · 本页

8,5361需要联网未明确未通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

WeChat Automation Skill

Expert guidance for WeChat monitoring and automation using wxauto (Windows) and Accessibility API (macOS).

Overview

WeReply uses Platform-specific Agents to monitor WeChat conversations and control the input box:

  • Windows Agent: Python 3.12 + wxauto v4
  • macOS Agent: Swift + Accessibility API
  • Communication: JSON protocol via stdin/stdout with Rust Orchestrator

Architecture Pattern

微信窗口
   ↓ (UI Automation)
Platform Agent
   ├→ 监听消息(定时轮询)
   ├→ 提取消息内容
   ├→ 发送到 Orchestrator (JSON via stdout)
   └→ 接收命令 (JSON via stdin)
       ↓
   控制输入框(写入建议)

Windows Agent - wxauto v4

Installation and Setup

# 安装依赖
pip install wxauto==4.0.0

# 确保微信已登录且窗口可见

Message Monitoring Pattern

import json
import time
import sys
from wxauto import WeChat

class WeChatMonitor:
    def __init__(self, interval_ms: int = 500):
        """
        初始化微信监听器

        Args:
            interval_ms: 监听间隔(毫秒),默认 500ms
        """
        self.wechat = WeChat()
        self.interval_ms = interval_ms
        self.last_message_id = None

    def start_monitoring(self):
        """开始监听微信消息"""
        try:
            while True:
                # 获取当前聊天窗口的最新消息
                messages = self.wechat.GetAllMessage()

                if messages and len(messages) > 0:
                    latest_message = messages[-1]

                    # 检查是否是新消息(避免重复处理)
                    message_id = self._generate_message_id(latest_message)
                    if message_id != self.last_message_id:
                        self.last_message_id = message_id
                        self._send_message_to_orchestrator(latest_message)

                # 间隔等待
                time.sleep(self.interval_ms / 1000.0)

        except KeyboardInterrupt:
            self._send_error("监听被用户中断")
        except Exception as e:
            self._send_error(f"监听错误: {str(e)}")

    def _generate_message_id(self, message) -> str:
        """生成消息唯一ID(用于去重)"""
        # 结合时间戳、发送者、内容生成ID
        content = message.get('content', '')
        sender = message.get('sender', '')
        timestamp = message.get('time', '')
        return f"{sender}:{timestamp}:{hash(content)}"

    def _send_message_to_orchestrator(self, message):
        """
        发送消息到 Rust Orchestrator

        格式:
        {
            "type": "MessageNew",
            "content": "消息内容",
            "sender": "发送者",
            "timestamp": "2024-01-23T10:30:00"
        }
        """
        payload = {
            "type": "MessageNew",
            "content": message.get('content', ''),
            "sender": message.get('sender', ''),
            "timestamp": message.get('time', '')
        }

        # 输出到 stdout(Rust 会读取)
        print(json.dumps(payload, ensure_ascii=False), flush=True)

    def _send_error(self, error_message: str):
        """发送错误信息到 Orchestrator"""
        payload = {
            "type": "Error",
            "message": error_message
        }
        print(json.dumps(payload, ensure_ascii=False), flush=True)

# 使用示例
if __name__ == '__main__':
    monitor = WeChatMonitor(interval_ms=500)
    monitor.start_monitoring()

Input Box Control Pattern

class WeChatInputWriter:
    def __init__(self):
        self.wechat = WeChat()

    def write_to_input(self, content: str) -> bool:
        """
        写入内容到微信输入框

        Args:
            content: 要写入的文本

        Returns:
            bool: 写入是否成功
        """
        try:
            # 使用 wxauto 写入输入框
            self.wechat.SendMsg(content)
            return True
        except Exception as e:
            self._send_error(f"写入失败: {str(e)}")
            return False

    def clear_input(self) -> bool:
        """清空输入框"""
        try:
            # wxauto v4 提供的清空方法
            self.wechat.ClearMsg()
            return True
        except Exception as e:
            self._send_error(f"清空失败: {str(e)}")
            return False

    def _send_error(self, error_message: str):
        """发送错误到 Orchestrator"""
        payload = {
            "type": "Error",
            "message": error_message
        }
        print(json.dumps(payload, ensure_ascii=False), flush=True)

Command Handling Pattern

import sys
import json
import threading

class AgentCommandHandler:
    def __init__(self):
        self.input_writer = WeChatInputWriter()
        self.running = True

    def start_command_listener(self):
        """监听来自 Orchestrator 的命令(stdin)"""
        thread = threading.Thread(target=self._listen_commands, daemon=True)
        thread.start()

    def _listen_commands(self):
        """从 stdin 读取命令"""
        try:
            for line in sys.stdin:
                if not self.running:
                    break

                try:
                    command = json.loads(line.strip())
                    self._handle_command(command)
                except json.JSONDecodeError:
                    self._send_error(f"无效的 JSON 命令: {line}")

        except Exception as e:
            self._send_error(f"命令监听错误: {str(e)}")

    def _handle_command(self, command: dict):
        """处理命令"""
        cmd_type = command.get('type')

        if cmd_type == 'WriteInput':
            content = command.get('content', '')
            success = self.input_writer.write_to_input(content)
            self._send_response(success)

        elif cmd_type == 'ClearInput':
            success = self.input_writer.clear_input()
            self._send_response(success)

        elif cmd_type == 'HealthCheck':
            self._send_health_status()

        else:
            self._send_error(f"未知命令类型: {cmd_type}")

    def _send_response(self, success: bool):
        """发送命令执行结果"""
        payload = {
            "type": "CommandResponse",
            "success": success
        }
        print(json.dumps(payload, ensure_ascii=False), flush=True)

    def _send_health_status(self):
        """发送健康状态"""
        payload = {
            "type": "HealthStatus",
            "status": "ok",
            "agent_type": "windows_wxauto"
        }
        print(json.dumps(payload, ensure_ascii=False), flush=True)

    def _send_error(self, error_message: str):
        """发送错误"""
        payload = {
            "type": "Error",
            "message": error_message
        }
        print(json.dumps(payload, ensure_ascii=False), flush=True)

macOS Agent - Accessibility API

Swift Implementation Pattern

import Cocoa
import ApplicationServices

class WeChatMonitor {
    private var monitoringTimer: Timer?
    private var lastMessageId: String?
    private let intervalMs: Int

    init(intervalMs: Int = 500) {
        self.intervalMs = intervalMs
    }

    func startMonitoring() {
        // 请求 Accessibility 权限
        if !AXIsProcessTrusted() {
            let options = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String: true]
            AXIsProcessTrustedWithOptions(options as CFDictionary)
            return
        }

        // 启动定时器
        monitoringTimer = Timer.scheduledTimer(
            withTimeInterval: TimeInterval(intervalMs) / 1000.0,
            repeats: true
        ) { [weak self] _ in
            self?.checkForNewMessages()
        }

        RunLoop.main.run()
    }

    private func checkForNewMessages() {
        guard let wechatApp = getWeChatApplication() else {
            return
        }

        // 使用 Accessibility API 获取消息
        if let messages = extractMessages(from: wechatApp) {
            if let latestMessage = messages.last {
                let messageId = generateMessageId(message: latestMessage)

                if messageId != lastMessageId {
                    lastMessageId = messageId
                    sendMessageToOrchestrator(message: latestMessage)
                }
            }
        }
    }

    private func getWeChatApplication() -> AXUIElement? {
        let runningApps = NSWorkspace.shared.runningApplications
        guard let wechatApp = runningApps.first(where: { $0.bundleIdentifier == "com.tencent.xinWeChat" }) else {
            return nil
        }

        return AXUIElementCreateApplication(wechatApp.processIdentifier)
    }

    private func extractMessages(from app: AXUIElement) -> [[String: String]]? {
        // 使用 Accessibility API 提取消息列表
        // 这需要深入分析微信的 UI 层次结构

        var messagesValue: AnyObject?
        let result = AXUIElementCopyAttributeValue(app, kAXChildrenAttribute as CFString, &messagesValue)

        guard result == .success, let windows = messagesValue as? [AXUIElement] else {
            return nil
        }

        // 遍历窗口,找到聊天窗口,提取消息
        // 具体实现需要根据微信的 UI 结构调整

        return nil // Placeholder
    }

    private func generateMessageId(message: [String: String]) -> String {
        let content = message["content"] ?? ""
        let sender = message["sender"] ?? ""
        let timestamp = message["timestamp"] ?? ""
        return "\(sender):\(timestamp):\(content.hashValue)"
    }

    private func sendMessageToOrchestrator(message: [String: String]) {
        let payload: [String: Any] = [
            "type": "MessageNew",
            "content": message["content"] ?? "",
            "sender": message["sender"] ?? "",
            "timestamp": message["timestamp"] ?? ""
        ]

        if let jsonData = try? JSONSerialization.data(withJSONObject: payload),
           let jsonString = String(data: jsonData, encoding: .utf8) {
            print(jsonString, terminator: "\n")
            fflush(stdout)
        }
    }
}

Input Writer (Swift)

class WeChatInputWriter {
    func writeToInput(content: String) -> Bool {
        guard let wechatApp = getWeChatApplication() else {
            sendError(message: "未找到微信应用")
            return false
        }

        // 查找输入框
        guard let inputField = findInputField(in: wechatApp) else {
            sendError(message: "未找到输入框")
            return false
        }

        // 写入内容
        var value = content as CFTypeRef
        let result = AXUIElementSetAttributeValue(inputField, kAXValueAttribute as CFString, value)

        if result == .success {
            return true
        } else {
            sendError(message: "写入失败: \(result.rawValue)")
            return false
        }
    }

    private func findInputField(in app: AXUIElement) -> AXUIElement? {
        // 使用 Accessibility API 查找输入框
        // 需要遍历 UI 层次结构找到输入框元素
        return nil // Placeholder
    }

    private func getWeChatApplication() -> AXUIElement? {
        // 同上
        return nil
    }

    private func sendError(message: String) {
        let payload: [String: Any] = [
            "type": "Error",
            "message": message
        ]

        if let jsonData = try? JSONSerialization.data(withJSONObject: payload),
           let jsonString = String(data: jsonData, encoding: .utf8) {
            print(jsonString, terminator: "\n")
            fflush(stdout)
        }
    }
}

Message Deduplication Strategy

Time-based Deduplication

from datetime import datetime, timedelta

class MessageDeduplicator:
    def __init__(self, window_seconds: int = 5):
        """
        消息去重器

        Args:
            window_seconds: 去重时间窗口(秒)
        """
        self.seen_messages = {}  # {message_id: timestamp}
        self.window_seconds = window_seconds

    def is_duplicate(self, message_id: str) -> bool:
        """检查消息是否重复"""
        now = datetime.now()

        # 清理过期的消息记录
        self._clean_old_messages(now)

        # 检查是否已见过
        if message_id in self.seen_messages:
            return True

        # 记录新消息
        self.seen_messages[message_id] = now
        return False

    def _clean_old_messages(self, now: datetime):
        """清理过期的消息记录"""
        cutoff = now - timedelta(seconds=self.window_seconds)
        self.seen_messages = {
            msg_id: timestamp
            for msg_id, timestamp in self.seen_messages.items()
            if timestamp > cutoff
        }

Performance Optimization

Polling Interval Tuning

class AdaptiveMonitor:
    def __init__(self, min_interval_ms: int = 200, max_interval_ms: int = 1000):
        """
        自适应监听间隔

        当有活跃消息时,使用较短间隔(200ms)
        当长时间无消息时,逐渐增加到最大间隔(1000ms)
        """
        self.min_interval = min_interval_ms / 1000.0
        self.max_interval = max_interval_ms / 1000.0
        self.current_interval = self.min_interval
        self.idle_count = 0

    def get_next_interval(self, has_new_message: bool) -> float:
        """获取下次轮询间隔"""
        if has_new_message:
            # 有新消息,使用最短间隔
            self.current_interval = self.min_interval
            self.idle_count = 0
        else:
            # 无新消息,逐渐增加间隔
            self.idle_count += 1
            if self.idle_count > 5:  # 5次无消息后开始增加间隔
                self.current_interval = min(
                    self.current_interval * 1.2,
                    self.max_interval
                )

        return self.current_interval

Memory Optimization

import gc

class MemoryEfficientMonitor:
    def __init__(self):
        self.message_buffer_size = 100  # 只保留最近100条消息
        self.message_buffer = []

    def add_message(self, message):
        """添加消息到缓冲区"""
        self.message_buffer.append(message)

        # 超过缓冲区大小,清理旧消息
        if len(self.message_buffer) > self.message_buffer_size:
            self.message_buffer = self.message_buffer[-self.message_buffer_size:]
            gc.collect()  # 触发垃圾回收

Error Handling and Recovery

Graceful Degradation

class RobustAgent:
    def __init__(self):
        self.max_retries = 3
        self.retry_delay_seconds = 2

    def monitor_with_retry(self):
        """带重试的监听"""
        retry_count = 0

        while retry_count < self.max_retries:
            try:
                self.start_monitoring()
                break  # 成功,跳出循环
            except Exception as e:
                retry_count += 1
                self._send_error(f"监听失败 (尝试 {retry_count}/{self.max_retries}): {str(e)}")

                if retry_count < self.max_retries:
                    time.sleep(self.retry_delay_seconds)
                else:
                    self._send_error("监听失败次数过多,Agent 退出")
                    sys.exit(1)

Health Check

class HealthMonitor:
    def __init__(self):
        self.last_heartbeat = time.time()
        self.heartbeat_interval = 10  # 每10秒发送一次心跳

    def send_heartbeat(self):
        """发送心跳到 Orchestrator"""
        payload = {
            "type": "Heartbeat",
            "timestamp": time.time(),
            "status": "ok"
        }
        print(json.dumps(payload, ensure_ascii=False), flush=True)
        self.last_heartbeat = time.time()

Security Considerations

Input Validation

def validate_command(command: dict) -> bool:
    """验证来自 Orchestrator 的命令"""
    # 检查命令类型
    if 'type' not in command:
        return False

    cmd_type = command['type']

    # 只接受预定义的命令类型
    valid_types = ['WriteInput', 'ClearInput', 'HealthCheck', 'Stop']
    if cmd_type not in valid_types:
        return False

    # 验证内容长度(防止恶意超长内容)
    if cmd_type == 'WriteInput':
        content = command.get('content', '')
        if len(content) > 10000:  # 最大10KB
            return False

    return True

Privacy Protection

def sanitize_message_for_logging(message: dict) -> dict:
    """清理消息中的敏感信息(用于日志)"""
    sanitized = message.copy()

    # 不记录完整的消息内容
    if 'content' in sanitized:
        content = sanitized['content']
        if len(content) > 50:
            sanitized['content'] = content[:50] + '...'

    return sanitized

Testing Guidelines

Unit Testing

import unittest
from unittest.mock import Mock, patch

class TestWeChatMonitor(unittest.TestCase):
    def test_message_deduplication(self):
        """测试消息去重"""
        deduplicator = MessageDeduplicator(window_seconds=5)

        message_id = "test_message_1"

        # 第一次应该不是重复
        self.assertFalse(deduplicator.is_duplicate(message_id))

        # 第二次应该是重复
        self.assertTrue(deduplicator.is_duplicate(message_id))

    @patch('wxauto.WeChat')
    def test_monitor_initialization(self, mock_wechat):
        """测试监听器初始化"""
        monitor = WeChatMonitor(interval_ms=500)
        self.assertEqual(monitor.interval_ms, 500)
        self.assertIsNone(monitor.last_message_id)

When to Use This Skill

Activate this skill when:

  • Implementing WeChat message monitoring
  • Developing Platform Agents (Windows/macOS)
  • Working with wxauto or Accessibility API
  • Handling message extraction and deduplication
  • Implementing input box control
  • Optimizing Agent performance
  • Handling Agent errors and recovery
  • Setting up IPC communication with Orchestrator

平台分布

Codex

33.07%
按下载量换算914

Claude

31.46%
按下载量换算869

Cursor

18.87%
按下载量换算521

Gemini CLI

8.78%
按下载量换算243

安全审计

Gen Agent Trust Hub

未通过

Socket

未通过

Snyk

可疑

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills