@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
- The service starts again when your user session starts. If you need it to start after reboot before you log in, run:
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.
@@ -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. To start after reboot before login:
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 启动:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foxden-app/foxclaw",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "Foxden local execution claw for controlling Codex from trusted chat interfaces.",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",