@eryuanspace/claude-code-dmwork
v0.2.0
Published
Connect Claude Code to DMWork messaging via WuKongIM
Readme
@eryuanspace/claude-code-dmwork (WebSocket Gateway)
A WebSocket-based gateway that connects Claude Agent SDK to DMWork messaging via the DMWORK protocol.
How It Works
DMWork Users ←→ DMWORK WebSocket ←→ Gateway ←→ Claude Agent SDKThe gateway maintains a persistent WebSocket connection to DMWORK, receives messages in real-time, routes them to Claude Code for processing, and sends replies back via the DMWork Bot REST API.
vs. claude-code-dmwork (Polling)
The existing claude-code-dmwork adapter in this repo uses a bash polling script. This gateway differs in:
| | Polling Adapter | WebSocket Gateway | |---|---|---| | Protocol | REST polling | DMWORK binary WebSocket | | Latency | Poll interval (seconds) | Real-time (< 100ms) | | Session | Stateless | Persistent with history | | Group chat | Not supported | Full support (context + @mention) | | Runtime | Bash + Claude Code skill | Node.js + Claude Agent SDK | | Encryption | None | DH key exchange + AES-CBC |
Prerequisites
- Node.js >= 18
- A DMWork server with BotFather enabled
- A bot token from BotFather
- Claude Code CLI installed and authenticated
Install
npm install -g @eryuanspace/claude-code-dmwork
# write ~/.claude-code-dmwork.json (see config.example.json), then:
claude-code-dmworkSetup (from source)
# Install dependencies
npm install
# Copy and edit config
cp config.example.json config.json
# Edit config.json with your bot token and API URL
# Run in development mode
npm run dev
# Or build and run
npm run build
npm startConfiguration
| Field | Description |
|---|---|
| botToken | Bot token from BotFather |
| apiUrl | DMWork API base URL |
| cwd | Working directory for Claude Code (loads CLAUDE.md, skills, etc.) |
| sdk.settingSources | Which Claude Code settings to load: "user", "project", "local" |
| access.dm | Non-owner DMs: "chat" (default, no tools) or "full" |
| access.group | Groups: "owner" (default: the owner's own messages get tools, others chat-only), "chat" (owner included) or "full" |
| access.confirmDangerous | Default true: in tool-enabled turns, dangerous calls (Bash except the read-only allowlist, WebFetch, WebSearch, writes outside cwd or into .git//.claude//.mcp.json, MCP tools, unknown tools) wait for the owner to reply 确认 <code> in their DM with the bot. false = explicit opt-out (not recommended) |
| access.confirmTimeoutMs | Default 120000; no answer → denied |
| sdk.allowedTools | Tools the agent can use in the owner's turns (e.g., ["Read", "Glob", "Grep"]) |
| sdk.permissionMode | Owner turns: "bypassPermissions" for headless, "acceptEdits" for semi-auto |
| sdk.maxTurns | Max conversation turns per request (optional) |
| sdk.systemPrompt | Custom system prompt (optional, uses built-in default if omitted) |
Security Note
Only the bot owner gets tools (E-10). The owner is the owner_uid returned
by bot registration. In the owner's DM — and, by default, for the owner's own
@-messages in groups — the agent runs with sdk.allowedTools /
sdk.permissionMode; every other DM and every other group member is
chat-only — no tools at all. If registration returns no owner, everyone is
chat-only. Dangerous owner operations are held until the owner replies
确认 <code> (or 取消 <code>) in their DM with the bot; the code is always
required. The classification is an allowlist: reads, TodoWrite, subagents,
skills, writes inside cwd (except .git/, .claude/, .mcp.json) and the
read-only commands ls cat head tail pwd wc / git status|log|diff (plain
options, all paths and the shell cwd inside cwd, no shell metacharacters)
run unasked; everything else — other Bash, WebFetch, WebSearch, MCP tools,
unknown tools — needs confirmation. Options: access.dm: "full",
access.group: "chat" or "full", access.confirmDangerous: false
(explicit opt-out).
Since the gateway runs headless, bypassPermissions is typically required for the owner's turns. Be aware of the following:
Tool restrictions: Carefully restrict allowedTools to limit what the agent can do. Avoid including Bash unless you fully trust all users who can message the bot. Even Write and Edit allow file modifications within cwd.
Settings loading: The default settingSources: ["user", "project"] loads both user-level (~/.claude) and project-level (cwd/.claude) settings, including CLAUDE.md files, skills, and custom system prompts. This means:
- Any persona or behavior defined in
CLAUDE.mdwill apply to bot responses - Project-level skills will be available to the agent
If the bot is shared with untrusted users, consider:
- Setting
settingSources: []to disable all external settings - Providing an explicit
sdk.systemPromptfor full control over bot behavior - Using a dedicated
cwddirectory instead of a personal project
Features
- DM + Group Chat: Responds to direct messages and @mentions in groups
- Session Persistence: Maintains conversation history per peer (sliding window of 40 messages)
- Group Context: Caches recent group messages and member mappings for context-aware replies
- Auto-Reconnect: Handles WS disconnections and token expiry with automatic recovery
- Typing Indicators: Shows typing status while Claude processes
- Streaming Replies: Incremental response delivery via DMWork stream API, with fallback to regular messages
- Process Lock: Prevents multiple gateway instances for the same bot
Architecture
src/
├── index.ts # Entry point
├── config.ts # Config loader (file + env vars)
├── gateway.ts # Core: message routing + Claude SDK integration
├── session-store.ts # Conversation history persistence
├── group-context.ts # Group chat context cache + member resolution
└── dmwork/
├── socket.ts # DMWORK binary protocol (DH, AES, heartbeat)
├── api.ts # DMWork Bot REST API client
├── types.ts # Type definitions
└── mentions.ts # @mention parsingEnvironment Variables
These override config.json for connection settings:
| Variable | Description |
|---|---|
| DMWORK_BOT_TOKEN | Bot token |
| DMWORK_API_URL | API base URL |
| DMWORK_CWD | Working directory for Claude Code |
License
MIT
