@cleocode/cleo 2026.5.1 → 2026.5.2

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.
@@ -154,6 +154,29 @@ async function runPostinstall() {
154
154
  console.error('CLEO: Bootstrap detail:', err);
155
155
  }
156
156
  }
157
+
158
+ // Register the CLEO daemon as a user-level system service (systemd / launchd).
159
+ // This is non-blocking and never fails the install — errors are caught and logged.
160
+ await installDaemonServiceFromScript();
161
+ }
162
+
163
+ /**
164
+ * Install the CLEO daemon as a user-level system service after global install.
165
+ *
166
+ * Delegates to the cross-platform installer in scripts/install-daemon-service.mjs.
167
+ * Always exits cleanly — installation failures are non-fatal.
168
+ */
169
+ async function installDaemonServiceFromScript() {
170
+ try {
171
+ const scriptPath = join(getPackageRoot(), 'scripts', 'install-daemon-service.mjs');
172
+ const { installDaemonService } = await import(scriptPath);
173
+ await installDaemonService();
174
+ } catch (err) {
175
+ console.log('CLEO: Daemon service registration deferred (will retry on first "cleo daemon install")');
176
+ if (process.env.CLEO_DEBUG) {
177
+ console.error('CLEO: Daemon install detail:', err);
178
+ }
179
+ }
157
180
  }
158
181
 
