Skip to content

Commit bbf3c97

Browse files
author
Slldyd2077
committed
feat: add Windows platform support (lightweight, seamless)
- Add MINGW/MSYS/CYGWIN branch to daemon.sh with PID file + nohup backend - Fix send.ts: process.env.HOME -> homedir() for Windows compatibility - Fix visualize-logs.ts: cross-platform file opening (cmd /c start / open / xdg-open) - Update prerequisites in README.md, README_en.md, SKILL.md
1 parent 8aead25 commit bbf3c97

6 files changed

Lines changed: 134 additions & 6 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ npm run daemon -- logs # 查看日志
110110
## 前置条件
111111

112112
- Node.js >= 18
113-
- macOS 或 Linux
113+
- macOS、Windows 或 Linux
114114
- 个人微信账号
115115
- 已安装 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) CLI 并完成认证
116116

README_en.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ The daemon long-polls WeChat for new messages, forwards them to the local `claud
121121
## Prerequisites
122122

123123
- Node.js >= 18
124-
- macOS or Linux
124+
- macOS, Windows, or Linux
125125
- A personal WeChat account
126126
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) CLI installed and authenticated
127127

SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ description: 微信消息桥接 - 在微信中与 Claude Code 聊天。支持文
1010
## 前置条件
1111

1212
- Node.js >= 18
13-
- macOS(daemon 使用 launchd 管理)
13+
- macOS、Windows 或 Linux
1414
- 个人微信账号(需扫码绑定)
1515
- 已安装 Claude Code(`@anthropic-ai/claude-agent-sdk`
1616

scripts/daemon.sh

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,114 @@ linux_logs() {
375375
fi
376376
}
377377

378+
# =============================================================================
379+
# Windows (Git Bash / MINGW) functions
380+
# =============================================================================
381+
382+
windows_pid_file() {
383+
echo "${DATA_DIR}/${SERVICE_NAME}.pid"
384+
}
385+
386+
windows_start() {
387+
local pid_file="$(windows_pid_file)"
388+
local node_bin="$(command -v node 2>/dev/null || echo 'node')"
389+
390+
if [ -f "$pid_file" ]; then
391+
local old_pid=$(cat "$pid_file" 2>/dev/null)
392+
if [ -n "$old_pid" ] && kill -0 "$old_pid" 2>/dev/null; then
393+
echo "Already running (PID: $old_pid)"
394+
exit 0
395+
fi
396+
rm -f "$pid_file"
397+
fi
398+
399+
mkdir -p "$DATA_DIR/logs"
400+
401+
echo "Starting wechat-claude-code daemon (Windows)..."
402+
nohup "$node_bin" "${PROJECT_DIR}/dist/main.js" start \
403+
>> "$DATA_DIR/logs/stdout.log" \
404+
2>> "$DATA_DIR/logs/stderr.log" &
405+
local pid=$!
406+
echo "$pid" > "$pid_file"
407+
echo "Started (PID: $pid)"
408+
echo "Logs: $DATA_DIR/logs/stdout.log"
409+
}
410+
411+
windows_stop() {
412+
local pid_file="$(windows_pid_file)"
413+
414+
if [ ! -f "$pid_file" ]; then
415+
echo "Not running (no PID file)"
416+
exit 0
417+
fi
418+
419+
local pid=$(cat "$pid_file" 2>/dev/null)
420+
if [ -z "$pid" ]; then
421+
rm -f "$pid_file"
422+
echo "Stopped"
423+
exit 0
424+
fi
425+
426+
if kill -0 "$pid" 2>/dev/null; then
427+
kill "$pid" 2>/dev/null || true
428+
local count=0
429+
while kill -0 "$pid" 2>/dev/null && [ $count -lt 10 ]; do
430+
sleep 1
431+
count=$((count + 1))
432+
done
433+
# Fallback: use taskkill if process still alive
434+
if kill -0 "$pid" 2>/dev/null; then
435+
taskkill //F //PID "$pid" 2>/dev/null || true
436+
fi
437+
echo "Stopped (PID: $pid)"
438+
else
439+
echo "Process not running (cleaning up PID file)"
440+
fi
441+
442+
rm -f "$pid_file"
443+
}
444+
445+
windows_status() {
446+
local pid_file="$(windows_pid_file)"
447+
448+
if [ ! -f "$pid_file" ]; then
449+
echo "Not running"
450+
exit 0
451+
fi
452+
453+
local pid=$(cat "$pid_file" 2>/dev/null)
454+
if [ -z "$pid" ]; then
455+
echo "Not running (invalid PID file)"
456+
exit 0
457+
fi
458+
459+
if kill -0 "$pid" 2>/dev/null; then
460+
echo "Running (PID: $pid)"
461+
else
462+
echo "Not running (stale PID file)"
463+
fi
464+
}
465+
466+
windows_logs() {
467+
local log_dir="${DATA_DIR}/logs"
468+
if [ -d "$log_dir" ]; then
469+
local latest=$(ls -t "${log_dir}"/bridge-*.log 2>/dev/null | head -1)
470+
if [ -n "$latest" ]; then
471+
tail -100 "$latest"
472+
else
473+
for f in "${log_dir}"/stdout.log "${log_dir}"/stderr.log; do
474+
if [ -f "$f" ]; then
475+
echo "=== $(basename "$f") ==="
476+
tail -50 "$f"
477+
echo ""
478+
fi
479+
done
480+
fi
481+
else
482+
echo "No logs found"
483+
fi
484+
}
485+
378486
# =============================================================================
379487
# Main dispatcher
380488
# =============================================================================
@@ -411,9 +519,23 @@ main() {
411519
;;
412520
esac
413521
;;
522+
MINGW*|MSYS*|CYGWIN*)
523+
case "$command" in
524+
start) windows_start ;;
525+
stop) windows_stop ;;
526+
restart) windows_stop; sleep 1; windows_start ;;
527+
status) windows_status ;;
528+
logs) windows_logs ;;
529+
*)
530+
echo "Usage: daemon.sh {start|stop|restart|status|logs}"
531+
echo "Platform: Windows (Git Bash)"
532+
exit 1
533+
;;
534+
esac
535+
;;
414536
*)
415537
echo "Error: Unsupported platform '$OS_TYPE'"
416-
echo "Supported platforms: macOS (Darwin), Linux"
538+
echo "Supported platforms: macOS (Darwin), Linux, Windows (MINGW/MSYS)"
417539
exit 1
418540
;;
419541
esac

src/tools/visualize-logs.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,12 @@ function main() {
721721
writeFileSync(output, html, 'utf-8');
722722
console.log(`Written to: ${output}`);
723723
if (open) {
724-
execSync(`open "${output}"`);
724+
const cmd = process.platform === 'win32'
725+
? `cmd /c start "" "${output}"`
726+
: process.platform === 'darwin'
727+
? `open "${output}"`
728+
: `xdg-open "${output}"`;
729+
execSync(cmd);
725730
}
726731
} else {
727732
process.stdout.write(html);

src/wechat/send.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { existsSync } from 'node:fs';
2+
import { homedir } from 'node:os';
23
import { resolve } from 'node:path';
34
import { WeChatApi } from './api.js';
45
import { MessageItemType, MessageType, MessageState, TypingStatus, type MessageItem, type OutboundMessage } from './types.js';
@@ -115,7 +116,7 @@ export function createSender(api: WeChatApi, botAccountId: string) {
115116
}
116117

117118
async function sendFile(toUserId: string, contextToken: string, filePath: string): Promise<void> {
118-
const resolved = resolve(filePath.replace(/^~/, process.env.HOME || ''));
119+
const resolved = resolve(filePath.replace(/^~/, homedir()));
119120
if (!existsSync(resolved)) {
120121
await sendText(toUserId, contextToken, `文件不存在: ${resolved}`);
121122
return;

0 commit comments

Comments
 (0)