claude-codex-wechat 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -94
- package/dist/server/cli.js +68 -99
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -83,11 +83,21 @@ pnpm install
|
|
|
83
83
|
可用命令:
|
|
84
84
|
|
|
85
85
|
- `claude-codex-wechat start`
|
|
86
|
-
-
|
|
87
|
-
- `claude-codex-wechat
|
|
88
|
-
-
|
|
86
|
+
- 后台启动服务(未安装则自动注册系统服务),默认命令
|
|
87
|
+
- `claude-codex-wechat stop`
|
|
88
|
+
- 停止后台服务
|
|
89
|
+
- `claude-codex-wechat restart`
|
|
90
|
+
- 重启后台服务
|
|
91
|
+
- `claude-codex-wechat status`
|
|
92
|
+
- 查看运行状态
|
|
93
|
+
- `claude-codex-wechat logs` / `tail`
|
|
94
|
+
- 打印 / 实时跟随日志
|
|
89
95
|
- `claude-codex-wechat doctor`
|
|
90
96
|
- 检查配置、前端产物、`claude`/`codex` 可执行文件
|
|
97
|
+
- `claude-codex-wechat init`
|
|
98
|
+
- 写默认配置到 `~/.claude-codex-wechat/config.json`
|
|
99
|
+
- `claude-codex-wechat uninstall`
|
|
100
|
+
- 卸载后台服务
|
|
91
101
|
- `claude-codex-wechat print-config`
|
|
92
102
|
- 打印当前配置文件
|
|
93
103
|
- `claude-codex-wechat help`
|
|
@@ -178,35 +188,24 @@ pnpm build
|
|
|
178
188
|
|
|
179
189
|
## 生产运行
|
|
180
190
|
|
|
181
|
-
|
|
191
|
+
安装后直接后台启动即可,`start` 会把当前 CLI 注册成操作系统服务并拉起:
|
|
182
192
|
|
|
183
193
|
```bash
|
|
184
|
-
claude-codex-wechat
|
|
194
|
+
claude-codex-wechat init # 首次:写配置,填好 token / accountId
|
|
195
|
+
claude-codex-wechat start # 后台启动(自动安装服务)
|
|
196
|
+
claude-codex-wechat status # 查看状态
|
|
185
197
|
```
|
|
186
198
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
- 这是前台进程
|
|
190
|
-
- npm 本身不负责守护
|
|
191
|
-
- 长期常驻建议交给进程管理器
|
|
192
|
-
- 如果默认端口已被本程序的后台服务占用,`start` 会先停掉后台服务,再以前台模式启动
|
|
193
|
-
- 如果端口被别的进程占用,`start` 会直接报出占用 PID 和命令,不会强杀陌生进程
|
|
194
|
-
|
|
195
|
-
### 安装后后台运行
|
|
196
|
-
|
|
197
|
-
参考 `happier` 的方式,这个仓库现在提供 `service` 命令,把当前 CLI 注册成操作系统服务,而不是在 Node 进程里自己 daemonize。
|
|
198
|
-
|
|
199
|
-
常用命令:
|
|
199
|
+
常用管理命令:
|
|
200
200
|
|
|
201
201
|
```bash
|
|
202
|
-
claude-codex-wechat
|
|
203
|
-
claude-codex-wechat
|
|
204
|
-
claude-codex-wechat
|
|
205
|
-
claude-codex-wechat
|
|
206
|
-
claude-codex-wechat
|
|
207
|
-
claude-codex-wechat
|
|
208
|
-
claude-codex-wechat
|
|
209
|
-
claude-codex-wechat service uninstall
|
|
202
|
+
claude-codex-wechat start # 后台启动 / 启动已安装服务
|
|
203
|
+
claude-codex-wechat restart # 重启
|
|
204
|
+
claude-codex-wechat status # 状态
|
|
205
|
+
claude-codex-wechat logs # 最近日志
|
|
206
|
+
claude-codex-wechat tail # 实时日志
|
|
207
|
+
claude-codex-wechat stop # 停止
|
|
208
|
+
claude-codex-wechat uninstall # 卸载服务
|
|
210
209
|
```
|
|
211
210
|
|
|
212
211
|
当前支持:
|
|
@@ -214,73 +213,7 @@ claude-codex-wechat service uninstall
|
|
|
214
213
|
- macOS:`launchd`(`~/Library/LaunchAgents/`)
|
|
215
214
|
- Linux:`systemd --user`(`~/.config/systemd/user/`)
|
|
216
215
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
```bash
|
|
220
|
-
claude-codex-wechat init
|
|
221
|
-
claude-codex-wechat service install
|
|
222
|
-
claude-codex-wechat service status
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### pm2
|
|
226
|
-
|
|
227
|
-
```bash
|
|
228
|
-
npm install -g pm2
|
|
229
|
-
pm2 start claude-codex-wechat --name ccwx -- start
|
|
230
|
-
pm2 logs ccwx
|
|
231
|
-
pm2 restart ccwx
|
|
232
|
-
pm2 startup && pm2 save
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
### systemd
|
|
236
|
-
|
|
237
|
-
示例:
|
|
238
|
-
|
|
239
|
-
```ini
|
|
240
|
-
[Unit]
|
|
241
|
-
Description=claude-codex-wechat bridge daemon
|
|
242
|
-
After=network.target
|
|
243
|
-
|
|
244
|
-
[Service]
|
|
245
|
-
Type=simple
|
|
246
|
-
User=youruser
|
|
247
|
-
Environment=BRIDGE_PORT=8787
|
|
248
|
-
ExecStart=/usr/bin/claude-codex-wechat start
|
|
249
|
-
Restart=on-failure
|
|
250
|
-
RestartSec=5
|
|
251
|
-
|
|
252
|
-
[Install]
|
|
253
|
-
WantedBy=multi-user.target
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### launchd
|
|
257
|
-
|
|
258
|
-
示例:
|
|
259
|
-
|
|
260
|
-
```xml
|
|
261
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
262
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
263
|
-
<plist version="1.0">
|
|
264
|
-
<dict>
|
|
265
|
-
<key>Label</key>
|
|
266
|
-
<string>com.claude-codex-wechat</string>
|
|
267
|
-
<key>ProgramArguments</key>
|
|
268
|
-
<array>
|
|
269
|
-
<string>/opt/homebrew/bin/claude-codex-wechat</string>
|
|
270
|
-
<string>start</string>
|
|
271
|
-
</array>
|
|
272
|
-
<key>EnvironmentVariables</key>
|
|
273
|
-
<dict>
|
|
274
|
-
<key>BRIDGE_PORT</key>
|
|
275
|
-
<string>8787</string>
|
|
276
|
-
</dict>
|
|
277
|
-
<key>RunAtLoad</key>
|
|
278
|
-
<true/>
|
|
279
|
-
<key>KeepAlive</key>
|
|
280
|
-
<true/>
|
|
281
|
-
</dict>
|
|
282
|
-
</plist>
|
|
283
|
-
```
|
|
216
|
+
服务会以 `KeepAlive` / `Restart=on-failure` 守护,崩溃后自动拉起,无需额外进程管理器。
|
|
284
217
|
|
|
285
218
|
## 发布 npm 包
|
|
286
219
|
|
|
@@ -347,7 +280,6 @@ HTTPS_PROXY=http://127.0.0.1:7890 HTTP_PROXY=http://127.0.0.1:7890 ./release.sh
|
|
|
347
280
|
|
|
348
281
|
这个脚本会:
|
|
349
282
|
|
|
350
|
-
- 先检查 `npm whoami`
|
|
351
283
|
- 先执行 `pnpm typecheck`
|
|
352
284
|
- 再执行 `pnpm build`
|
|
353
285
|
- 提交当前改动
|
package/dist/server/cli.js
CHANGED
|
@@ -3989,27 +3989,6 @@ async function resolveProviderCommands(providers) {
|
|
|
3989
3989
|
};
|
|
3990
3990
|
}
|
|
3991
3991
|
|
|
3992
|
-
// src/daemon/portGuard.ts
|
|
3993
|
-
import { execFile } from "node:child_process";
|
|
3994
|
-
import { promisify } from "node:util";
|
|
3995
|
-
var execFileAsync = promisify(execFile);
|
|
3996
|
-
async function findListeningProcess(port) {
|
|
3997
|
-
if (process.platform === "win32") return null;
|
|
3998
|
-
try {
|
|
3999
|
-
const { stdout } = await execFileAsync("lsof", ["-n", "-P", `-iTCP:${port}`, "-sTCP:LISTEN"]);
|
|
4000
|
-
const lines = stdout.trim().split(/\r?\n/).filter(Boolean);
|
|
4001
|
-
const record = lines.slice(1)[0];
|
|
4002
|
-
if (!record) return null;
|
|
4003
|
-
const parts = record.trim().split(/\s+/);
|
|
4004
|
-
const command = parts[0] ?? "";
|
|
4005
|
-
const pid = Number(parts[1] ?? "");
|
|
4006
|
-
if (!command || !Number.isFinite(pid)) return null;
|
|
4007
|
-
return { pid, command };
|
|
4008
|
-
} catch {
|
|
4009
|
-
return null;
|
|
4010
|
-
}
|
|
4011
|
-
}
|
|
4012
|
-
|
|
4013
3992
|
// src/daemon/staticFrontend.ts
|
|
4014
3993
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
4015
3994
|
import { join as join9 } from "node:path";
|
|
@@ -4037,10 +4016,10 @@ import { mkdir as mkdir4, readFile as readFile6, rm as rm2, writeFile as writeFi
|
|
|
4037
4016
|
import { homedir as homedir7 } from "node:os";
|
|
4038
4017
|
import { dirname as dirname10, join as join10 } from "node:path";
|
|
4039
4018
|
import { createReadStream } from "node:fs";
|
|
4040
|
-
import { execFile
|
|
4019
|
+
import { execFile, spawn as spawn6 } from "node:child_process";
|
|
4041
4020
|
import { createInterface } from "node:readline";
|
|
4042
|
-
import { promisify
|
|
4043
|
-
var
|
|
4021
|
+
import { promisify } from "node:util";
|
|
4022
|
+
var execFileAsync = promisify(execFile);
|
|
4044
4023
|
async function installService(context) {
|
|
4045
4024
|
if (process.platform === "darwin") {
|
|
4046
4025
|
const spec = buildLaunchdSpec(context);
|
|
@@ -4181,7 +4160,7 @@ function buildLaunchdSpec(context) {
|
|
|
4181
4160
|
return {
|
|
4182
4161
|
label: "com.claude-codex-wechat",
|
|
4183
4162
|
plistPath: join10(homedir7(), "Library", "LaunchAgents", "com.claude-codex-wechat.plist"),
|
|
4184
|
-
programArgs: [context.nodePath ?? process.execPath, context.cliEntrypointPath, "
|
|
4163
|
+
programArgs: [context.nodePath ?? process.execPath, context.cliEntrypointPath, "__daemon"],
|
|
4185
4164
|
workingDirectory: homedir7(),
|
|
4186
4165
|
stdoutPath: join10(stateDir, "logs", "service.stdout.log"),
|
|
4187
4166
|
stderrPath: join10(stateDir, "logs", "service.stderr.log"),
|
|
@@ -4193,7 +4172,7 @@ function buildSystemdUserSpec(context) {
|
|
|
4193
4172
|
return {
|
|
4194
4173
|
unitName: "claude-codex-wechat.service",
|
|
4195
4174
|
unitPath: join10(homedir7(), ".config", "systemd", "user", "claude-codex-wechat.service"),
|
|
4196
|
-
execStart: [context.nodePath ?? process.execPath, context.cliEntrypointPath, "
|
|
4175
|
+
execStart: [context.nodePath ?? process.execPath, context.cliEntrypointPath, "__daemon"],
|
|
4197
4176
|
workingDirectory: homedir7(),
|
|
4198
4177
|
stdoutPath: join10(stateDir, "logs", "service.stdout.log"),
|
|
4199
4178
|
stderrPath: join10(stateDir, "logs", "service.stderr.log"),
|
|
@@ -4292,10 +4271,10 @@ function quoteSystemdEnv(value) {
|
|
|
4292
4271
|
return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
|
|
4293
4272
|
}
|
|
4294
4273
|
async function runLaunchctl(args) {
|
|
4295
|
-
await
|
|
4274
|
+
await execFileAsync("launchctl", args);
|
|
4296
4275
|
}
|
|
4297
4276
|
async function runSystemctl(args) {
|
|
4298
|
-
await
|
|
4277
|
+
await execFileAsync("systemctl", args);
|
|
4299
4278
|
}
|
|
4300
4279
|
async function ensureFileExists(path, errorCode) {
|
|
4301
4280
|
if (!existsSync8(path)) throw new Error(errorCode);
|
|
@@ -4350,18 +4329,37 @@ async function main() {
|
|
|
4350
4329
|
case "start":
|
|
4351
4330
|
await cmdStart();
|
|
4352
4331
|
return;
|
|
4332
|
+
case "stop":
|
|
4333
|
+
await cmdStop();
|
|
4334
|
+
return;
|
|
4335
|
+
case "restart":
|
|
4336
|
+
await cmdRestart();
|
|
4337
|
+
return;
|
|
4338
|
+
case "status":
|
|
4339
|
+
await cmdStatus();
|
|
4340
|
+
return;
|
|
4341
|
+
case "logs":
|
|
4342
|
+
await cmdLogs();
|
|
4343
|
+
return;
|
|
4344
|
+
case "tail":
|
|
4345
|
+
await cmdTail();
|
|
4346
|
+
return;
|
|
4353
4347
|
case "init":
|
|
4354
4348
|
cmdInit();
|
|
4355
4349
|
return;
|
|
4356
4350
|
case "doctor":
|
|
4357
4351
|
await cmdDoctor();
|
|
4358
4352
|
return;
|
|
4359
|
-
case "
|
|
4360
|
-
await
|
|
4353
|
+
case "uninstall":
|
|
4354
|
+
await cmdUninstall();
|
|
4361
4355
|
return;
|
|
4362
4356
|
case "print-config":
|
|
4363
4357
|
cmdPrintConfig();
|
|
4364
4358
|
return;
|
|
4359
|
+
// 内部命令:service 文件实际拉起的前台 daemon 进程,不对外暴露。
|
|
4360
|
+
case "__daemon":
|
|
4361
|
+
await cmdDaemon();
|
|
4362
|
+
return;
|
|
4365
4363
|
case "help":
|
|
4366
4364
|
case "--help":
|
|
4367
4365
|
case "-h":
|
|
@@ -4377,24 +4375,38 @@ async function main() {
|
|
|
4377
4375
|
async function cmdStart() {
|
|
4378
4376
|
if (!existsSync9(webRoot)) {
|
|
4379
4377
|
console.error(`\u627E\u4E0D\u5230\u524D\u7AEF\u6784\u5EFA\u4EA7\u7269: ${webRoot}`);
|
|
4380
|
-
console.error("\u8BF7\
|
|
4378
|
+
console.error("\u8BF7\u91CD\u65B0\u5B89\u88C5\u5B8C\u6574\u7684 npm \u5305\u3002");
|
|
4381
4379
|
process.exitCode = 1;
|
|
4382
4380
|
return;
|
|
4383
4381
|
}
|
|
4384
4382
|
const context = createServiceContext();
|
|
4385
|
-
const
|
|
4386
|
-
const
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4383
|
+
const status = await readServiceStatus(context).catch(() => null);
|
|
4384
|
+
const result = status?.installed ? await startService(context) : await installService(context);
|
|
4385
|
+
printServiceStatus("service started", result);
|
|
4386
|
+
}
|
|
4387
|
+
async function cmdStop() {
|
|
4388
|
+
const status = await stopService(createServiceContext());
|
|
4389
|
+
printServiceStatus("service stopped", status);
|
|
4390
|
+
}
|
|
4391
|
+
async function cmdRestart() {
|
|
4392
|
+
const status = await restartService(createServiceContext());
|
|
4393
|
+
printServiceStatus("service restarted", status);
|
|
4394
|
+
}
|
|
4395
|
+
async function cmdStatus() {
|
|
4396
|
+
const status = await readServiceStatus(createServiceContext());
|
|
4397
|
+
printServiceStatus("service status", status);
|
|
4398
|
+
}
|
|
4399
|
+
async function cmdLogs() {
|
|
4400
|
+
console.log(await readServiceLogs(createServiceContext()));
|
|
4401
|
+
}
|
|
4402
|
+
async function cmdTail() {
|
|
4403
|
+
await tailServiceLogs(createServiceContext());
|
|
4404
|
+
}
|
|
4405
|
+
async function cmdDaemon() {
|
|
4406
|
+
if (!existsSync9(webRoot)) {
|
|
4407
|
+
console.error(`\u627E\u4E0D\u5230\u524D\u7AEF\u6784\u5EFA\u4EA7\u7269: ${webRoot}`);
|
|
4408
|
+
process.exitCode = 1;
|
|
4409
|
+
return;
|
|
4398
4410
|
}
|
|
4399
4411
|
await startDaemon({
|
|
4400
4412
|
attachFrontend: attachStaticFrontend(webRoot)
|
|
@@ -4452,54 +4464,9 @@ function cmdPrintConfig() {
|
|
|
4452
4464
|
}
|
|
4453
4465
|
console.log(readFileSync7(configPath, "utf8"));
|
|
4454
4466
|
}
|
|
4455
|
-
async function
|
|
4456
|
-
const
|
|
4457
|
-
|
|
4458
|
-
switch (action) {
|
|
4459
|
-
case "install": {
|
|
4460
|
-
const status = await installService(context);
|
|
4461
|
-
printServiceStatus("service installed", status);
|
|
4462
|
-
return;
|
|
4463
|
-
}
|
|
4464
|
-
case "start": {
|
|
4465
|
-
const status = await startService(context);
|
|
4466
|
-
printServiceStatus("service started", status);
|
|
4467
|
-
return;
|
|
4468
|
-
}
|
|
4469
|
-
case "stop": {
|
|
4470
|
-
const status = await stopService(context);
|
|
4471
|
-
printServiceStatus("service stopped", status);
|
|
4472
|
-
return;
|
|
4473
|
-
}
|
|
4474
|
-
case "restart": {
|
|
4475
|
-
const status = await restartService(context);
|
|
4476
|
-
printServiceStatus("service restarted", status);
|
|
4477
|
-
return;
|
|
4478
|
-
}
|
|
4479
|
-
case "logs": {
|
|
4480
|
-
console.log(await readServiceLogs(context));
|
|
4481
|
-
return;
|
|
4482
|
-
}
|
|
4483
|
-
case "tail": {
|
|
4484
|
-
await tailServiceLogs(context);
|
|
4485
|
-
return;
|
|
4486
|
-
}
|
|
4487
|
-
case "uninstall": {
|
|
4488
|
-
const status = await uninstallService(context);
|
|
4489
|
-
printServiceStatus("service uninstalled", status);
|
|
4490
|
-
return;
|
|
4491
|
-
}
|
|
4492
|
-
case "status": {
|
|
4493
|
-
const status = await readServiceStatus(context);
|
|
4494
|
-
printServiceStatus("service status", status);
|
|
4495
|
-
return;
|
|
4496
|
-
}
|
|
4497
|
-
default:
|
|
4498
|
-
console.error(`\u672A\u77E5 service \u5B50\u547D\u4EE4: ${action}
|
|
4499
|
-
`);
|
|
4500
|
-
printUsage();
|
|
4501
|
-
process.exitCode = 1;
|
|
4502
|
-
}
|
|
4467
|
+
async function cmdUninstall() {
|
|
4468
|
+
const status = await uninstallService(createServiceContext());
|
|
4469
|
+
printServiceStatus("service uninstalled", status);
|
|
4503
4470
|
}
|
|
4504
4471
|
function createServiceContext() {
|
|
4505
4472
|
return {
|
|
@@ -4530,18 +4497,20 @@ function printUsage() {
|
|
|
4530
4497
|
claude-codex-wechat <command>
|
|
4531
4498
|
|
|
4532
4499
|
\u547D\u4EE4:
|
|
4533
|
-
start \u542F\u52A8
|
|
4534
|
-
|
|
4500
|
+
start \u540E\u53F0\u542F\u52A8\u670D\u52A1\uFF08\u672A\u5B89\u88C5\u5219\u81EA\u52A8\u5B89\u88C5\uFF0C\u9ED8\u8BA4\u547D\u4EE4\uFF09
|
|
4501
|
+
stop \u505C\u6B62\u540E\u53F0\u670D\u52A1
|
|
4502
|
+
restart \u91CD\u542F\u540E\u53F0\u670D\u52A1
|
|
4503
|
+
status \u67E5\u770B\u8FD0\u884C\u72B6\u6001
|
|
4504
|
+
logs \u6253\u5370\u6700\u8FD1\u65E5\u5FD7
|
|
4505
|
+
tail \u5B9E\u65F6\u8DDF\u968F\u65E5\u5FD7
|
|
4535
4506
|
doctor \u68C0\u67E5\u914D\u7F6E\u3001\u524D\u7AEF\u4EA7\u7269\u4E0E claude/codex \u53EF\u6267\u884C\u6587\u4EF6
|
|
4536
|
-
|
|
4507
|
+
init \u5728 ~/.claude-codex-wechat/ \u521B\u5EFA\u9ED8\u8BA4\u914D\u7F6E
|
|
4508
|
+
uninstall \u5378\u8F7D\u540E\u53F0\u670D\u52A1
|
|
4537
4509
|
print-config \u6253\u5370\u5F53\u524D\u914D\u7F6E\u6587\u4EF6\u5185\u5BB9
|
|
4538
4510
|
help \u663E\u793A\u672C\u5E2E\u52A9
|
|
4539
4511
|
|
|
4540
4512
|
\u73AF\u5883\u53D8\u91CF:
|
|
4541
4513
|
BRIDGE_PORT \u76D1\u542C\u7AEF\u53E3\uFF08\u9ED8\u8BA4 8787\uFF09
|
|
4542
|
-
BRIDGE_CONFIG \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4 ~/.claude-codex-wechat/config.json\uFF09
|
|
4543
|
-
|
|
4544
|
-
\u5E38\u9A7B\u8FD0\u884C\u8BF7\u7528\u8FDB\u7A0B\u7BA1\u7406\u5668\u6258\u7BA1\uFF0C\u4F8B\u5982:
|
|
4545
|
-
pm2 start claude-codex-wechat -- start`);
|
|
4514
|
+
BRIDGE_CONFIG \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4 ~/.claude-codex-wechat/config.json\uFF09`);
|
|
4546
4515
|
}
|
|
4547
4516
|
await main();
|