@foxden-app/foxclaw 0.5.8 → 0.5.9
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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable FoxClaw changes are listed here. Each release note is bilingual so GitHub Releases and the npm package are useful to both Chinese and English readers.
|
|
4
4
|
|
|
5
|
+
## 0.5.9 - 2026-06-07
|
|
6
|
+
|
|
7
|
+
### 中文
|
|
8
|
+
- Linux 用户级 systemd 安装现在会在 `foxclaw start` / `restart` / `install-systemd` 时自动尝试启用 systemd user linger,避免用户退出 SSH 或桌面会话后 FoxClaw 停止接收 Telegram 消息。
|
|
9
|
+
- `foxclaw doctor` 新增 linger 状态检查;如果自动启用失败,会提示使用 `sudo loginctl enable-linger <user>` 手动修复。
|
|
10
|
+
- 中文/英文安装指南和故障排查文档更新为默认自动处理 linger,失败时再手动介入。
|
|
11
|
+
|
|
12
|
+
### English
|
|
13
|
+
- Linux user-systemd installation now tries to enable systemd user linger during `foxclaw start`, `restart`, and `install-systemd`, preventing FoxClaw from stopping after SSH or desktop logout.
|
|
14
|
+
- `foxclaw doctor` now checks linger state and tells users to run `sudo loginctl enable-linger <user>` if automatic setup fails.
|
|
15
|
+
- Updated the Chinese and English install and troubleshooting docs to describe automatic linger setup with manual recovery only when needed.
|
|
16
|
+
|
|
5
17
|
## 0.5.8 - 2026-06-05
|
|
6
18
|
|
|
7
19
|
### 中文
|
package/dist/main.js
CHANGED
|
@@ -1132,6 +1132,7 @@ function runDoctorChecks() {
|
|
|
1132
1132
|
warnIfProxyEnvMissingFromLoadedEnv();
|
|
1133
1133
|
warnIfProxyConfigNeedsAttention();
|
|
1134
1134
|
warnIfInstalledServiceNodeLooksWrong();
|
|
1135
|
+
warnIfSystemdUserLingerDisabled();
|
|
1135
1136
|
return passed;
|
|
1136
1137
|
}
|
|
1137
1138
|
function warnIfProxyConfigNeedsAttention() {
|
|
@@ -1204,6 +1205,21 @@ function warnIfInstalledServiceNodeLooksWrong() {
|
|
|
1204
1205
|
console.log(`[WARN] installed service node is older than 24: ${nodePath}${version ? ` (${version})` : ''}`);
|
|
1205
1206
|
console.log('[WARN] Run foxclaw start from a Node 24 shell to refresh the service unit.');
|
|
1206
1207
|
}
|
|
1208
|
+
function warnIfSystemdUserLingerDisabled() {
|
|
1209
|
+
if (process.platform !== 'linux' || !hasCommand('loginctl')) {
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
const user = currentServiceUser();
|
|
1213
|
+
const linger = readSystemdUserLinger(user);
|
|
1214
|
+
if (linger === 'enabled') {
|
|
1215
|
+
console.log(`[OK] systemd user linger enabled: ${user}`);
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1218
|
+
if (linger === 'disabled') {
|
|
1219
|
+
console.log(`[WARN] systemd user linger is disabled for ${user}; user services may stop after logout.`);
|
|
1220
|
+
console.log('[WARN] Run foxclaw start to let FoxClaw enable it, or run: sudo loginctl enable-linger "$USER"');
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1207
1223
|
function extractNodePathFromExecStart(execStart) {
|
|
1208
1224
|
const tokens = execStart.split(/\s+/).map(systemdUnescape).filter(Boolean);
|
|
1209
1225
|
const directNode = tokens[0] || '';
|
|
@@ -1262,6 +1278,7 @@ function installSystemd() {
|
|
|
1262
1278
|
console.log(`[OK] updated FoxClaw ExecStart override: ${update.path}`);
|
|
1263
1279
|
}
|
|
1264
1280
|
}
|
|
1281
|
+
ensureSystemdUserLingerEnabled();
|
|
1265
1282
|
spawnChecked('systemctl', ['--user', 'daemon-reload']);
|
|
1266
1283
|
spawnChecked('systemctl', ['--user', 'enable', unitName]);
|
|
1267
1284
|
const restarted = spawnSync('systemctl', ['--user', 'restart', unitName], { stdio: 'inherit' });
|
|
@@ -1272,6 +1289,32 @@ function installSystemd() {
|
|
|
1272
1289
|
console.log(`Status: systemctl --user status ${unitName}`);
|
|
1273
1290
|
console.log(`Logs: journalctl --user -u ${unitName} -f`);
|
|
1274
1291
|
}
|
|
1292
|
+
function ensureSystemdUserLingerEnabled() {
|
|
1293
|
+
if (process.platform !== 'linux') {
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1296
|
+
if (!hasCommand('loginctl')) {
|
|
1297
|
+
console.log('[WARN] loginctl not found; cannot enable systemd user linger automatically.');
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
const user = currentServiceUser();
|
|
1301
|
+
const before = readSystemdUserLinger(user);
|
|
1302
|
+
if (before === 'enabled') {
|
|
1303
|
+
console.log(`[OK] systemd user linger enabled: ${user}`);
|
|
1304
|
+
return;
|
|
1305
|
+
}
|
|
1306
|
+
console.log(`[INFO] Enabling systemd user linger for ${user} so FoxClaw keeps running after logout.`);
|
|
1307
|
+
let result = spawnSync('loginctl', ['enable-linger', user], { stdio: 'inherit' });
|
|
1308
|
+
if (result.status !== 0 && hasCommand('sudo')) {
|
|
1309
|
+
result = spawnSync('sudo', ['-n', 'loginctl', 'enable-linger', user], { stdio: 'inherit' });
|
|
1310
|
+
}
|
|
1311
|
+
if (result.status === 0 && readSystemdUserLinger(user) === 'enabled') {
|
|
1312
|
+
console.log(`[OK] systemd user linger enabled: ${user}`);
|
|
1313
|
+
return;
|
|
1314
|
+
}
|
|
1315
|
+
console.log(`[WARN] Could not enable systemd user linger automatically for ${user}.`);
|
|
1316
|
+
console.log(`[WARN] FoxClaw is installed, but it may stop after logout until you run: sudo loginctl enable-linger ${shellQuote(user)}`);
|
|
1317
|
+
}
|
|
1275
1318
|
function uninstallSystemd() {
|
|
1276
1319
|
if (!hasCommand('systemctl')) {
|
|
1277
1320
|
console.error('systemctl not found');
|
|
@@ -1392,6 +1435,36 @@ function buildServicePath(nodeDir) {
|
|
|
1392
1435
|
function serviceEnvPath() {
|
|
1393
1436
|
return path.resolve(process.env.FOXCLAW_ENV?.trim() || getLoadedEnvPath() || DEFAULT_ENV_PATH);
|
|
1394
1437
|
}
|
|
1438
|
+
function currentServiceUser() {
|
|
1439
|
+
return process.env.USER?.trim()
|
|
1440
|
+
|| process.env.LOGNAME?.trim()
|
|
1441
|
+
|| os.userInfo().username;
|
|
1442
|
+
}
|
|
1443
|
+
function readSystemdUserLinger(user) {
|
|
1444
|
+
const valueResult = spawnSync('loginctl', ['show-user', user, '-p', 'Linger', '--value'], { encoding: 'utf8' });
|
|
1445
|
+
if (valueResult.status === 0) {
|
|
1446
|
+
return parseSystemdUserLinger(valueResult.stdout);
|
|
1447
|
+
}
|
|
1448
|
+
const propertyResult = spawnSync('loginctl', ['show-user', user, '-p', 'Linger'], { encoding: 'utf8' });
|
|
1449
|
+
if (propertyResult.status === 0) {
|
|
1450
|
+
return parseSystemdUserLinger(propertyResult.stdout);
|
|
1451
|
+
}
|
|
1452
|
+
return 'unknown';
|
|
1453
|
+
}
|
|
1454
|
+
function parseSystemdUserLinger(output) {
|
|
1455
|
+
const value = output.trim().replace(/^Linger=/, '').toLowerCase();
|
|
1456
|
+
if (value === 'yes')
|
|
1457
|
+
return 'enabled';
|
|
1458
|
+
if (value === 'no')
|
|
1459
|
+
return 'disabled';
|
|
1460
|
+
return 'unknown';
|
|
1461
|
+
}
|
|
1462
|
+
function shellQuote(value) {
|
|
1463
|
+
if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(value)) {
|
|
1464
|
+
return value;
|
|
1465
|
+
}
|
|
1466
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
1467
|
+
}
|
|
1395
1468
|
function hasStandardNodeProxyEnv() {
|
|
1396
1469
|
return STANDARD_NODE_PROXY_ENV_KEYS.some((key) => Boolean(proxyEnvValue(key)));
|
|
1397
1470
|
}
|
|
@@ -250,17 +250,17 @@ Create a short README-style summary of this folder.
|
|
|
250
250
|
|
|
251
251
|
## 10. Service Commands
|
|
252
252
|
|
|
253
|
-
On Linux, `foxclaw start` manages a user-level systemd service. Check it with:
|
|
253
|
+
On Linux, `foxclaw start` manages a user-level systemd service and tries to enable systemd user linger so the service keeps running after you leave SSH or log out. Check it with:
|
|
254
254
|
|
|
255
255
|
```bash
|
|
256
256
|
systemctl --user status foxclaw.service
|
|
257
257
|
journalctl --user -u foxclaw.service -f
|
|
258
258
|
```
|
|
259
259
|
|
|
260
|
-
|
|
260
|
+
If install reports that linger could not be enabled automatically, run:
|
|
261
261
|
|
|
262
262
|
```bash
|
|
263
|
-
loginctl enable-linger "$USER"
|
|
263
|
+
sudo loginctl enable-linger "$USER"
|
|
264
264
|
```
|
|
265
265
|
|
|
266
266
|
On macOS, `foxclaw start` manages launchd and starts FoxClaw when you log in.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -261,10 +261,10 @@ Linux user systemd:
|
|
|
261
261
|
systemctl --user is-enabled foxclaw.service
|
|
262
262
|
```
|
|
263
263
|
|
|
264
|
-
`enabled` means it starts with your user session.
|
|
264
|
+
`enabled` means it starts with your user session. `foxclaw start` tries to enable systemd user linger automatically so the service keeps running after SSH logout and before login. If automatic linger setup fails:
|
|
265
265
|
|
|
266
266
|
```bash
|
|
267
|
-
loginctl enable-linger "$USER"
|
|
267
|
+
sudo loginctl enable-linger "$USER"
|
|
268
268
|
```
|
|
269
269
|
|
|
270
270
|
macOS launchd starts FoxClaw when you log in after running:
|
|
@@ -248,17 +248,17 @@ Create a short README-style summary of this folder.
|
|
|
248
248
|
|
|
249
249
|
## 10. 服务命令
|
|
250
250
|
|
|
251
|
-
Linux 上 `foxclaw start` 管理用户级 systemd
|
|
251
|
+
Linux 上 `foxclaw start` 管理用户级 systemd 服务,并会尝试启用 systemd user linger,让服务在你退出 SSH 或桌面会话后继续运行。查看状态:
|
|
252
252
|
|
|
253
253
|
```bash
|
|
254
254
|
systemctl --user status foxclaw.service
|
|
255
255
|
journalctl --user -u foxclaw.service -f
|
|
256
256
|
```
|
|
257
257
|
|
|
258
|
-
|
|
258
|
+
如果安装时提示 linger 启用失败,手动执行:
|
|
259
259
|
|
|
260
260
|
```bash
|
|
261
|
-
loginctl enable-linger "$USER"
|
|
261
|
+
sudo loginctl enable-linger "$USER"
|
|
262
262
|
```
|
|
263
263
|
|
|
264
264
|
macOS 上 `foxclaw start` 管理 launchd,并在你登录后启动 FoxClaw。
|
|
@@ -262,10 +262,10 @@ Linux 用户级 systemd:
|
|
|
262
262
|
systemctl --user is-enabled foxclaw.service
|
|
263
263
|
```
|
|
264
264
|
|
|
265
|
-
`enabled`
|
|
265
|
+
`enabled` 表示会随用户会话启动。`foxclaw start` 会尝试自动启用 systemd user linger,让服务在退出 SSH 或未登录时也继续运行。如果自动启用失败:
|
|
266
266
|
|
|
267
267
|
```bash
|
|
268
|
-
loginctl enable-linger "$USER"
|
|
268
|
+
sudo loginctl enable-linger "$USER"
|
|
269
269
|
```
|
|
270
270
|
|
|
271
271
|
macOS 上,运行过下面命令后,FoxClaw 会在你登录时由 launchd 启动:
|