chore: align with moltbot rename (upstream moltbot/moltbot)

- package.json: name moltbot, bin moltbot + clawdbot (compat shim)
- paths.ts: MOLTBOT_* preferred, CLAWDBOT_* legacy; default ~/.clawdbot; config moltbot.json; export STATE_DIR/CONFIG_PATH
- render.yaml: service name moltbot, disk moltbot-data; CLAWDBOT_* env vars and /data/.clawdbot (match upstream)
- render-start.sh: support CLAWDBOT_* and MOLTBOT_* for state/token; write moltbot.json
- Dockerfile: MOLTBOT_DOCKER_APT_PACKAGES, MOLTBOT_PREFER_PNPM
- config/io.ts: MOLTBOT_* env for gateway token and config cache
- Replace STATE_DIR_CLAWDBOT/CONFIG_PATH_CLAWDBOT with STATE_DIR_MOLTBOT/CONFIG_PATH_MOLTBOT across src; paths exports both for compat
This commit is contained in:
Ojus Save 2026-01-27 09:38:28 -08:00
parent ed70785316
commit 3518abc344
37 changed files with 227 additions and 178 deletions

View File

@ -8,10 +8,10 @@ RUN corepack enable
WORKDIR /app WORKDIR /app
ARG CLAWDBOT_DOCKER_APT_PACKAGES="" ARG MOLTBOT_DOCKER_APT_PACKAGES=""
RUN if [ -n "$CLAWDBOT_DOCKER_APT_PACKAGES" ]; then \ RUN if [ -n "$MOLTBOT_DOCKER_APT_PACKAGES" ]; then \
apt-get update && \ apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $CLAWDBOT_DOCKER_APT_PACKAGES && \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $MOLTBOT_DOCKER_APT_PACKAGES && \
apt-get clean && \ apt-get clean && \
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \ rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
fi fi
@ -28,7 +28,7 @@ RUN pnpm install --frozen-lockfile
COPY . . COPY . .
RUN pnpm build RUN pnpm build
# Force pnpm for UI build (Bun may fail on ARM/Synology architectures) # Force pnpm for UI build (Bun may fail on ARM/Synology architectures)
ENV CLAWDBOT_PREFER_PNPM=1 ENV MOLTBOT_PREFER_PNPM=1
RUN pnpm ui:install RUN pnpm ui:install
RUN pnpm ui:build RUN pnpm ui:build

View File

