aradotso/trending-skills/openilink-hub-wechat-bot

Claude Code and agent skill by aradotso/trending-skills

Trust tier 1
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Install

npx vskill@latest install aradotso/trending-skills/openilink-hub-wechat-bot

SKILL.md

markdown
---
name: openilink-hub-wechat-bot
description: Self-hosted WeChat Bot management platform using iLink protocol with WebSocket/Webhook/AI relay, App Marketplace, and 7-language SDKs
triggers:
-set up openilink hub for wechat bot management
-integrate wechat messages with webhook or websocket
-build an openilink app for wechat automation
-configure ai auto-reply for wechat bot
-deploy openilink hub with docker
-use openilink sdk to send wechat messages
-create custom app for openilink marketplace
-forward wechat messages to slack or feishu
---
# OpeniLink Hub — WeChat Bot Management Platform
> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.
OpeniLink Hub is an open-source self-hosted platform for managing WeChat bots via the official **iLink (智联) protocol** introduced with WeChat ClawBot in March 2026. It handles context_token lifecycle, CDN encryption, 24-hour session renewal, multi-bot management, and message dispatch — so you focus on your business logic.
## Installation
### One-line install (Linux/macOS)

curl -fsSL https://raw.githubusercontent.com/openilink/openilink-hub/main/install.sh | sh oih

### Docker (quickstart)

docker run -d -p 9800:9800 ghcr.io/openilink/openilink-hub:latest

### Docker Compose (production with PostgreSQL)

docker-compose.yml

services: postgres: image: postgres:17-alpine environment: POSTGRES_USER: openilink POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: openilink volumes:

  • pgdata:/var/lib/postgresql/data

hub: image: ghcr.io/openilink/openilink-hub:latest ports:

  • "9800:9800"

environment: DATABASE_URL: postgres://openilink:${POSTGRES_PASSWORD}@postgres:5432/openilink?sslmode=disable RP_ORIGIN: https://hub.example.com RP_ID: hub.example.com SECRET: ${HUB_SECRET} depends_on:

  • postgres

volumes: pgdata:

docker compose up -d

### Build from source

git clone https://github.com/openilink/openilink-hub.git cd openilink-hub cd web && pnpm install && pnpm run build && cd .. go build -o oih . ./oih

## CLI Commands
| Command | Description |
|---------|-------------|
| `oih` | Run in foreground |
| `oih install` | Register as systemd (Linux) or launchd (macOS) service |
| `oih uninstall` | Remove system service |
| `oih version` | Show version |
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `DATABASE_URL` | SQLite (auto) | `postgres://user:pass@host/db?sslmode=disable` |
| `SECRET` | — | Random string for signing tokens |
| `RP_ORIGIN` | `http://localhost:9800` | WebAuthn relying party origin (full URL) |
| `RP_ID` | `localhost` | WebAuthn relying party ID (domain only) |
| `PORT` | `9800` | HTTP server port |
**SQLite data locations:**
- Linux: `~/.local/share/openilink-hub/openilink.db`
- macOS: `~/Library/Application Support/openilink-hub/openilink.db`
- root/service: `/var/lib/openilink-hub/openilink.db`
## SDK Usage
### Go SDK

go get github.com/openilink/openilink-sdk-go

package main

import ( "context" "fmt" "log"

openilink "github.com/openilink/openilink-sdk-go" )

