diff --git a/src/cli.ts b/src/cli.ts index 09a331a..7775b1f 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -514,6 +514,39 @@ program } }); +// Local - switch back to local daemon mode (removes daemonUrl/authUrl) +program + .command("local") + .description("Switch back to local daemon mode (removes remote daemon URL)") + .action(async () => { + const config = await loadConfig(); + + if (!config.daemonUrl) { + console.log("Already in local mode — no remote daemon URL is configured."); + return; + } + + const previousDaemonUrl = config.daemonUrl; + const previousAuthUrl = config.authUrl; + + const { daemonUrl: _daemonUrl, authUrl: _authUrl, ...rest } = config; + const updatedConfig: RoutstrdConfig = rest; + + await Bun.write(CONFIG_FILE, JSON.stringify(updatedConfig, null, 2)); + + console.log("Switched back to local daemon mode."); + if (previousDaemonUrl) { + console.log(` Removed remote daemon URL: ${previousDaemonUrl}`); + } + if (previousAuthUrl) { + console.log(` Removed auth proxy URL: ${previousAuthUrl}`); + } + console.log( + `\nUse 'routstrd onboard' for first time using local mode or 'routstrd start' to start the local daemon if you already are using it.`, + ); + console.log(`You can view the config file at: ${CONFIG_FILE}`); + }); + // Onboard - initialize the daemon program .command("onboard") diff --git a/src/integrations/claudecode.ts b/src/integrations/claudecode.ts index 5b4acf2..66da52a 100644 --- a/src/integrations/claudecode.ts +++ b/src/integrations/claudecode.ts @@ -27,7 +27,8 @@ export async function installClaudeCodeIntegration( settings = JSON.parse(content); } } catch (error) { - console.error(`Error reading ${configPath}, creating new one.`); + console.error(`Failed to read or parse ${configPath}; leaving it unchanged:`, error); + return; } if (!settings.env) { diff --git a/src/integrations/hermes.ts b/src/integrations/hermes.ts index f5f3a28..63706fd 100644 --- a/src/integrations/hermes.ts +++ b/src/integrations/hermes.ts @@ -99,7 +99,8 @@ export async function installHermesIntegration( content = await readFile(configPath, "utf-8"); } } catch (error) { - console.error(`Error reading ${configPath}, creating new one.`); + console.error(`Failed to read ${configPath}; leaving it unchanged:`, error); + return; } let newContent: string; diff --git a/src/integrations/openclaw.ts b/src/integrations/openclaw.ts index c0c1928..9129b88 100644 --- a/src/integrations/openclaw.ts +++ b/src/integrations/openclaw.ts @@ -67,8 +67,9 @@ export async function installOpenClawIntegration( const content = await readFile(configPath, "utf-8"); openclawConfig = JSON.parse(content) as OpenClawConfig; } - } catch { - openclawConfig = {}; + } catch (error) { + console.error(`Failed to read or parse ${configPath}; leaving it unchanged:`, error); + return; } if (!openclawConfig.models) { diff --git a/src/integrations/opencode.ts b/src/integrations/opencode.ts index 56c08f3..2bbdd13 100644 --- a/src/integrations/opencode.ts +++ b/src/integrations/opencode.ts @@ -40,8 +40,9 @@ export async function installOpencodeIntegration( } else { opencodeConfig = { provider: {} }; } - } catch { - opencodeConfig = { provider: {} }; + } catch (error) { + console.error(`Failed to read or parse ${configPath}; leaving it unchanged:`, error); + return; } if (!opencodeConfig.provider) { diff --git a/src/integrations/pi.ts b/src/integrations/pi.ts index ea19385..5715b5f 100644 --- a/src/integrations/pi.ts +++ b/src/integrations/pi.ts @@ -40,8 +40,9 @@ export async function installPiIntegration( const content = await readFile(configPath, "utf-8"); piConfig = JSON.parse(content) as PiConfig; } - } catch { - piConfig = {}; + } catch (error) { + console.error(`Failed to read or parse ${configPath}; leaving it unchanged:`, error); + return; } if (!piConfig.providers) { diff --git a/src/integrations/registry.ts b/src/integrations/registry.ts index 03efe93..b16ac5d 100644 --- a/src/integrations/registry.ts +++ b/src/integrations/registry.ts @@ -6,6 +6,8 @@ import { installOpenClawIntegration } from "./openclaw"; import { installClaudeCodeIntegration } from "./claudecode"; import { installHermesIntegration } from "./hermes"; +const HOME = process.env.HOME || process.env.USERPROFILE || ""; + export interface IntegrationConfig { clientId: string; name: string; @@ -28,27 +30,27 @@ export const CLIENT_CONFIGS: Record = { opencode: { clientId: "opencode", name: "OpenCode", - configPath: join(process.env.HOME || "", ".config/opencode/opencode.json"), + configPath: join(HOME, ".config/opencode/opencode.json"), }, "pi-agent": { clientId: "pi-agent", name: "Pi Agent", - configPath: join(process.env.HOME || "", ".pi/agent/models.json"), + configPath: join(HOME, ".pi/agent/models.json"), }, openclaw: { clientId: "openclaw", name: "OpenClaw", - configPath: join(process.env.HOME || "", ".openclaw/openclaw.json"), + configPath: join(HOME, ".openclaw/openclaw.json"), }, "claude-code": { clientId: "claude-code", name: "Claude Code", - configPath: join(process.env.HOME || "", ".claude/settings.json"), + configPath: join(HOME, ".claude/settings.json"), }, hermes: { clientId: "hermes", name: "Hermes", - configPath: join(process.env.HOME || "", ".hermes/config.yaml"), + configPath: join(HOME, ".hermes/config.yaml"), }, };