From 471196dc2ea9121b73f74e843820143d7799d35f Mon Sep 17 00:00:00 2001 From: clagentic <10177887+akuehner@users.noreply.github.com> Date: Tue, 9 Jun 2026 17:56:40 -0400 Subject: [PATCH] fix(daemon): bootstrap minimal config on fresh install, ensureConfigDir at startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On a systemd/supervisor-driven start with no prior CLI run, daemon.json may not exist. Previously this hit process.exit(1) before any dirs were created or the socket was bound — crash-loop with no recovery path. Two fixes: - ensureConfigDir() moved to daemon startup (before config read) so dirs always exist regardless of launch path - Missing daemon.json (ENOENT) now bootstraps minimal defaults and writes the file rather than hard-exiting; other read errors still exit Co-Authored-By: Claude Sonnet 4.6 --- lib/daemon.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/daemon.js b/lib/daemon.js index 817190a..3a8c7c4 100644 --- a/lib/daemon.js +++ b/lib/daemon.js @@ -36,11 +36,24 @@ var daemonVersion = require("../package.json").version; var configFile = process.env.CLAGENTIC_CONFIG || process.env.CLAY_CONFIG || require("./config").configPath(); var config; +// Ensure dirs exist before any file access — daemon must be self-sufficient when +// launched directly by systemd/supervisor with no prior CLI run. +ensureConfigDir(); + try { config = JSON.parse(fs.readFileSync(configFile, "utf8")); } catch (e) { - console.error("[daemon] Failed to read config:", e.message); - process.exit(1); + if (e.code === "ENOENT") { + // No config file yet (fresh install, systemd-only start). Bootstrap minimal defaults. + console.warn("[daemon] No config file found at " + configFile + " — bootstrapping defaults. Run clagentic-console to configure projects."); + var _isDev = !!(process.env.CLAGENTIC_DEV || process.env.CLAY_DEV); + config = { port: _isDev ? 2635 : 2633, projects: [], mode: "single", setupCompleted: false }; + // Persist so subsequent reads succeed. + fs.writeFileSync(configFile, JSON.stringify(config, null, 2), { mode: 0o600 }); + } else { + console.error("[daemon] Failed to read config:", e.message); + process.exit(1); + } } console.log("[daemon] v" + daemonVersion + " PID " + process.pid + " config " + configFile); @@ -1150,9 +1163,6 @@ if (existingConfig && existingConfig.pid && existingConfig.pid !== process.pid) clearStaleConfig(); } } -// Ensure config dirs exist before binding the socket. The daemon may start -// without a prior CLI invocation (systemd, supervisor), so it must be self-sufficient. -ensureConfigDir(); var ipc = createIPCServer(socketPath(), function (msg) { console.log("[daemon] IPC:", msg.cmd); switch (msg.cmd) {