func main() { client := openilink.NewClient(openilink.Config{ HubURL: "http://localhost:9800", Token: os.Getenv("OPENILINK_TOKEN"), })

// Listen for incoming messages via WebSocket err := client.OnMessage(context.Background(), func(msg *openilink.Message) error { fmt.Printf("[%s] %s: %s\n", msg.BotID, msg.Sender, msg.Content)

// Reply to the message return client.SendText(context.Background(), &openilink.SendTextRequest{ BotID: msg.BotID, ToUserID: msg.Sender, Content: "收到你的消息: " + msg.Content, }) }) if err != nil { log.Fatal(err) } }

### Node.js SDK

npm install @openilink/openilink-sdk-node

import { OpeniLinkClient } from '@openilink/openilink-sdk-node';

const client = new OpeniLinkClient({ hubUrl: 'http://localhost:9800', token: process.env.OPENILINK_TOKEN, });

// Subscribe to messages client.onMessage(async (msg) => { console.log([${msg.botId}] ${msg.sender}: ${msg.content});

// Send a reply await client.sendText({ botId: msg.botId, toUserId: msg.sender, content: Echo: ${msg.content}, }); });

await client.connect();

### Python SDK

pip install openilink-sdk-python

import os import asyncio from openilink import OpeniLinkClient

async def main(): client = OpeniLinkClient( hub_url="http://localhost:9800", token=os.environ["OPENILINK_TOKEN"], )

@client.on_message async def handle(msg): print(f"[{msg.bot_id}] {msg.sender}: {msg.content}") await client.send_text( bot_id=msg.bot_id, to_user_id=msg.sender, content=f"你好,我收到了: {msg.content}", )

await client.connect()

asyncio.run(main())

## Webhook Configuration
Configure a Webhook endpoint in the Hub dashboard under **Settings → Webhooks**. Hub will POST events to your URL:

{ "event": "message.received", "bot_id": "bot_abc123", "message": { "id": "msg_xyz", "sender": "user_openid", "content": "Hello", "type": "text", "timestamp": 1711900800 } }

### Express.js webhook handler

import express from 'express'; import crypto from 'crypto';

const app = express(); app.use(express.json());

app.post('/webhook', (req, res) => { // Verify Hub signature const sig = req.headers['x-openilink-signature']; const expected = crypto .createHmac('sha256', process.env.WEBHOOK_SECRET) .update(JSON.stringify(req.body)) .digest('hex');

if (sig !== sha256=${expected}) { return res.status(401).json({ error: 'Invalid signature' }); }

const { event, bot_id, message } = req.body;

if (event === 'message.received') { console.log(Bot ${bot_id} received: ${message.content}); // process message... }

res.json({ ok: true }); });

app.listen(8080);

### Go webhook handler

package main

import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "net/http" "os" )

type WebhookEvent struct { Event string json:"event" BotID string json:"bot_id" Message Message json:"message" }

type Message struct { ID string json:"id" Sender string json:"sender" Content string json:"content" Type string json:"type" Timestamp int64 json:"timestamp" }

func webhookHandler(w http.ResponseWriter, r *http.Request) { var body []byte body, _ = io.ReadAll(r.Body)

// Verify signature sig := r.Header.Get("X-OpeniLink-Signature") mac := hmac.New(sha256.New, []byte(os.Getenv("WEBHOOK_SECRET"))) mac.Write(body) expected := "sha256=" + hex.EncodeToString(mac.Sum(nil)) if sig != expected { http.Error(w, "Unauthorized", http.StatusUnauthorized) return }

var event WebhookEvent if err := json.Unmarshal(body, &event); err != nil { http.Error(w, "Bad Request", http.StatusBadRequest) return }

if event.Event == "message.received" { fmt.Printf("Bot %s received from %s: %s\n", event.BotID, event.Message.Sender, event.Message.Content) }

w.Header().Set("Content-Type", "application/json") w.Write([]byte({"ok":true})) }

func main() { http.HandleFunc("/webhook", webhookHandler) http.ListenAndServe(":8080", nil) }

## Building a Custom App
Apps integrate with Hub via WebSocket or Webhook and are authorized via PKCE OAuth.
### Minimal Go App (based on openilink-app-echo)

git clone https://github.com/openilink/openilink-app-echo.git my-app cd my-app

// main.go package main

import ( "context" "log" "os"

app "github.com/openilink/openilink-app-sdk-go" )

func main() { a := app.New(app.Config{ AppID: os.Getenv("APP_ID"), AppSecret: os.Getenv("APP_SECRET"), HubURL: os.Getenv("HUB_URL"), })

// Declare a command: users type /ping in WeChat a.RegisterCommand("ping", "Reply with pong", func(ctx context.Context, req *app.CommandRequest) error { return req.Reply("pong 🏓") })

// Handle all messages a.OnMessage(func(ctx context.Context, msg *app.Message) error { log.Printf("Received: %s", msg.Content) return nil })

if err := a.Start(context.Background()); err != nil { log.Fatal(err) } }

**App manifest** (`app.json`) required for marketplace listing:

{ "id": "my-awesome-app", "name": "My Awesome App", "version": "1.0.0", "description": "Does something great with WeChat messages", "webhook_url": "https://my-app.example.com/webhook", "commands": [ { "name": "ping", "description": "Replies with pong" } ], "scopes": ["messages:read", "messages:write"] }

### Local Development with Mock Server

Terminal 1: Start Mock Server (no real WeChat needed)

go run ./cmd/appmock --webhook-url http://localhost:8080/webhook

Terminal 2: Run your App

APP_ID=test APP_SECRET=test HUB_URL=http://localhost:9801 go run .

Terminal 3: Inject a test message

curl -X POST http://localhost:9801/mock/event \ -H "Content-Type: application/json" \ -d '{"sender":"alice","content":"/ping"}'

Check what your App sent back

curl http://localhost:9801/mock/messages

## AI Auto-Reply Configuration
In the Hub dashboard → **Settings → AI**:

Set via env or dashboard

OPENAI_API_KEY=... # Set in environment OPENAI_BASE_URL=... # For compatible APIs (Ollama, DeepSeek, etc.) OPENAI_MODEL=gpt-4o-mini AI_SYSTEM_PROMPT="You are a helpful WeChat assistant."

Compatible with any OpenAI-spec API (Ollama, DeepSeek, Qwen, etc.).
## REST API Patterns
Hub exposes a REST API at `http://localhost:9800/api/v1`.

List connected bots

curl -H "Authorization: Bearer $OPENILINK_TOKEN" \ http://localhost:9800/api/v1/bots

Send a text message

curl -X POST \ -H "Authorization: Bearer $OPENILINK_TOKEN" \ -H "Content-Type: application/json" \ -d '{"bot_id":"bot_abc","to_user_id":"user_openid","content":"Hello!"}' \ http://localhost:9800/api/v1/messages/send

Send an image

curl -X POST \ -H "Authorization: Bearer $OPENILINK_TOKEN" \ -F "bot_id=bot_abc" \ -F "to_user_id=user_openid" \ -F "image=@/path/to/image.png" \ http://localhost:9800/api/v1/messages/send-image

Get message trace (debugging)

curl -H "Authorization: Bearer $OPENILINK_TOKEN" \ http://localhost:9800/api/v1/messages/trace/msg_xyz

## Common Patterns
### Pattern: Forward WeChat messages to Slack
Install the **Bridge** app from the marketplace, configure:

BRIDGE_TARGET=slack SLACK_WEBHOOK_URL=https://hooks.slack.com/services/... BRIDGE_BOT_ID=bot_abc123 # which bot to bridge

### Pattern: Multi-bot message routing

client.OnMessage(context.Background(), func(msg *openilink.Message) error { switch msg.BotID { case "bot_customer_service": return handleCustomerService(msg) case "bot_sales": return handleSales(msg) default: return handleDefault(msg) } })

### Pattern: Command parsing in webhook

@client.on_message async def handle(msg): if msg.content.startswith("/"): parts = msg.content.split(maxsplit=1) cmd = parts[0][1:] # strip leading / args = parts[1] if len(parts) > 1 else ""

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 73 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
72
Repository forks
13
7-day trend score
21

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 16 Aug 2026, 2 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/aradotso/trending-skills/openilink-hub-wechat-bot/badge)](https://verified-skill.com/skills/aradotso/trending-skills/openilink-hub-wechat-bot)

Something wrong with this skill or its page? Tell us.