@ -1,5 +1,5 @@
{ {
"name": "clawdbot", "name": "moltbot",
"version": "2026.1.25", "version": "2026.1.25",
"description": "WhatsApp gateway CLI (Baileys web) with Pi RPC agent", "description": "WhatsApp gateway CLI (Baileys web) with Pi RPC agent",
"type": "module", "type": "module",
@ -10,6 +10,7 @@
"./plugin-sdk/*": "./dist/plugin-sdk/*" "./plugin-sdk/*": "./dist/plugin-sdk/*"
}, },
"bin": { "bin": {
"moltbot": "dist/entry.js",
"clawdbot": "dist/entry.js" "clawdbot": "dist/entry.js"
}, },
"files": [ "files": [

View File

@ -1,6 +1,6 @@
services: services:
- type: web - type: web
name: clawdbot name: moltbot
runtime: docker runtime: docker
plan: starter plan: starter
dockerCommand: /bin/sh scripts/render-start.sh dockerCommand: /bin/sh scripts/render-start.sh
@ -34,6 +34,6 @@ services:
- key: DEEPGRAM_API_KEY - key: DEEPGRAM_API_KEY
sync: false sync: false
disk: disk:
name: clawdbot-data name: moltbot-data
mountPath: /data mountPath: /data
sizeGB: 1 sizeGB: 1

View File

@ -5,6 +5,7 @@
echo "=== Render startup script ===" echo "=== Render startup script ==="
echo "HOME=${HOME:-not set}" echo "HOME=${HOME:-not set}"
echo "CLAWDBOT_STATE_DIR=${CLAWDBOT_STATE_DIR:-not set}" echo "CLAWDBOT_STATE_DIR=${CLAWDBOT_STATE_DIR:-not set}"
echo "MOLTBOT_STATE_DIR=${MOLTBOT_STATE_DIR:-not set}"
echo "User: $(whoami 2>/dev/null || echo unknown)" echo "User: $(whoami 2>/dev/null || echo unknown)"
echo "UID: $(id -u 2>/dev/null || echo unknown)" echo "UID: $(id -u 2>/dev/null || echo unknown)"
echo "PWD: $(pwd)" echo "PWD: $(pwd)"
@ -19,29 +20,30 @@ if [ -z "${HOME}" ]; then
echo "Set HOME to: ${HOME}" echo "Set HOME to: ${HOME}"
fi fi
# Use CLAWDBOT_STATE_DIR if set and writable, otherwise use HOME/.clawdbot # Prefer MOLTBOT_STATE_DIR or CLAWDBOT_STATE_DIR (legacy), else HOME/.moltbot then HOME/.clawdbot
CONFIG_DIR="${HOME}/.clawdbot" CONFIG_DIR="${HOME}/.moltbot"
if [ -n "${CLAWDBOT_STATE_DIR}" ]; then for var in MOLTBOT_STATE_DIR CLAWDBOT_STATE_DIR; do
# Test if we can write to it (disable exit on error for this test) eval "val=\${${var}:-}"
set +e if [ -n "$val" ]; then
mkdir -p "${CLAWDBOT_STATE_DIR}" 2>/dev/null set +e
touch "${CLAWDBOT_STATE_DIR}/.test" 2>/dev/null mkdir -p "$val" 2>/dev/null
if [ $? -eq 0 ]; then touch "$val/.test" 2>/dev/null
rm -f "${CLAWDBOT_STATE_DIR}/.test" 2>/dev/null if [ $? -eq 0 ]; then
CONFIG_DIR="${CLAWDBOT_STATE_DIR}" rm -f "$val/.test" 2>/dev/null
echo "Using CLAWDBOT_STATE_DIR: ${CONFIG_DIR}" CONFIG_DIR="$val"
else echo "Using ${var}: ${CONFIG_DIR}"
echo "Warning: ${CLAWDBOT_STATE_DIR} not writable, using ${CONFIG_DIR}" fi
set -e
break
fi fi
set -e done
fi
CONFIG_FILE="${CONFIG_DIR}/clawdbot.json" CONFIG_FILE="${CONFIG_DIR}/moltbot.json"
echo "Config dir: ${CONFIG_DIR}" echo "Config dir: ${CONFIG_DIR}"
echo "Config file: ${CONFIG_FILE}" echo "Config file: ${CONFIG_FILE}"
# Create config directory (this should always work for HOME/.clawdbot) # Create config directory (fallback: HOME/.moltbot or HOME/.clawdbot)
if ! mkdir -p "${CONFIG_DIR}" 2>/dev/null; then if ! mkdir -p "${CONFIG_DIR}" 2>/dev/null; then
echo "ERROR: Failed to create config directory: ${CONFIG_DIR}" echo "ERROR: Failed to create config directory: ${CONFIG_DIR}"
exit 1 exit 1
@ -73,14 +75,17 @@ if [ ! -f "${CONFIG_FILE}" ]; then
exit 1 exit 1
fi fi
# Set environment variables for gateway # Set environment variables for gateway (app accepts MOLTBOT_* or CLAWDBOT_*)
export CLAWDBOT_STATE_DIR="${CONFIG_DIR}" export CLAWDBOT_STATE_DIR="${CONFIG_DIR}"
export CLAWDBOT_CONFIG_PATH="${CONFIG_FILE}" export CLAWDBOT_CONFIG_PATH="${CONFIG_FILE}"
export CLAWDBOT_CONFIG_CACHE_MS=0 export CLAWDBOT_CONFIG_CACHE_MS=0
export MOLTBOT_STATE_DIR="${CONFIG_DIR}"
export MOLTBOT_CONFIG_PATH="${CONFIG_FILE}"
export MOLTBOT_CONFIG_CACHE_MS=0
echo "=== Starting gateway ===" echo "=== Starting gateway ==="
echo "CLAWDBOT_STATE_DIR=${CLAWDBOT_STATE_DIR}" echo "CONFIG_DIR=${CONFIG_DIR}"
echo "CLAWDBOT_CONFIG_PATH=${CLAWDBOT_CONFIG_PATH}" echo "CONFIG_FILE=${CONFIG_FILE}"
# Verify node is available # Verify node is available
if ! command -v node >/dev/null 2>&1; then if ! command -v node >/dev/null 2>&1; then
@ -103,13 +108,14 @@ fi
echo "Found dist/index.js" echo "Found dist/index.js"
# Check if token is set # Token: CLAWDBOT_GATEWAY_TOKEN (legacy) or MOLTBOT_GATEWAY_TOKEN
if [ -z "${CLAWDBOT_GATEWAY_TOKEN}" ]; then GATEWAY_TOKEN="${CLAWDBOT_GATEWAY_TOKEN:-${MOLTBOT_GATEWAY_TOKEN}}"
echo "ERROR: CLAWDBOT_GATEWAY_TOKEN is not set" if [ -z "${GATEWAY_TOKEN}" ]; then
echo "ERROR: CLAWDBOT_GATEWAY_TOKEN or MOLTBOT_GATEWAY_TOKEN must be set"
exit 1 exit 1
fi fi
echo "Token is set (length: ${#CLAWDBOT_GATEWAY_TOKEN})" echo "Token is set (length: ${#GATEWAY_TOKEN})"
# Enable strict error handling for the final exec # Enable strict error handling for the final exec
set -e set -e
@ -120,5 +126,5 @@ exec node dist/index.js gateway \
--port 8080 \ --port 8080 \
--bind lan \ --bind lan \
--auth token \ --auth token \
--token "${CLAWDBOT_GATEWAY_TOKEN}" \ --token "${GATEWAY_TOKEN}" \
--allow-unconfigured --allow-unconfigured

View File

@ -2,9 +2,9 @@ import os from "node:os";
import path from "node:path"; import path from "node:path";
import { CHANNEL_IDS } from "../../channels/registry.js"; import { CHANNEL_IDS } from "../../channels/registry.js";
import { STATE_DIR_CLAWDBOT } from "../../config/config.js"; import { STATE_DIR_MOLTBOT } from "../../config/config.js";
export const DEFAULT_SANDBOX_WORKSPACE_ROOT = path.join(os.homedir(), ".clawdbot", "sandboxes"); export const DEFAULT_SANDBOX_WORKSPACE_ROOT = path.join(os.homedir(), ".moltbot", "sandboxes");
export const DEFAULT_SANDBOX_IMAGE = "clawdbot-sandbox:bookworm-slim"; export const DEFAULT_SANDBOX_IMAGE = "clawdbot-sandbox:bookworm-slim";
export const DEFAULT_SANDBOX_CONTAINER_PREFIX = "clawdbot-sbx-"; export const DEFAULT_SANDBOX_CONTAINER_PREFIX = "clawdbot-sbx-";
@ -48,7 +48,7 @@ export const DEFAULT_SANDBOX_BROWSER_AUTOSTART_TIMEOUT_MS = 12_000;
export const SANDBOX_AGENT_WORKSPACE_MOUNT = "/agent"; export const SANDBOX_AGENT_WORKSPACE_MOUNT = "/agent";
const resolvedSandboxStateDir = STATE_DIR_CLAWDBOT ?? path.join(os.homedir(), ".clawdbot"); const resolvedSandboxStateDir = STATE_DIR_MOLTBOT ?? path.join(os.homedir(), ".moltbot");
export const SANDBOX_STATE_DIR = path.join(resolvedSandboxStateDir, "sandbox"); export const SANDBOX_STATE_DIR = path.join(resolvedSandboxStateDir, "sandbox");
export const SANDBOX_REGISTRY_PATH = path.join(SANDBOX_STATE_DIR, "containers.json"); export const SANDBOX_REGISTRY_PATH = path.join(SANDBOX_STATE_DIR, "containers.json");
export const SANDBOX_BROWSER_REGISTRY_PATH = path.join(SANDBOX_STATE_DIR, "browsers.json"); export const SANDBOX_BROWSER_REGISTRY_PATH = path.join(SANDBOX_STATE_DIR, "browsers.json");

View File

@ -1,6 +1,6 @@
import path from "node:path"; import path from "node:path";
import { STATE_DIR_CLAWDBOT } from "../config/paths.js"; import { STATE_DIR_MOLTBOT } from "../config/paths.js";
import { loadJsonFile, saveJsonFile } from "../infra/json-file.js"; import { loadJsonFile, saveJsonFile } from "../infra/json-file.js";
import { normalizeDeliveryContext } from "../utils/delivery-context.js"; import { normalizeDeliveryContext } from "../utils/delivery-context.js";
import type { SubagentRunRecord } from "./subagent-registry.js"; import type { SubagentRunRecord } from "./subagent-registry.js";
@ -31,7 +31,7 @@ type LegacySubagentRunRecord = PersistedSubagentRunRecord & {
}; };
export function resolveSubagentRegistryPath(): string { export function resolveSubagentRegistryPath(): string {
return path.join(STATE_DIR_CLAWDBOT, "subagents", "runs.json"); return path.join(STATE_DIR_MOLTBOT, "subagents", "runs.json");
} }
export function loadSubagentRegistryFromDisk(): Map<string, SubagentRunRecord> { export function loadSubagentRegistryFromDisk(): Map<string, SubagentRunRecord> {

View File

@ -4,7 +4,7 @@ import { fileURLToPath } from "node:url";
import type { Command } from "commander"; import type { Command } from "commander";
import { STATE_DIR_CLAWDBOT } from "../config/paths.js"; import { STATE_DIR_MOLTBOT } from "../config/paths.js";
import { danger, info } from "../globals.js"; import { danger, info } from "../globals.js";
import { copyToClipboard } from "../infra/clipboard.js"; import { copyToClipboard } from "../infra/clipboard.js";
import { defaultRuntime } from "../runtime.js"; import { defaultRuntime } from "../runtime.js";
@ -20,7 +20,7 @@ function bundledExtensionRootDir() {
} }
function installedExtensionRootDir() { function installedExtensionRootDir() {
return path.join(STATE_DIR_CLAWDBOT, "browser", "chrome-extension"); return path.join(STATE_DIR_MOLTBOT, "browser", "chrome-extension");
} }
function hasManifest(dir: string) { function hasManifest(dir: string) {
@ -36,7 +36,7 @@ export async function installChromeExtension(opts?: {
throw new Error("Bundled Chrome extension is missing. Reinstall Clawdbot and try again."); throw new Error("Bundled Chrome extension is missing. Reinstall Clawdbot and try again.");
} }
const stateDir = opts?.stateDir ?? STATE_DIR_CLAWDBOT; const stateDir = opts?.stateDir ?? STATE_DIR_MOLTBOT;
const dest = path.join(stateDir, "browser", "chrome-extension"); const dest = path.join(stateDir, "browser", "chrome-extension");
fs.mkdirSync(path.dirname(dest), { recursive: true }); fs.mkdirSync(path.dirname(dest), { recursive: true });

View File

@ -4,7 +4,7 @@ import path from "node:path";
import { resolveDefaultAgentWorkspaceDir } from "../../agents/workspace.js"; import { resolveDefaultAgentWorkspaceDir } from "../../agents/workspace.js";
import { handleReset } from "../../commands/onboard-helpers.js"; import { handleReset } from "../../commands/onboard-helpers.js";
import { CONFIG_PATH_CLAWDBOT, writeConfigFile } from "../../config/config.js"; import { CONFIG_PATH_MOLTBOT, writeConfigFile } from "../../config/config.js";
import { defaultRuntime } from "../../runtime.js"; import { defaultRuntime } from "../../runtime.js";
import { resolveUserPath, shortenHomePath } from "../../utils.js"; import { resolveUserPath, shortenHomePath } from "../../utils.js";
@ -89,7 +89,7 @@ export async function ensureDevGatewayConfig(opts: { reset?: boolean }) {
await handleReset("full", workspace, defaultRuntime); await handleReset("full", workspace, defaultRuntime);
} }
const configExists = fs.existsSync(CONFIG_PATH_CLAWDBOT); const configExists = fs.existsSync(CONFIG_PATH_MOLTBOT);
if (!opts.reset && configExists) return; if (!opts.reset && configExists) return;
await writeConfigFile({ await writeConfigFile({
@ -117,6 +117,6 @@ export async function ensureDevGatewayConfig(opts: { reset?: boolean }) {
}, },
}); });
await ensureDevWorkspace(workspace); await ensureDevWorkspace(workspace);
defaultRuntime.log(`Dev config ready: ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`); defaultRuntime.log(`Dev config ready: ${shortenHomePath(CONFIG_PATH_MOLTBOT)}`);
defaultRuntime.log(`Dev workspace ready: ${shortenHomePath(resolveUserPath(workspace))}`); defaultRuntime.log(`Dev workspace ready: ${shortenHomePath(resolveUserPath(workspace))}`);
} }

View File