159
182
  runPostinstall().catch((err) => {
package/dist/cli/index.js CHANGED
@@ -25958,7 +25958,7 @@ var init_cli = __esm({
25958
25958
  // packages/cleo/src/cli/index.ts
25959
25959
  import { readFileSync as readFileSync13 } from "node:fs";
25960
25960
  import { dirname as dirname9, join as join19 } from "node:path";
25961
- import { fileURLToPath as fileURLToPath3 } from "node:url";
25961
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
25962
25962
  import {
25963
25963
  detectAndRemoveLegacyGlobalFiles,
25964
25964
  detectAndRemoveStrayProjectNexus,
@@ -34026,8 +34026,12 @@ var currentCommand = defineCommand({
34026
34026
  // packages/cleo/src/cli/commands/daemon.ts
34027
34027
  import { homedir as homedir2 } from "node:os";
34028
34028
  import { join as join9 } from "node:path";
34029
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
34029
34030
  import { getGCDaemonStatus, spawnGCDaemon, stopGCDaemon } from "@cleocode/core/gc/daemon.js";
34030
- import { getSentientDaemonStatus } from "@cleocode/core/sentient";
34031
+ import {
34032
+ bootstrapDaemon as bootstrapSentientDaemon,
34033
+ getSentientDaemonStatus
34034
+ } from "@cleocode/core/sentient";
34031
34035
  async function showDaemonStatus(cleoDir, projectRoot, json2) {
34032
34036
  try {
34033
34037
  const gcStatus = await getGCDaemonStatus(cleoDir);
@@ -34123,6 +34127,11 @@ Hygiene Loop (cross-project):
34123
34127
  process.exit(1);
34124
34128
  }
34125
34129
  }
34130
+ function resolveDaemonInstallerScript() {
34131
+ const __filename = fileURLToPath3(import.meta.url);
34132
+ const pkgRoot = join9(__filename, "..", "..", "..", "..");
34133
+ return join9(pkgRoot, "scripts", "install-daemon-service.mjs");
34134
+ }
34126
34135
  var startCommand3 = defineCommand({
34127
34136
  meta: { name: "start", description: "Spawn the GC daemon as a detached background process" },
34128
34137
  args: {
@@ -34130,6 +34139,10 @@ var startCommand3 = defineCommand({
34130
34139
  type: "string",
34131
34140
  description: "Override .cleo/ directory path"
34132
34141
  },
34142
+ foreground: {
34143
+ type: "boolean",
34144
+ description: "Run the sentient daemon in the foreground (used by systemd/launchd service units)"
34145
+ },
34133
34146
  json: {
34134
34147
  type: "boolean",
34135
34148
  description: "Output result as JSON"
@@ -34138,6 +34151,16 @@ var startCommand3 = defineCommand({
34138
34151
  async run({ args }) {
34139
34152
  const cleoDir = args["cleo-dir"] ?? join9(homedir2(), ".cleo");
34140
34153
  const jsonMode = args.json ?? false;
34154
+ const foreground = args.foreground ?? false;
34155
+ if (foreground) {
34156
+ const projectRoot = process.cwd();
34157
+ process.stdout.write(
34158
+ `[CLEO DAEMON] Starting sentient daemon in foreground mode (PID ${process.pid})
34159
+ `
34160
+ );
34161
+ await bootstrapSentientDaemon(projectRoot);
34162
+ return;
34163
+ }
34141
34164
  try {
34142
34165
  const status = await getGCDaemonStatus(cleoDir);
34143
34166
  if (status.running && status.pid) {
@@ -34246,6 +34269,86 @@ var statusCommand4 = defineCommand({
34246
34269
  await showDaemonStatus(cleoDir, process.cwd(), args.json ?? false);
34247
34270
  }
34248
34271
  });
34272
+ var installCommand2 = defineCommand({
34273
+ meta: {
34274
+ name: "install",
34275
+ description: "Register the CLEO daemon as a user-level system service (systemd / launchd)"
34276
+ },
34277
+ args: {
34278
+ json: {
34279
+ type: "boolean",
34280
+ description: "Output result as JSON"
34281
+ }
34282
+ },
34283
+ async run({ args }) {
34284
+ const jsonMode = args.json ?? false;
34285
+ try {
34286
+ const scriptPath = resolveDaemonInstallerScript();
34287
+ const { installDaemonService } = await import(scriptPath);
34288
+ await installDaemonService();
34289
+ const result = {
34290
+ success: true,
34291
+ data: {
34292
+ platform: process.platform,
34293
+ message: "Daemon service installation complete."
34294
+ }
34295
+ };
34296
+ if (jsonMode) {
34297
+ process.stdout.write(JSON.stringify(result) + "\n");
34298
+ } else {
34299
+ process.stdout.write("CLEO: Daemon service installation complete.\n");
34300
+ }
34301
+ } catch (err) {
34302
+ const message = err instanceof Error ? err.message : String(err);
34303
+ const result = { success: false, error: { code: "E_INTERNAL", message } };
34304
+ if (jsonMode) {
34305
+ process.stdout.write(JSON.stringify(result) + "\n");
34306
+ } else {
34307
+ process.stderr.write(`Error installing daemon service: ${message}
34308
+ `);
34309
+ }
34310
+ process.exit(1);
34311
+ }
34312
+ }
34313
+ });
34314
+ var uninstallCommand = defineCommand({
34315
+ meta: {
34316
+ name: "uninstall",
34317
+ description: "Disable and remove the user-level system service (systemd unit / launchd plist)"
34318
+ },
34319
+ args: {
34320
+ json: {
34321
+ type: "boolean",
34322
+ description: "Output result as JSON"
34323
+ }
34324
+ },
34325
+ async run({ args }) {
34326
+ const jsonMode = args.json ?? false;
34327
+ try {
34328
+ const scriptPath = resolveDaemonInstallerScript();
34329
+ const { uninstallDaemonService } = await import(scriptPath);
34330
+ const result = await uninstallDaemonService();
34331
+ const envelope = { success: result.success, data: result };
34332
+ if (jsonMode) {
34333
+ process.stdout.write(JSON.stringify(envelope) + "\n");
34334
+ } else {
34335
+ process.stdout.write(`CLEO: ${result.message}
34336
+ `);
34337
+ }
34338
+ if (!result.success) process.exit(1);
34339
+ } catch (err) {
34340
+ const message = err instanceof Error ? err.message : String(err);
34341
+ const result = { success: false, error: { code: "E_INTERNAL", message } };
34342
+ if (jsonMode) {
34343
+ process.stdout.write(JSON.stringify(result) + "\n");
34344
+ } else {
34345
+ process.stderr.write(`Error uninstalling daemon service: ${message}
34346
+ `);
34347
+ }
34348
+ process.exit(1);
34349
+ }
34350
+ }
34351
+ });
34249
34352
  var daemonCommand = defineCommand({
34250
34353
  meta: {
34251
34354
  name: "daemon",
@@ -34264,7 +34367,9 @@ var daemonCommand = defineCommand({
34264
34367
  subCommands: {
34265
34368
  start: startCommand3,
34266
34369
  stop: stopCommand3,
34267
- status: statusCommand4
34370
+ status: statusCommand4,
34371
+ install: installCommand2,
34372
+ uninstall: uninstallCommand
34268
34373
  },
34269
34374
  async run({ args, cmd, rawArgs }) {
34270
34375
  if (isSubCommandDispatch(rawArgs, cmd.subCommands)) return;
@@ -50243,7 +50348,7 @@ var infoCommand = defineCommand({
50243
50348
  );
50244
50349
  }
50245
50350
  });
50246
- var installCommand2 = defineCommand({
50351
+ var installCommand3 = defineCommand({
50247
50352
  meta: { name: "install", description: "Install skill to agent directory" },
50248
50353
  args: {
50249
50354
  "skill-name": {
@@ -50269,7 +50374,7 @@ var installCommand2 = defineCommand({
50269
50374
  );
50270
50375
  }
50271
50376
  });
50272
- var uninstallCommand = defineCommand({
50377
+ var uninstallCommand2 = defineCommand({
50273
50378
  meta: { name: "uninstall", description: "Uninstall a skill" },
50274
50379
  args: {
50275
50380
  "skill-name": {
@@ -50470,8 +50575,8 @@ var skillsCommand2 = defineCommand({
50470
50575
  search: searchCommand3,
50471
50576
  validate: validateCommand7,
50472
50577
  info: infoCommand,
50473
- install: installCommand2,
50474
- uninstall: uninstallCommand,
50578
+ install: installCommand3,
50579
+ uninstall: uninstallCommand2,
50475
50580
  enable: enableCommand2,
50476
50581
  disable: disableCommand2,
50477
50582
  refresh: refreshCommand,
@@ -52638,7 +52743,7 @@ Or via NodeSource: https://github.com/nodesource/distributions
52638
52743
  }
52639
52744
  }
52640
52745
  function getPackageVersion() {
52641
- const pkgPath = join19(dirname9(fileURLToPath3(import.meta.url)), "../../package.json");
52746
+ const pkgPath = join19(dirname9(fileURLToPath4(import.meta.url)), "../../package.json");
52642
52747
  const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
52643
52748
  return pkg.version;
52644
52749
  }