@ -3,7 +3,7 @@ import fs from "node:fs";
import type { Command } from "commander"; import type { Command } from "commander";
import type { GatewayAuthMode } from "../../config/config.js"; import type { GatewayAuthMode } from "../../config/config.js";
import { import {
CONFIG_PATH_CLAWDBOT, CONFIG_PATH_MOLTBOT,
loadConfig, loadConfig,
readConfigFileSnapshot, readConfigFileSnapshot,
resolveGatewayPort, resolveGatewayPort,
@ -157,7 +157,7 @@ async function runGatewayCommand(opts: GatewayRunOpts) {
const passwordRaw = toOptionString(opts.password); const passwordRaw = toOptionString(opts.password);
const tokenRaw = toOptionString(opts.token); const tokenRaw = toOptionString(opts.token);
const configExists = fs.existsSync(CONFIG_PATH_CLAWDBOT); const configExists = fs.existsSync(CONFIG_PATH_MOLTBOT);
const mode = cfg.gateway?.mode; const mode = cfg.gateway?.mode;
if (!opts.allowUnconfigured && mode !== "local") { if (!opts.allowUnconfigured && mode !== "local") {
if (!configExists) { if (!configExists) {

View File

@ -1,7 +1,7 @@
import { getChannelPlugin, listChannelPlugins } from "../channels/plugins/index.js"; import { getChannelPlugin, listChannelPlugins } from "../channels/plugins/index.js";
import { formatCliCommand } from "../cli/command-format.js"; import { formatCliCommand } from "../cli/command-format.js";
import type { ClawdbotConfig } from "../config/config.js"; import type { ClawdbotConfig } from "../config/config.js";
import { CONFIG_PATH_CLAWDBOT } from "../config/config.js"; import { CONFIG_PATH_MOLTBOT } from "../config/config.js";
import type { RuntimeEnv } from "../runtime.js"; import type { RuntimeEnv } from "../runtime.js";
import { note } from "../terminal/note.js"; import { note } from "../terminal/note.js";
import { shortenHomePath } from "../utils.js"; import { shortenHomePath } from "../utils.js";
@ -52,7 +52,7 @@ export async function removeChannelConfigWizard(
const label = getChannelPlugin(channel)?.meta.label ?? channel; const label = getChannelPlugin(channel)?.meta.label ?? channel;
const confirmed = guardCancel( const confirmed = guardCancel(
await confirm({ await confirm({
message: `Delete ${label} configuration from ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}?`, message: `Delete ${label} configuration from ${shortenHomePath(CONFIG_PATH_MOLTBOT)}?`,
initialValue: false, initialValue: false,
}), }),
runtime, runtime,

View File

@ -30,7 +30,7 @@ vi.mock("@clack/prompts", () => ({
})); }));
vi.mock("../config/config.js", () => ({ vi.mock("../config/config.js", () => ({
CONFIG_PATH_CLAWDBOT: "~/.clawdbot/clawdbot.json", CONFIG_PATH_MOLTBOT: "~/.moltbot/moltbot.json",
readConfigFileSnapshot: mocks.readConfigFileSnapshot, readConfigFileSnapshot: mocks.readConfigFileSnapshot,
writeConfigFile: mocks.writeConfigFile, writeConfigFile: mocks.writeConfigFile,
resolveGatewayPort: mocks.resolveGatewayPort, resolveGatewayPort: mocks.resolveGatewayPort,

View File

@ -3,7 +3,7 @@ import type { ZodIssue } from "zod";
import type { ClawdbotConfig } from "../config/config.js"; import type { ClawdbotConfig } from "../config/config.js";
import { import {
ClawdbotSchema, ClawdbotSchema,
CONFIG_PATH_CLAWDBOT, CONFIG_PATH_MOLTBOT,
migrateLegacyConfig, migrateLegacyConfig,
readConfigFileSnapshot, readConfigFileSnapshot,
} from "../config/config.js"; } from "../config/config.js";
@ -214,5 +214,5 @@ export async function loadAndMaybeMigrateDoctorConfig(params: {
noteOpencodeProviderOverrides(cfg); noteOpencodeProviderOverrides(cfg);
return { cfg, path: snapshot.path ?? CONFIG_PATH_CLAWDBOT, shouldWriteConfig }; return { cfg, path: snapshot.path ?? CONFIG_PATH_MOLTBOT, shouldWriteConfig };
} }

View File

@ -34,7 +34,7 @@ beforeEach(() => {
durationMs: 0, durationMs: 0,
}); });
legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({ legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: false, exists: false,
raw: null, raw: null,
parsed: {}, parsed: {},
@ -135,7 +135,7 @@ const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {
const loadClawdbotPlugins = vi.fn().mockReturnValue({ plugins: [], diagnostics: [] }); const loadClawdbotPlugins = vi.fn().mockReturnValue({ plugins: [], diagnostics: [] });
const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({ const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: false, exists: false,
raw: null, raw: null,
parsed: {}, parsed: {},
@ -181,7 +181,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
const actual = await importOriginal(); const actual = await importOriginal();
return { return {
...actual, ...actual,
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json", CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
createConfigIO, createConfigIO,
readConfigFileSnapshot, readConfigFileSnapshot,
writeConfigFile, writeConfigFile,
@ -327,7 +327,7 @@ vi.mock("./doctor-state-migrations.js", () => ({
describe("doctor command", () => { describe("doctor command", () => {
it("runs legacy state migrations in non-interactive mode without prompting", async () => { it("runs legacy state migrations in non-interactive mode without prompting", async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},

View File

@ -34,7 +34,7 @@ beforeEach(() => {
durationMs: 0, durationMs: 0,
}); });
legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({ legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: false, exists: false,
raw: null, raw: null,
parsed: {}, parsed: {},
@ -133,7 +133,7 @@ const runCommandWithTimeout = vi.fn().mockResolvedValue({
const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} }); const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} });
const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({ const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: false, exists: false,
raw: null, raw: null,
parsed: {}, parsed: {},
@ -180,7 +180,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
const actual = await importOriginal(); const actual = await importOriginal();
return { return {
...actual, ...actual,
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json", CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
createConfigIO, createConfigIO,
readConfigFileSnapshot, readConfigFileSnapshot,
writeConfigFile, writeConfigFile,
@ -326,7 +326,7 @@ vi.mock("./doctor-state-migrations.js", () => ({
describe("doctor command", () => { describe("doctor command", () => {
it("migrates routing.allowFrom to channels.whatsapp.allowFrom", { timeout: 60_000 }, async () => { it("migrates routing.allowFrom to channels.whatsapp.allowFrom", { timeout: 60_000 }, async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: { routing: { allowFrom: ["+15555550123"] } }, parsed: { routing: { allowFrom: ["+15555550123"] } },
@ -370,7 +370,7 @@ describe("doctor command", () => {
it("migrates legacy gateway services", { timeout: 60_000 }, async () => { it("migrates legacy gateway services", { timeout: 60_000 }, async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},
@ -424,7 +424,7 @@ describe("doctor command", () => {
}); });
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},

View File

@ -34,7 +34,7 @@ beforeEach(() => {
durationMs: 0, durationMs: 0,
}); });
legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({ legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: false, exists: false,
raw: null, raw: null,
parsed: {}, parsed: {},
@ -133,7 +133,7 @@ const runCommandWithTimeout = vi.fn().mockResolvedValue({
const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} }); const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} });
const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({ const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: false, exists: false,
raw: null, raw: null,
parsed: {}, parsed: {},
@ -180,7 +180,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
const actual = await importOriginal(); const actual = await importOriginal();
return { return {
...actual, ...actual,
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json", CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
createConfigIO, createConfigIO,
readConfigFileSnapshot, readConfigFileSnapshot,
writeConfigFile, writeConfigFile,
@ -326,7 +326,7 @@ vi.mock("./doctor-state-migrations.js", () => ({
describe("doctor command", () => { describe("doctor command", () => {
it("runs legacy state migrations in yes mode without prompting", async () => { it("runs legacy state migrations in yes mode without prompting", async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},
@ -385,7 +385,7 @@ describe("doctor command", () => {
it("skips gateway restarts in non-interactive mode", async () => { it("skips gateway restarts in non-interactive mode", async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},
@ -417,7 +417,7 @@ describe("doctor command", () => {
it("migrates anthropic oauth config profile id when only email profile exists", async () => { it("migrates anthropic oauth config profile id when only email profile exists", async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},

View File

@ -11,7 +11,7 @@ import {
} from "../agents/model-selection.js"; } from "../agents/model-selection.js";
import { formatCliCommand } from "../cli/command-format.js"; import { formatCliCommand } from "../cli/command-format.js";
import type { ClawdbotConfig } from "../config/config.js"; import type { ClawdbotConfig } from "../config/config.js";
import { CONFIG_PATH_CLAWDBOT, readConfigFileSnapshot, writeConfigFile } from "../config/config.js"; import { CONFIG_PATH_MOLTBOT, readConfigFileSnapshot, writeConfigFile } from "../config/config.js";
import { logConfigUpdated } from "../config/logging.js"; import { logConfigUpdated } from "../config/logging.js";
import { resolveGatewayService } from "../daemon/service.js"; import { resolveGatewayService } from "../daemon/service.js";
import { resolveGatewayAuth } from "../gateway/auth.js"; import { resolveGatewayAuth } from "../gateway/auth.js";
@ -90,7 +90,7 @@ export async function doctorCommand(
}); });
let cfg: ClawdbotConfig = configResult.cfg; let cfg: ClawdbotConfig = configResult.cfg;
const configPath = configResult.path ?? CONFIG_PATH_CLAWDBOT; const configPath = configResult.path ?? CONFIG_PATH_MOLTBOT;
if (!cfg.gateway?.mode) { if (!cfg.gateway?.mode) {
const lines = [ const lines = [
"gateway.mode is unset; gateway start will be blocked.", "gateway.mode is unset; gateway start will be blocked.",
@ -174,7 +174,7 @@ export async function doctorCommand(
} }
} }
await noteStateIntegrity(cfg, prompter, configResult.path ?? CONFIG_PATH_CLAWDBOT); await noteStateIntegrity(cfg, prompter, configResult.path ?? CONFIG_PATH_MOLTBOT);
cfg = await maybeRepairSandboxImages(cfg, runtime, prompter); cfg = await maybeRepairSandboxImages(cfg, runtime, prompter);
noteSandboxScopeWarnings(cfg); noteSandboxScopeWarnings(cfg);
@ -272,7 +272,7 @@ export async function doctorCommand(
cfg = applyWizardMetadata(cfg, { command: "doctor", mode: resolveMode(cfg) }); cfg = applyWizardMetadata(cfg, { command: "doctor", mode: resolveMode(cfg) });
await writeConfigFile(cfg); await writeConfigFile(cfg);
logConfigUpdated(runtime); logConfigUpdated(runtime);
const backupPath = `${CONFIG_PATH_CLAWDBOT}.bak`; const backupPath = `${CONFIG_PATH_MOLTBOT}.bak`;
if (fs.existsSync(backupPath)) { if (fs.existsSync(backupPath)) {
runtime.log(`Backup: ${shortenHomePath(backupPath)}`); runtime.log(`Backup: ${shortenHomePath(backupPath)}`);
} }

View File

@ -34,7 +34,7 @@ beforeEach(() => {
durationMs: 0, durationMs: 0,
}); });
legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({ legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: false, exists: false,
raw: null, raw: null,
parsed: {}, parsed: {},
@ -133,7 +133,7 @@ const runCommandWithTimeout = vi.fn().mockResolvedValue({
const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} }); const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} });
const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({ const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: false, exists: false,
raw: null, raw: null,
parsed: {}, parsed: {},
@ -180,7 +180,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
const actual = await importOriginal(); const actual = await importOriginal();
return { return {
...actual, ...actual,
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json", CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
createConfigIO, createConfigIO,
readConfigFileSnapshot, readConfigFileSnapshot,
writeConfigFile, writeConfigFile,
@ -326,7 +326,7 @@ vi.mock("./doctor-state-migrations.js", () => ({
describe("doctor command", () => { describe("doctor command", () => {
it("warns when per-agent sandbox docker/browser/prune overrides are ignored under shared scope", async () => { it("warns when per-agent sandbox docker/browser/prune overrides are ignored under shared scope", async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},
@ -383,7 +383,7 @@ describe("doctor command", () => {
it("warns when extra workspace directories exist", async () => { it("warns when extra workspace directories exist", async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},

View File

@ -34,7 +34,7 @@ beforeEach(() => {
durationMs: 0, durationMs: 0,
}); });
legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({ legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: false, exists: false,
raw: null, raw: null,
parsed: {}, parsed: {},
@ -133,7 +133,7 @@ const runCommandWithTimeout = vi.fn().mockResolvedValue({
const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} }); const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} });
const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({ const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: false, exists: false,
raw: null, raw: null,
parsed: {}, parsed: {},
@ -180,7 +180,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
const actual = await importOriginal(); const actual = await importOriginal();
return { return {
...actual, ...actual,
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json", CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
createConfigIO, createConfigIO,
readConfigFileSnapshot, readConfigFileSnapshot,
writeConfigFile, writeConfigFile,
@ -330,7 +330,7 @@ vi.mock("./doctor-update.js", () => ({
describe("doctor command", () => { describe("doctor command", () => {
it("warns when the state directory is missing", async () => { it("warns when the state directory is missing", async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},
@ -358,7 +358,7 @@ describe("doctor command", () => {
it("warns about opencode provider overrides", async () => { it("warns about opencode provider overrides", async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},
@ -392,7 +392,7 @@ describe("doctor command", () => {
it("skips gateway auth warning when CLAWDBOT_GATEWAY_TOKEN is set", async () => { it("skips gateway auth warning when CLAWDBOT_GATEWAY_TOKEN is set", async () => {
readConfigFileSnapshot.mockResolvedValue({ readConfigFileSnapshot.mockResolvedValue({
path: "/tmp/clawdbot.json", path: "/tmp/moltbot.json",
exists: true, exists: true,
raw: "{}", raw: "{}",
parsed: {}, parsed: {},

View File

@ -17,8 +17,8 @@ const discoverAuthStorage = vi.fn().mockReturnValue({});
const discoverModels = vi.fn(); const discoverModels = vi.fn();
vi.mock("../config/config.js", () => ({ vi.mock("../config/config.js", () => ({
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json", CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
STATE_DIR_CLAWDBOT: "/tmp/clawdbot-state", STATE_DIR_MOLTBOT: "/tmp/moltbot-state",
loadConfig, loadConfig,
})); }));

View File

@ -5,7 +5,7 @@ const writeConfigFile = vi.fn().mockResolvedValue(undefined);
const loadConfig = vi.fn().mockReturnValue({}); const loadConfig = vi.fn().mockReturnValue({});
vi.mock("../config/config.js", () => ({ vi.mock("../config/config.js", () => ({
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json", CONFIG_PATH_MOLTBOT: "/tmp/clawdbot.json",
readConfigFileSnapshot, readConfigFileSnapshot,
writeConfigFile, writeConfigFile,
loadConfig, loadConfig,

View File

@ -17,7 +17,7 @@ import {
resolveConfiguredModelRef, resolveConfiguredModelRef,
resolveModelRefFromString, resolveModelRefFromString,
} from "../../agents/model-selection.js"; } from "../../agents/model-selection.js";
import { CONFIG_PATH_CLAWDBOT, loadConfig } from "../../config/config.js"; import { CONFIG_PATH_MOLTBOT, loadConfig } from "../../config/config.js";
import { getShellEnvAppliedKeys, shouldEnableShellEnvFallback } from "../../infra/shell-env.js"; import { getShellEnvAppliedKeys, shouldEnableShellEnvFallback } from "../../infra/shell-env.js";
import { withProgressTotals } from "../../cli/progress.js"; import { withProgressTotals } from "../../cli/progress.js";
import { import {
@ -294,7 +294,7 @@ export async function modelsStatusCommand(
runtime.log( runtime.log(
JSON.stringify( JSON.stringify(
{ {
configPath: CONFIG_PATH_CLAWDBOT, configPath: CONFIG_PATH_MOLTBOT,
agentDir, agentDir,
defaultModel: defaultLabel, defaultModel: defaultLabel,
resolvedDefault: resolvedLabel, resolvedDefault: resolvedLabel,
@ -341,7 +341,7 @@ export async function modelsStatusCommand(
rawModel && rawModel !== resolvedLabel ? `${resolvedLabel} (from ${rawModel})` : resolvedLabel; rawModel && rawModel !== resolvedLabel ? `${resolvedLabel} (from ${rawModel})` : resolvedLabel;
runtime.log( runtime.log(
`${label("Config")}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.info, shortenHomePath(CONFIG_PATH_CLAWDBOT))}`, `${label("Config")}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.info, shortenHomePath(CONFIG_PATH_MOLTBOT))}`,
); );
runtime.log( runtime.log(
`${label("Agent dir")}${colorize(rich, theme.muted, ":")} ${colorize( `${label("Agent dir")}${colorize(rich, theme.muted, ":")} ${colorize(

View File

@ -7,7 +7,7 @@ import { cancel, isCancel } from "@clack/prompts";
import { DEFAULT_AGENT_WORKSPACE_DIR, ensureAgentWorkspace } from "../agents/workspace.js"; import { DEFAULT_AGENT_WORKSPACE_DIR, ensureAgentWorkspace } from "../agents/workspace.js";
import type { ClawdbotConfig } from "../config/config.js"; import type { ClawdbotConfig } from "../config/config.js";
import { CONFIG_PATH_CLAWDBOT } from "../config/config.js"; import { CONFIG_PATH_MOLTBOT } from "../config/config.js";
import { resolveSessionTranscriptsDirForAgent } from "../config/sessions.js"; import { resolveSessionTranscriptsDirForAgent } from "../config/sessions.js";
import { callGateway } from "../gateway/call.js"; import { callGateway } from "../gateway/call.js";
import { normalizeControlUiBasePath } from "../gateway/control-ui-shared.js"; import { normalizeControlUiBasePath } from "../gateway/control-ui-shared.js";
@ -274,7 +274,7 @@ export async function moveToTrash(pathname: string, runtime: RuntimeEnv): Promis
} }
export async function handleReset(scope: ResetScope, workspaceDir: string, runtime: RuntimeEnv) { export async function handleReset(scope: ResetScope, workspaceDir: string, runtime: RuntimeEnv) {
await moveToTrash(CONFIG_PATH_CLAWDBOT, runtime); await moveToTrash(CONFIG_PATH_MOLTBOT, runtime);
if (scope === "config") return; if (scope === "config") return;
await moveToTrash(path.join(CONFIG_DIR, "credentials"), runtime); await moveToTrash(path.join(CONFIG_DIR, "credentials"), runtime);
await moveToTrash(resolveSessionTranscriptsDirForAgent(), runtime); await moveToTrash(resolveSessionTranscriptsDirForAgent(), runtime);

View File

@ -56,8 +56,8 @@ describe("onboard (non-interactive): Vercel AI Gateway", () => {
runtime, runtime,
); );
const { CONFIG_PATH_CLAWDBOT } = await import("../config/config.js"); const { CONFIG_PATH_MOLTBOT } = await import("../config/config.js");
const cfg = JSON.parse(await fs.readFile(CONFIG_PATH_CLAWDBOT, "utf8")) as { const cfg = JSON.parse(await fs.readFile(CONFIG_PATH_MOLTBOT, "utf8")) as {
auth?: { auth?: {
profiles?: Record<string, { provider?: string; mode?: string }>; profiles?: Record<string, { provider?: string; mode?: string }>;
}; };

View File

@ -59,8 +59,8 @@ describe("onboard (non-interactive): token auth", () => {
runtime, runtime,
); );
const { CONFIG_PATH_CLAWDBOT } = await import("../config/config.js"); const { CONFIG_PATH_MOLTBOT } = await import("../config/config.js");
const cfg = JSON.parse(await fs.readFile(CONFIG_PATH_CLAWDBOT, "utf8")) as { const cfg = JSON.parse(await fs.readFile(CONFIG_PATH_MOLTBOT, "utf8")) as {
auth?: { auth?: {
profiles?: Record<string, { provider?: string; mode?: string }>; profiles?: Record<string, { provider?: string; mode?: string }>;
}; };

View File

@ -3,7 +3,7 @@ import fs from "node:fs/promises";
import JSON5 from "json5"; import JSON5 from "json5";
import { DEFAULT_AGENT_WORKSPACE_DIR, ensureAgentWorkspace } from "../agents/workspace.js"; import { DEFAULT_AGENT_WORKSPACE_DIR, ensureAgentWorkspace } from "../agents/workspace.js";
import { type ClawdbotConfig, CONFIG_PATH_CLAWDBOT, writeConfigFile } from "../config/config.js"; import { type ClawdbotConfig, CONFIG_PATH_MOLTBOT, writeConfigFile } from "../config/config.js";
import { formatConfigPath, logConfigUpdated } from "../config/logging.js"; import { formatConfigPath, logConfigUpdated } from "../config/logging.js";
import { resolveSessionTranscriptsDir } from "../config/sessions.js"; import { resolveSessionTranscriptsDir } from "../config/sessions.js";
import type { RuntimeEnv } from "../runtime.js"; import type { RuntimeEnv } from "../runtime.js";
@ -15,7 +15,7 @@ async function readConfigFileRaw(): Promise<{
parsed: ClawdbotConfig; parsed: ClawdbotConfig;
}> { }> {
try { try {
const raw = await fs.readFile(CONFIG_PATH_CLAWDBOT, "utf-8"); const raw = await fs.readFile(CONFIG_PATH_MOLTBOT, "utf-8");
const parsed = JSON5.parse(raw); const parsed = JSON5.parse(raw);
if (parsed && typeof parsed === "object") { if (parsed && typeof parsed === "object") {
return { exists: true, parsed: parsed as ClawdbotConfig }; return { exists: true, parsed: parsed as ClawdbotConfig };

View File

@ -35,56 +35,56 @@ describe("Nix integration (U3, U5, U9)", () => {
}); });
describe("U5: CONFIG_PATH and STATE_DIR env var overrides", () => { describe("U5: CONFIG_PATH and STATE_DIR env var overrides", () => {
it("STATE_DIR_CLAWDBOT defaults to ~/.clawdbot when env not set", async () => { it("STATE_DIR_MOLTBOT defaults to ~/.moltbot when env not set", async () => {
await withEnvOverride({ CLAWDBOT_STATE_DIR: undefined }, async () => { await withEnvOverride({ MOLTBOT_STATE_DIR: undefined }, async () => {
const { STATE_DIR_CLAWDBOT } = await import("./config.js"); const { STATE_DIR_MOLTBOT } = await import("./config.js");
expect(STATE_DIR_CLAWDBOT).toMatch(/\.clawdbot$/); expect(STATE_DIR_MOLTBOT).toMatch(/\.moltbot$/);
}); });
}); });
it("STATE_DIR_CLAWDBOT respects CLAWDBOT_STATE_DIR override", async () => { it("STATE_DIR_MOLTBOT respects MOLTBOT_STATE_DIR override", async () => {
await withEnvOverride({ CLAWDBOT_STATE_DIR: "/custom/state/dir" }, async () => { await withEnvOverride({ MOLTBOT_STATE_DIR: "/custom/state/dir" }, async () => {
const { STATE_DIR_CLAWDBOT } = await import("./config.js"); const { STATE_DIR_MOLTBOT } = await import("./config.js");
expect(STATE_DIR_CLAWDBOT).toBe(path.resolve("/custom/state/dir")); expect(STATE_DIR_MOLTBOT).toBe(path.resolve("/custom/state/dir"));
}); });
}); });
it("CONFIG_PATH_CLAWDBOT defaults to ~/.clawdbot/clawdbot.json when env not set", async () => { it("CONFIG_PATH_MOLTBOT defaults to ~/.moltbot/moltbot.json when env not set", async () => {
await withEnvOverride( await withEnvOverride(
{ CLAWDBOT_CONFIG_PATH: undefined, CLAWDBOT_STATE_DIR: undefined }, { MOLTBOT_CONFIG_PATH: undefined, MOLTBOT_STATE_DIR: undefined },
async () => { async () => {
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js"); const { CONFIG_PATH_MOLTBOT } = await import("./config.js");
expect(CONFIG_PATH_CLAWDBOT).toMatch(/\.clawdbot[\\/]clawdbot\.json$/); expect(CONFIG_PATH_MOLTBOT).toMatch(/\.moltbot[\\/]clawdbot\.json$/);
}, },
); );
}); });
it("CONFIG_PATH_CLAWDBOT respects CLAWDBOT_CONFIG_PATH override", async () => { it("CONFIG_PATH_MOLTBOT respects MOLTBOT_CONFIG_PATH override", async () => {
await withEnvOverride({ CLAWDBOT_CONFIG_PATH: "/nix/store/abc/clawdbot.json" }, async () => { await withEnvOverride({ MOLTBOT_CONFIG_PATH: "/nix/store/abc/moltbot.json" }, async () => {
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js"); const { CONFIG_PATH_MOLTBOT } = await import("./config.js");
expect(CONFIG_PATH_CLAWDBOT).toBe(path.resolve("/nix/store/abc/clawdbot.json")); expect(CONFIG_PATH_MOLTBOT).toBe(path.resolve("/nix/store/abc/moltbot.json"));
}); });
}); });
it("CONFIG_PATH_CLAWDBOT expands ~ in CLAWDBOT_CONFIG_PATH override", async () => { it("CONFIG_PATH_MOLTBOT expands ~ in MOLTBOT_CONFIG_PATH override", async () => {
await withTempHome(async (home) => { await withTempHome(async (home) => {
await withEnvOverride({ CLAWDBOT_CONFIG_PATH: "~/.clawdbot/custom.json" }, async () => { await withEnvOverride({ MOLTBOT_CONFIG_PATH: "~/.moltbot/custom.json" }, async () => {
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js"); const { CONFIG_PATH_MOLTBOT } = await import("./config.js");
expect(CONFIG_PATH_CLAWDBOT).toBe(path.join(home, ".clawdbot", "custom.json")); expect(CONFIG_PATH_MOLTBOT).toBe(path.join(home, ".moltbot", "custom.json"));
}); });
}); });
}); });
it("CONFIG_PATH_CLAWDBOT uses STATE_DIR_CLAWDBOT when only state dir is overridden", async () => { it("CONFIG_PATH_MOLTBOT uses STATE_DIR_MOLTBOT when only state dir is overridden", async () => {
await withEnvOverride( await withEnvOverride(
{ {
CLAWDBOT_CONFIG_PATH: undefined, MOLTBOT_CONFIG_PATH: undefined,
CLAWDBOT_STATE_DIR: "/custom/state", MOLTBOT_STATE_DIR: "/custom/state",
}, },
async () => { async () => {
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js"); const { CONFIG_PATH_MOLTBOT } = await import("./config.js");
expect(CONFIG_PATH_CLAWDBOT).toBe( expect(CONFIG_PATH_MOLTBOT).toBe(
path.join(path.resolve("/custom/state"), "clawdbot.json"), path.join(path.resolve("/custom/state"), "moltbot.json"),
); );
}, },
); );
@ -94,7 +94,7 @@ describe("Nix integration (U3, U5, U9)", () => {
describe("U5b: tilde expansion for config paths", () => { describe("U5b: tilde expansion for config paths", () => {
it("expands ~ in common path-ish config fields", async () => { it("expands ~ in common path-ish config fields", async () => {
await withTempHome(async (home) => { await withTempHome(async (home) => {
const configDir = path.join(home, ".clawdbot"); const configDir = path.join(home, ".moltbot");
await fs.mkdir(configDir, { recursive: true }); await fs.mkdir(configDir, { recursive: true });
const pluginDir = path.join(home, "plugins", "demo-plugin"); const pluginDir = path.join(home, "plugins", "demo-plugin");
await fs.mkdir(pluginDir, { recursive: true }); await fs.mkdir(pluginDir, { recursive: true });
@ -116,7 +116,7 @@ describe("Nix integration (U3, U5, U9)", () => {
"utf-8", "utf-8",
); );
await fs.writeFile( await fs.writeFile(
path.join(configDir, "clawdbot.json"), path.join(configDir, "moltbot.json"),
JSON.stringify( JSON.stringify(
{ {
plugins: { plugins: {
@ -130,7 +130,7 @@ describe("Nix integration (U3, U5, U9)", () => {
{ {
id: "main", id: "main",
workspace: "~/ws-agent", workspace: "~/ws-agent",
agentDir: "~/.clawdbot/agents/main", agentDir: "~/.moltbot/agents/main",
sandbox: { workspaceRoot: "~/sandbox-root" }, sandbox: { workspaceRoot: "~/sandbox-root" },
}, },
], ],
@ -139,7 +139,7 @@ describe("Nix integration (U3, U5, U9)", () => {
whatsapp: { whatsapp: {
accounts: { accounts: {
personal: { personal: {
authDir: "~/.clawdbot/credentials/wa-personal", authDir: "~/.moltbot/credentials/wa-personal",
}, },
}, },
}, },
@ -159,11 +159,11 @@ describe("Nix integration (U3, U5, U9)", () => {
expect(cfg.agents?.defaults?.workspace).toBe(path.join(home, "ws-default")); expect(cfg.agents?.defaults?.workspace).toBe(path.join(home, "ws-default"));
expect(cfg.agents?.list?.[0]?.workspace).toBe(path.join(home, "ws-agent")); expect(cfg.agents?.list?.[0]?.workspace).toBe(path.join(home, "ws-agent"));
expect(cfg.agents?.list?.[0]?.agentDir).toBe( expect(cfg.agents?.list?.[0]?.agentDir).toBe(
path.join(home, ".clawdbot", "agents", "main"), path.join(home, ".moltbot", "agents", "main"),
); );
expect(cfg.agents?.list?.[0]?.sandbox?.workspaceRoot).toBe(path.join(home, "sandbox-root")); expect(cfg.agents?.list?.[0]?.sandbox?.workspaceRoot).toBe(path.join(home, "sandbox-root"));
expect(cfg.channels?.whatsapp?.accounts?.personal?.authDir).toBe( expect(cfg.channels?.whatsapp?.accounts?.personal?.authDir).toBe(
path.join(home, ".clawdbot", "credentials", "wa-personal"), path.join(home, ".moltbot", "credentials", "wa-personal"),
); );
}); });
}); });
@ -195,10 +195,10 @@ describe("Nix integration (U3, U5, U9)", () => {
describe("U9: telegram.tokenFile schema validation", () => { describe("U9: telegram.tokenFile schema validation", () => {
it("accepts config with only botToken", async () => { it("accepts config with only botToken", async () => {
await withTempHome(async (home) => { await withTempHome(async (home) => {
const configDir = path.join(home, ".clawdbot"); const configDir = path.join(home, ".moltbot");
await fs.mkdir(configDir, { recursive: true }); await fs.mkdir(configDir, { recursive: true });
await fs.writeFile( await fs.writeFile(
path.join(configDir, "clawdbot.json"), path.join(configDir, "moltbot.json"),
JSON.stringify({ JSON.stringify({
channels: { telegram: { botToken: "123:ABC" } }, channels: { telegram: { botToken: "123:ABC" } },
}), }),
@ -215,10 +215,10 @@ describe("Nix integration (U3, U5, U9)", () => {
it("accepts config with only tokenFile", async () => { it("accepts config with only tokenFile", async () => {
await withTempHome(async (home) => { await withTempHome(async (home) => {
const configDir = path.join(home, ".clawdbot"); const configDir = path.join(home, ".moltbot");
await fs.mkdir(configDir, { recursive: true }); await fs.mkdir(configDir, { recursive: true });
await fs.writeFile( await fs.writeFile(
path.join(configDir, "clawdbot.json"), path.join(configDir, "moltbot.json"),
JSON.stringify({ JSON.stringify({
channels: { telegram: { tokenFile: "/run/agenix/telegram-token" } }, channels: { telegram: { tokenFile: "/run/agenix/telegram-token" } },
}), }),
@ -235,10 +235,10 @@ describe("Nix integration (U3, U5, U9)", () => {
it("accepts config with both botToken and tokenFile", async () => { it("accepts config with both botToken and tokenFile", async () => {
await withTempHome(async (home) => { await withTempHome(async (home) => {
const configDir = path.join(home, ".clawdbot"); const configDir = path.join(home, ".moltbot");
await fs.mkdir(configDir, { recursive: true }); await fs.mkdir(configDir, { recursive: true });
await fs.writeFile( await fs.writeFile(
path.join(configDir, "clawdbot.json"), path.join(configDir, "moltbot.json"),
JSON.stringify({ JSON.stringify({
channels: { channels: {
telegram: { telegram: {

View File

@ -53,8 +53,8 @@ const SHELL_ENV_EXPECTED_KEYS = [
"DISCORD_BOT_TOKEN", "DISCORD_BOT_TOKEN",
"SLACK_BOT_TOKEN", "SLACK_BOT_TOKEN",
"SLACK_APP_TOKEN", "SLACK_APP_TOKEN",
"CLAWDBOT_GATEWAY_TOKEN", "MOLTBOT_GATEWAY_TOKEN",
"CLAWDBOT_GATEWAY_PASSWORD", "MOLTBOT_GATEWAY_PASSWORD",
]; ];
const CONFIG_BACKUP_COUNT = 5; const CONFIG_BACKUP_COUNT = 5;
@ -522,7 +522,7 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
} }
// NOTE: These wrappers intentionally do *not* cache the resolved config path at // NOTE: These wrappers intentionally do *not* cache the resolved config path at
// module scope. `CLAWDBOT_CONFIG_PATH` (and friends) are expected to work even // module scope. `MOLTBOT_CONFIG_PATH` (and friends) are expected to work even
// when set after the module has been imported (tests, one-off scripts, etc.). // when set after the module has been imported (tests, one-off scripts, etc.).
const DEFAULT_CONFIG_CACHE_MS = 200; const DEFAULT_CONFIG_CACHE_MS = 200;
let configCache: { let configCache: {
@ -532,7 +532,7 @@ let configCache: {
} | null = null; } | null = null;
function resolveConfigCacheMs(env: NodeJS.ProcessEnv): number { function resolveConfigCacheMs(env: NodeJS.ProcessEnv): number {
const raw = env.CLAWDBOT_CONFIG_CACHE_MS?.trim(); const raw = env.MOLTBOT_CONFIG_CACHE_MS?.trim();
if (raw === "" || raw === "0") return 0; if (raw === "" || raw === "0") return 0;
if (!raw) return DEFAULT_CONFIG_CACHE_MS; if (!raw) return DEFAULT_CONFIG_CACHE_MS;
const parsed = Number.parseInt(raw, 10); const parsed = Number.parseInt(raw, 10);
@ -541,7 +541,7 @@ function resolveConfigCacheMs(env: NodeJS.ProcessEnv): number {
} }
function shouldUseConfigCache(env: NodeJS.ProcessEnv): boolean { function shouldUseConfigCache(env: NodeJS.ProcessEnv): boolean {
if (env.CLAWDBOT_DISABLE_CONFIG_CACHE?.trim()) return false; if (env.MOLTBOT_DISABLE_CONFIG_CACHE?.trim()) return false;
return resolveConfigCacheMs(env) > 0; return resolveConfigCacheMs(env) > 0;
} }

View File

@ -1,18 +1,18 @@
import type { RuntimeEnv } from "../runtime.js"; import type { RuntimeEnv } from "../runtime.js";
import { displayPath } from "../utils.js"; import { displayPath } from "../utils.js";
import { CONFIG_PATH_CLAWDBOT } from "./paths.js"; import { CONFIG_PATH_MOLTBOT } from "./paths.js";
type LogConfigUpdatedOptions = { type LogConfigUpdatedOptions = {
path?: string; path?: string;
suffix?: string; suffix?: string;
}; };
export function formatConfigPath(path: string = CONFIG_PATH_CLAWDBOT): string { export function formatConfigPath(path: string = CONFIG_PATH_MOLTBOT): string {
return displayPath(path); return displayPath(path);
} }
export function logConfigUpdated(runtime: RuntimeEnv, opts: LogConfigUpdatedOptions = {}): void { export function logConfigUpdated(runtime: RuntimeEnv, opts: LogConfigUpdatedOptions = {}): void {
const path = formatConfigPath(opts.path ?? CONFIG_PATH_CLAWDBOT); const path = formatConfigPath(opts.path ?? CONFIG_PATH_MOLTBOT);
const suffix = opts.suffix ? ` ${opts.suffix}` : ""; const suffix = opts.suffix ? ` ${opts.suffix}` : "";
runtime.log(`Updated ${path}${suffix}`); runtime.log(`Updated ${path}${suffix}`);
} }

View File

@ -15,18 +15,30 @@ export function resolveIsNixMode(env: NodeJS.ProcessEnv = process.env): boolean
export const isNixMode = resolveIsNixMode(); export const isNixMode = resolveIsNixMode();
const LEGACY_STATE_DIRNAME = ".clawdbot";
const NEW_STATE_DIRNAME = ".moltbot";
const CONFIG_FILENAME = "moltbot.json";
function legacyStateDir(homedir: () => string = os.homedir): string {
return path.join(homedir(), LEGACY_STATE_DIRNAME);
}
function newStateDir(homedir: () => string = os.homedir): string {
return path.join(homedir(), NEW_STATE_DIRNAME);
}
/** /**
* State directory for mutable data (sessions, logs, caches). * State directory for mutable data (sessions, logs, caches).
* Can be overridden via CLAWDBOT_STATE_DIR environment variable. * Can be overridden via MOLTBOT_STATE_DIR (preferred) or CLAWDBOT_STATE_DIR (legacy).
* Default: ~/.clawdbot * Default: ~/.clawdbot (legacy default for compatibility)
*/ */
export function resolveStateDir( export function resolveStateDir(
env: NodeJS.ProcessEnv = process.env, env: NodeJS.ProcessEnv = process.env,
homedir: () => string = os.homedir, homedir: () => string = os.homedir,
): string { ): string {
const override = env.CLAWDBOT_STATE_DIR?.trim(); const override = env.MOLTBOT_STATE_DIR?.trim() || env.CLAWDBOT_STATE_DIR?.trim();
if (override) return resolveUserPath(override); if (override) return resolveUserPath(override);
return path.join(homedir(), ".clawdbot"); return legacyStateDir(homedir);
} }
function resolveUserPath(input: string): string { function resolveUserPath(input: string): string {
@ -39,34 +51,64 @@ function resolveUserPath(input: string): string {
return path.resolve(trimmed); return path.resolve(trimmed);
} }
export const STATE_DIR_CLAWDBOT = resolveStateDir(); /** @deprecated Use STATE_DIR. Kept for compatibility during migration. */
export const STATE_DIR_MOLTBOT = resolveStateDir();
export const STATE_DIR = resolveStateDir();
/** /**
* Config file path (JSON5). * Config file path (JSON5).
* Can be overridden via CLAWDBOT_CONFIG_PATH environment variable. * Can be overridden via MOLTBOT_CONFIG_PATH (preferred) or CLAWDBOT_CONFIG_PATH (legacy).
* Default: ~/.clawdbot/clawdbot.json (or $CLAWDBOT_STATE_DIR/clawdbot.json) * Default: ~/.clawdbot/moltbot.json (or $*_STATE_DIR/moltbot.json)
*/ */
export function resolveConfigPath( export function resolveConfigPath(
env: NodeJS.ProcessEnv = process.env, env: NodeJS.ProcessEnv = process.env,
stateDir: string = resolveStateDir(env, os.homedir), stateDir: string = resolveStateDir(env, os.homedir),
): string { ): string {
const override = env.CLAWDBOT_CONFIG_PATH?.trim(); const override = env.MOLTBOT_CONFIG_PATH?.trim() || env.CLAWDBOT_CONFIG_PATH?.trim();
if (override) return resolveUserPath(override); if (override) return resolveUserPath(override);
return path.join(stateDir, "clawdbot.json"); return path.join(stateDir, CONFIG_FILENAME);
} }
export const CONFIG_PATH_CLAWDBOT = resolveConfigPath(); /** @deprecated Use CONFIG_PATH. Kept for compatibility during migration. */
export const CONFIG_PATH_MOLTBOT = resolveConfigPath();
export const CONFIG_PATH = resolveConfigPath();
/**
* Resolve default config path candidates across new + legacy locations.
* Order: explicit config path state-dir-derived paths new default legacy default.
*/
export function resolveDefaultConfigCandidates(
env: NodeJS.ProcessEnv = process.env,
homedir: () => string = os.homedir,
): string[] {
const explicit = env.MOLTBOT_CONFIG_PATH?.trim() || env.CLAWDBOT_CONFIG_PATH?.trim();
if (explicit) return [resolveUserPath(explicit)];
const candidates: string[] = [];
const moltbotStateDir = env.MOLTBOT_STATE_DIR?.trim();
if (moltbotStateDir) {
candidates.push(path.join(resolveUserPath(moltbotStateDir), CONFIG_FILENAME));
}
const legacyStateDirOverride = env.CLAWDBOT_STATE_DIR?.trim();
if (legacyStateDirOverride) {
candidates.push(path.join(resolveUserPath(legacyStateDirOverride), CONFIG_FILENAME));
}
candidates.push(path.join(newStateDir(homedir), CONFIG_FILENAME));
candidates.push(path.join(legacyStateDir(homedir), CONFIG_FILENAME));
return candidates;
}
export const DEFAULT_GATEWAY_PORT = 18789; export const DEFAULT_GATEWAY_PORT = 18789;
/** /**
* Gateway lock directory (ephemeral). * Gateway lock directory (ephemeral).
* Default: os.tmpdir()/clawdbot-<uid> (uid suffix when available). * Default: os.tmpdir()/moltbot-<uid> (uid suffix when available).
*/ */
export function resolveGatewayLockDir(tmpdir: () => string = os.tmpdir): string { export function resolveGatewayLockDir(tmpdir: () => string = os.tmpdir): string {
const base = tmpdir(); const base = tmpdir();
const uid = typeof process.getuid === "function" ? process.getuid() : undefined; const uid = typeof process.getuid === "function" ? process.getuid() : undefined;
const suffix = uid != null ? `clawdbot-${uid}` : "clawdbot"; const suffix = uid != null ? `moltbot-${uid}` : "moltbot";
return path.join(base, suffix); return path.join(base, suffix);
} }
@ -77,7 +119,7 @@ const OAUTH_FILENAME = "oauth.json";
* *
* Precedence: * Precedence:
* - `CLAWDBOT_OAUTH_DIR` (explicit override) * - `CLAWDBOT_OAUTH_DIR` (explicit override)
* - `CLAWDBOT_STATE_DIR/credentials` (canonical server/default) * - `$*_STATE_DIR/credentials` (canonical server/default)
* - `~/.clawdbot/credentials` (legacy default) * - `~/.clawdbot/credentials` (legacy default)
*/ */
export function resolveOAuthDir( export function resolveOAuthDir(

View File

@ -2,7 +2,7 @@ import path from "node:path";
import { pathToFileURL } from "node:url"; import { pathToFileURL } from "node:url";
import { import {
CONFIG_PATH_CLAWDBOT, CONFIG_PATH_MOLTBOT,
type HookMappingConfig, type HookMappingConfig,
type HooksConfig, type HooksConfig,
} from "../config/config.js"; } from "../config/config.js";
@ -125,7 +125,7 @@ export function resolveHookMappings(hooks?: HooksConfig): HookMappingResolved[]
} }
if (mappings.length === 0) return []; if (mappings.length === 0) return [];
const configDir = path.dirname(CONFIG_PATH_CLAWDBOT); const configDir = path.dirname(CONFIG_PATH_MOLTBOT);
const transformsDir = hooks?.transformsDir const transformsDir = hooks?.transformsDir
? resolvePath(configDir, hooks.transformsDir) ? resolvePath(configDir, hooks.transformsDir)
: configDir; : configDir;

View File

@ -1,6 +1,6 @@
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js"; import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js";
import { import {
CONFIG_PATH_CLAWDBOT, CONFIG_PATH_MOLTBOT,
loadConfig, loadConfig,
parseConfigJson5, parseConfigJson5,
readConfigFileSnapshot, readConfigFileSnapshot,
@ -186,7 +186,7 @@ export const configHandlers: GatewayRequestHandlers = {
true, true,
{ {
ok: true, ok: true,
path: CONFIG_PATH_CLAWDBOT, path: CONFIG_PATH_MOLTBOT,
config: validated.config, config: validated.config,
}, },
undefined, undefined,
@ -284,7 +284,7 @@ export const configHandlers: GatewayRequestHandlers = {
doctorHint: formatDoctorNonInteractiveHint(), doctorHint: formatDoctorNonInteractiveHint(),
stats: { stats: {
mode: "config.patch", mode: "config.patch",
root: CONFIG_PATH_CLAWDBOT, root: CONFIG_PATH_MOLTBOT,
}, },
}; };
let sentinelPath: string | null = null; let sentinelPath: string | null = null;
@ -301,7 +301,7 @@ export const configHandlers: GatewayRequestHandlers = {
true, true,
{ {
ok: true, ok: true,
path: CONFIG_PATH_CLAWDBOT, path: CONFIG_PATH_MOLTBOT,
config: validated.config, config: validated.config,
restart, restart,
sentinel: { sentinel: {
@ -381,7 +381,7 @@ export const configHandlers: GatewayRequestHandlers = {
doctorHint: formatDoctorNonInteractiveHint(), doctorHint: formatDoctorNonInteractiveHint(),
stats: { stats: {
mode: "config.apply", mode: "config.apply",
root: CONFIG_PATH_CLAWDBOT, root: CONFIG_PATH_MOLTBOT,
}, },
}; };
let sentinelPath: string | null = null; let sentinelPath: string | null = null;
@ -398,7 +398,7 @@ export const configHandlers: GatewayRequestHandlers = {
true, true,
{ {
ok: true, ok: true,
path: CONFIG_PATH_CLAWDBOT, path: CONFIG_PATH_MOLTBOT,
config: validated.config, config: validated.config,
restart, restart,
sentinel: { sentinel: {

View File

@ -66,7 +66,7 @@ describe("gateway server auth/connect", () => {
}); });
test("connect (req) handshake returns hello-ok payload", async () => { test("connect (req) handshake returns hello-ok payload", async () => {
const { CONFIG_PATH_CLAWDBOT, STATE_DIR_CLAWDBOT } = await import("../config/config.js"); const { CONFIG_PATH_MOLTBOT, STATE_DIR_MOLTBOT } = await import("../config/config.js");
const ws = await openWs(port); const ws = await openWs(port);
const res = await connectReq(ws); const res = await connectReq(ws);
@ -78,8 +78,8 @@ describe("gateway server auth/connect", () => {
} }
| undefined; | undefined;
expect(payload?.type).toBe("hello-ok"); expect(payload?.type).toBe("hello-ok");
expect(payload?.snapshot?.configPath).toBe(CONFIG_PATH_CLAWDBOT); expect(payload?.snapshot?.configPath).toBe(CONFIG_PATH_MOLTBOT);
expect(payload?.snapshot?.stateDir).toBe(STATE_DIR_CLAWDBOT); expect(payload?.snapshot?.stateDir).toBe(STATE_DIR_MOLTBOT);
ws.close(); ws.close();
}); });

View File

@ -6,7 +6,7 @@ import { type ChannelId, listChannelPlugins } from "../channels/plugins/index.js
import { createDefaultDeps } from "../cli/deps.js"; import { createDefaultDeps } from "../cli/deps.js";
import { formatCliCommand } from "../cli/command-format.js"; import { formatCliCommand } from "../cli/command-format.js";
import { import {
CONFIG_PATH_CLAWDBOT, CONFIG_PATH_MOLTBOT,
isNixMode, isNixMode,
loadConfig, loadConfig,
migrateLegacyConfig, migrateLegacyConfig,
@ -541,7 +541,7 @@ export async function startGatewayServer(
warn: (msg) => logReload.warn(msg), warn: (msg) => logReload.warn(msg),
error: (msg) => logReload.error(msg), error: (msg) => logReload.error(msg),
}, },
watchPath: CONFIG_PATH_CLAWDBOT, watchPath: CONFIG_PATH_MOLTBOT,
}); });
const close = createGatewayCloseHandler({ const close = createGatewayCloseHandler({

View File

@ -1,6 +1,6 @@
import { resolveDefaultAgentId } from "../../agents/agent-scope.js"; import { resolveDefaultAgentId } from "../../agents/agent-scope.js";
import { getHealthSnapshot, type HealthSummary } from "../../commands/health.js"; import { getHealthSnapshot, type HealthSummary } from "../../commands/health.js";
import { CONFIG_PATH_CLAWDBOT, STATE_DIR_CLAWDBOT, loadConfig } from "../../config/config.js"; import { CONFIG_PATH_MOLTBOT, STATE_DIR_MOLTBOT, loadConfig } from "../../config/config.js";
import { resolveMainSessionKey } from "../../config/sessions.js"; import { resolveMainSessionKey } from "../../config/sessions.js";
import { normalizeMainKey } from "../../routing/session-key.js"; import { normalizeMainKey } from "../../routing/session-key.js";
import { listSystemPresence } from "../../infra/system-presence.js"; import { listSystemPresence } from "../../infra/system-presence.js";
@ -28,8 +28,8 @@ export function buildGatewaySnapshot(): Snapshot {
stateVersion: { presence: presenceVersion, health: healthVersion }, stateVersion: { presence: presenceVersion, health: healthVersion },
uptimeMs, uptimeMs,
// Surface resolved paths so UIs can display the true config location. // Surface resolved paths so UIs can display the true config location.
configPath: CONFIG_PATH_CLAWDBOT, configPath: CONFIG_PATH_MOLTBOT,
stateDir: STATE_DIR_CLAWDBOT, stateDir: STATE_DIR_MOLTBOT,
sessionDefaults: { sessionDefaults: {
defaultAgentId, defaultAgentId,
mainKey, mainKey,

View File

@ -350,10 +350,10 @@ vi.mock("../config/config.js", async () => {
return { return {
...actual, ...actual,
get CONFIG_PATH_CLAWDBOT() { get CONFIG_PATH_MOLTBOT() {
return resolveConfigPath(); return resolveConfigPath();
}, },
get STATE_DIR_CLAWDBOT() { get STATE_DIR_MOLTBOT() {
return path.dirname(resolveConfigPath()); return path.dirname(resolveConfigPath());
}, },
get isNixMode() { get isNixMode() {

View File

@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
import { import {
type ClawdbotConfig, type ClawdbotConfig,
CONFIG_PATH_CLAWDBOT, CONFIG_PATH_MOLTBOT,
loadConfig, loadConfig,
readConfigFileSnapshot, readConfigFileSnapshot,
resolveGatewayPort, resolveGatewayPort,
@ -99,7 +99,7 @@ export async function runGmailSetup(opts: GmailSetupOptions) {
const configSnapshot = await readConfigFileSnapshot(); const configSnapshot = await readConfigFileSnapshot();
if (!configSnapshot.valid) { if (!configSnapshot.valid) {
throw new Error(`Config invalid: ${CONFIG_PATH_CLAWDBOT}`); throw new Error(`Config invalid: ${CONFIG_PATH_MOLTBOT}`);
} }
const baseConfig = configSnapshot.config; const baseConfig = configSnapshot.config;
@ -277,7 +277,7 @@ export async function runGmailSetup(opts: GmailSetupOptions) {
defaultRuntime.log(`- subscription: ${subscription}`); defaultRuntime.log(`- subscription: ${subscription}`);
defaultRuntime.log(`- push endpoint: ${pushEndpoint}`); defaultRuntime.log(`- push endpoint: ${pushEndpoint}`);
defaultRuntime.log(`- hook url: ${hookUrl}`); defaultRuntime.log(`- hook url: ${hookUrl}`);
defaultRuntime.log(`- config: ${displayPath(CONFIG_PATH_CLAWDBOT)}`); defaultRuntime.log(`- config: ${displayPath(CONFIG_PATH_MOLTBOT)}`);
defaultRuntime.log(`Next: ${formatCliCommand("clawdbot webhooks gmail run")}`); defaultRuntime.log(`Next: ${formatCliCommand("clawdbot webhooks gmail run")}`);
} }

View File

@ -1,5 +1,5 @@
import type { ClawdbotConfig } from "../config/config.js"; import type { ClawdbotConfig } from "../config/config.js";
import { STATE_DIR_CLAWDBOT } from "../config/paths.js"; import { STATE_DIR_MOLTBOT } from "../config/paths.js";
import { createSubsystemLogger } from "../logging/subsystem.js"; import { createSubsystemLogger } from "../logging/subsystem.js";
import type { PluginRegistry } from "./registry.js"; import type { PluginRegistry } from "./registry.js";
@ -25,7 +25,7 @@ export async function startPluginServices(params: {
await service.start({ await service.start({
config: params.config, config: params.config,
workspaceDir: params.workspaceDir, workspaceDir: params.workspaceDir,
stateDir: STATE_DIR_CLAWDBOT, stateDir: STATE_DIR_MOLTBOT,
logger: { logger: {
info: (msg) => log.info(msg), info: (msg) => log.info(msg),
warn: (msg) => log.warn(msg), warn: (msg) => log.warn(msg),
@ -40,7 +40,7 @@ export async function startPluginServices(params: {
service.stop?.({ service.stop?.({
config: params.config, config: params.config,
workspaceDir: params.workspaceDir, workspaceDir: params.workspaceDir,
stateDir: STATE_DIR_CLAWDBOT, stateDir: STATE_DIR_MOLTBOT,
logger: { logger: {
info: (msg) => log.info(msg), info: (msg) => log.info(msg),
warn: (msg) => log.warn(msg), warn: (msg) => log.warn(msg),