chore: rename project to clawdbot

This commit is contained in:
Peter Steinberger
2026-01-04 14:32:47 +00:00
parent d48dc71fa4
commit 246adaa119
841 changed files with 4590 additions and 4328 deletions

View File

@@ -43,9 +43,9 @@ function parseDnsSdBrowse(stdout: string): string[] {
const instances = new Set<string>();
for (const raw of stdout.split("\n")) {
const line = raw.trim();
if (!line || !line.includes("_clawdis-bridge._tcp")) continue;
if (!line || !line.includes("_clawdbot-bridge._tcp")) continue;
if (!line.includes("Add")) continue;
const match = line.match(/_clawdis-bridge\._tcp\.?\s+(.+)$/);
const match = line.match(/_clawdbot-bridge\._tcp\.?\s+(.+)$/);
if (match?.[1]) {
instances.add(match[1].trim());
}
@@ -97,14 +97,14 @@ async function discoverViaDnsSd(
timeoutMs: number,
): Promise<GatewayBonjourBeacon[]> {
const browse = await runCommandWithTimeout(
["dns-sd", "-B", "_clawdis-bridge._tcp", "local."],
["dns-sd", "-B", "_clawdbot-bridge._tcp", "local."],
{ timeoutMs },
);
const instances = parseDnsSdBrowse(browse.stdout);
const results: GatewayBonjourBeacon[] = [];
for (const instance of instances) {
const resolved = await runCommandWithTimeout(
["dns-sd", "-L", instance, "_clawdis-bridge._tcp", "local."],
["dns-sd", "-L", instance, "_clawdbot-bridge._tcp", "local."],
{ timeoutMs },
);
const parsed = parseDnsSdResolve(resolved.stdout, instance);
@@ -120,9 +120,9 @@ function parseAvahiBrowse(stdout: string): GatewayBonjourBeacon[] {
for (const raw of stdout.split("\n")) {
const line = raw.trimEnd();
if (!line) continue;
if (line.startsWith("=") && line.includes("_clawdis-bridge._tcp")) {
if (line.startsWith("=") && line.includes("_clawdbot-bridge._tcp")) {
if (current) results.push(current);
const marker = " _clawdis-bridge._tcp";
const marker = " _clawdbot-bridge._tcp";
const idx = line.indexOf(marker);
const left = idx >= 0 ? line.slice(0, idx).trim() : line;
const parts = left.split(/\s+/);
@@ -171,7 +171,7 @@ async function discoverViaAvahi(
timeoutMs: number,
): Promise<GatewayBonjourBeacon[]> {
const browse = await runCommandWithTimeout(
["avahi-browse", "-rt", "_clawdis-bridge._tcp"],
["avahi-browse", "-rt", "_clawdbot-bridge._tcp"],
{ timeoutMs },
);
return parseAvahiBrowse(browse.stdout);

View File

@@ -100,14 +100,14 @@ describe("gateway bonjour advertiser", () => {
sshPort: 2222,
bridgePort: 18790,
tailnetDns: "host.tailnet.ts.net",
cliPath: "/opt/homebrew/bin/clawdis",
cliPath: "/opt/homebrew/bin/clawdbot",
});
expect(createService).toHaveBeenCalledTimes(1);
const [bridgeCall] = createService.mock.calls as Array<
[Record<string, unknown>]
>;
expect(bridgeCall?.[0]?.type).toBe("clawdis-bridge");
expect(bridgeCall?.[0]?.type).toBe("clawdbot-bridge");
expect(bridgeCall?.[0]?.port).toBe(18790);
expect(bridgeCall?.[0]?.domain).toBe("local");
expect(bridgeCall?.[0]?.hostname).toBe("test-host");
@@ -121,7 +121,7 @@ describe("gateway bonjour advertiser", () => {
"2222",
);
expect((bridgeCall?.[0]?.txt as Record<string, string>)?.cliPath).toBe(
"/opt/homebrew/bin/clawdis",
"/opt/homebrew/bin/clawdbot",
);
expect((bridgeCall?.[0]?.txt as Record<string, string>)?.transport).toBe(
"bridge",
@@ -297,7 +297,7 @@ describe("gateway bonjour advertiser", () => {
});
const [bridgeCall] = createService.mock.calls as Array<[ServiceCall]>;
expect(bridgeCall?.[0]?.name).toBe("Mac (Clawdis)");
expect(bridgeCall?.[0]?.name).toBe("Mac (Clawdbot)");
expect(bridgeCall?.[0]?.domain).toBe("local");
expect(bridgeCall?.[0]?.hostname).toBe("Mac");
expect((bridgeCall?.[0]?.txt as Record<string, string>)?.lanHost).toBe(

View File

@@ -18,7 +18,7 @@ export type GatewayBonjourAdvertiseOpts = {
};
function isDisabledByEnv() {
if (process.env.CLAWDIS_DISABLE_BONJOUR === "1") return true;
if (process.env.CLAWDBOT_DISABLE_BONJOUR === "1") return true;
if (process.env.NODE_ENV === "test") return true;
if (process.env.VITEST) return true;
return false;
@@ -26,12 +26,12 @@ function isDisabledByEnv() {
function safeServiceName(name: string) {
const trimmed = name.trim();
return trimmed.length > 0 ? trimmed : "Clawdis";
return trimmed.length > 0 ? trimmed : "Clawdbot";
}
function prettifyInstanceName(name: string) {
const normalized = name.trim().replace(/\s+/g, " ");
return normalized.replace(/\s+\(Clawdis\)\s*$/i, "").trim() || normalized;
return normalized.replace(/\s+\(Clawdbot\)\s*$/i, "").trim() || normalized;
}
type BonjourService = {
@@ -94,11 +94,11 @@ export async function startGatewayBonjourAdvertiser(
.hostname()
.replace(/\.local$/i, "")
.split(".")[0]
.trim() || "clawdis";
.trim() || "clawdbot";
const instanceName =
typeof opts.instanceName === "string" && opts.instanceName.trim()
? opts.instanceName.trim()
: `${hostname} (Clawdis)`;
: `${hostname} (Clawdbot)`;
const displayName = prettifyInstanceName(instanceName);
const txtBase: Record<string, string> = {
@@ -126,7 +126,7 @@ export async function startGatewayBonjourAdvertiser(
if (typeof opts.bridgePort === "number" && opts.bridgePort > 0) {
const bridge = responder.createService({
name: safeServiceName(instanceName),
type: "clawdis-bridge",
type: "clawdbot-bridge",
protocol: Protocol.TCP,
port: opts.bridgePort,
domain: "local",

View File

@@ -61,13 +61,13 @@ describe("node bridge server", () => {
};
beforeAll(async () => {
process.env.CLAWDIS_ENABLE_BRIDGE_IN_TESTS = "1";
baseDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdis-bridge-test-"));
process.env.CLAWDBOT_ENABLE_BRIDGE_IN_TESTS = "1";
baseDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-bridge-test-"));
});
afterAll(async () => {
await fs.rm(baseDir, { recursive: true, force: true });
delete process.env.CLAWDIS_ENABLE_BRIDGE_IN_TESTS;
delete process.env.CLAWDBOT_ENABLE_BRIDGE_IN_TESTS;
});
it("rejects hello when not paired", async () => {

View File

@@ -171,7 +171,7 @@ async function sleep(ms: number) {
export async function startNodeBridgeServer(
opts: NodeBridgeServerOpts,
): Promise<NodeBridgeServer> {
if (isTestEnv() && process.env.CLAWDIS_ENABLE_BRIDGE_IN_TESTS !== "1") {
if (isTestEnv() && process.env.CLAWDBOT_ENABLE_BRIDGE_IN_TESTS !== "1") {
return {
port: 0,
close: async () => {},

View File

@@ -4,7 +4,7 @@ import path from "node:path";
import { describe, expect, it, vi } from "vitest";
import { HEARTBEAT_PROMPT } from "../auto-reply/heartbeat.js";
import * as replyModule from "../auto-reply/reply.js";
import type { ClawdisConfig } from "../config/config.js";
import type { ClawdbotConfig } from "../config/config.js";
import {
resolveHeartbeatDeliveryTarget,
resolveHeartbeatIntervalMs,
@@ -42,7 +42,7 @@ describe("resolveHeartbeatPrompt", () => {
});
it("uses a trimmed override when configured", () => {
const cfg: ClawdisConfig = {
const cfg: ClawdbotConfig = {
agent: { heartbeat: { prompt: " ping " } },
};
expect(resolveHeartbeatPrompt(cfg)).toBe("ping");
@@ -56,7 +56,7 @@ describe("resolveHeartbeatDeliveryTarget", () => {
};
it("respects target none", () => {
const cfg: ClawdisConfig = {
const cfg: ClawdbotConfig = {
agent: { heartbeat: { target: "none" } },
};
expect(resolveHeartbeatDeliveryTarget({ cfg, entry: baseEntry })).toEqual({
@@ -66,7 +66,7 @@ describe("resolveHeartbeatDeliveryTarget", () => {
});
it("uses last route by default", () => {
const cfg: ClawdisConfig = {};
const cfg: ClawdbotConfig = {};
const entry = {
...baseEntry,
lastChannel: "whatsapp" as const,
@@ -79,7 +79,7 @@ describe("resolveHeartbeatDeliveryTarget", () => {
});
it("skips when last route is webchat", () => {
const cfg: ClawdisConfig = {};
const cfg: ClawdbotConfig = {};
const entry = {
...baseEntry,
lastChannel: "webchat" as const,
@@ -92,7 +92,7 @@ describe("resolveHeartbeatDeliveryTarget", () => {
});
it("applies allowFrom fallback for WhatsApp targets", () => {
const cfg: ClawdisConfig = {
const cfg: ClawdbotConfig = {
agent: { heartbeat: { target: "whatsapp", to: "+1999" } },
whatsapp: { allowFrom: ["+1555", "+1666"] },
};
@@ -109,7 +109,7 @@ describe("resolveHeartbeatDeliveryTarget", () => {
});
it("keeps explicit telegram targets", () => {
const cfg: ClawdisConfig = {
const cfg: ClawdbotConfig = {
agent: { heartbeat: { target: "telegram", to: "123" } },
};
expect(resolveHeartbeatDeliveryTarget({ cfg, entry: baseEntry })).toEqual({
@@ -121,7 +121,7 @@ describe("resolveHeartbeatDeliveryTarget", () => {
describe("runHeartbeatOnce", () => {
it("uses the last non-empty payload for delivery", async () => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdis-hb-"));
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-hb-"));
const storePath = path.join(tmpDir, "sessions.json");
const replySpy = vi.spyOn(replyModule, "getReplyFromConfig");
try {
@@ -141,7 +141,7 @@ describe("runHeartbeatOnce", () => {
),
);
const cfg: ClawdisConfig = {
const cfg: ClawdbotConfig = {
agent: {
heartbeat: { every: "5m", target: "whatsapp", to: "+1555" },
},
@@ -182,7 +182,7 @@ describe("runHeartbeatOnce", () => {
});
it("skips WhatsApp delivery when not linked or running", async () => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdis-hb-"));
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-hb-"));
const storePath = path.join(tmpDir, "sessions.json");
const replySpy = vi.spyOn(replyModule, "getReplyFromConfig");
try {
@@ -202,7 +202,7 @@ describe("runHeartbeatOnce", () => {
),
);
const cfg: ClawdisConfig = {
const cfg: ClawdbotConfig = {
agent: {
heartbeat: { every: "5m", target: "whatsapp", to: "+1555" },
},

View File

@@ -6,7 +6,7 @@ import {
import { getReplyFromConfig } from "../auto-reply/reply.js";
import type { ReplyPayload } from "../auto-reply/types.js";
import { parseDurationMs } from "../cli/parse-duration.js";
import type { ClawdisConfig } from "../config/config.js";
import type { ClawdbotConfig } from "../config/config.js";
import { loadConfig } from "../config/config.js";
import {
loadSessionStore,
@@ -79,7 +79,7 @@ export function setHeartbeatsEnabled(enabled: boolean) {
}
export function resolveHeartbeatIntervalMs(
cfg: ClawdisConfig,
cfg: ClawdbotConfig,
overrideEvery?: string,
) {
const raw = overrideEvery ?? cfg.agent?.heartbeat?.every;
@@ -96,13 +96,13 @@ export function resolveHeartbeatIntervalMs(
return ms;
}
export function resolveHeartbeatPrompt(cfg: ClawdisConfig) {
export function resolveHeartbeatPrompt(cfg: ClawdbotConfig) {
const raw = cfg.agent?.heartbeat?.prompt;
const trimmed = typeof raw === "string" ? raw.trim() : "";
return trimmed || HEARTBEAT_PROMPT;
}
function resolveHeartbeatSession(cfg: ClawdisConfig) {
function resolveHeartbeatSession(cfg: ClawdbotConfig) {
const sessionCfg = cfg.session;
const scope = sessionCfg?.scope ?? "per-sender";
const mainKey = (sessionCfg?.mainKey ?? "main").trim() || "main";
@@ -164,7 +164,7 @@ function resolveHeartbeatSender(params: {
}
async function resolveWhatsAppReadiness(
cfg: ClawdisConfig,
cfg: ClawdbotConfig,
deps?: HeartbeatDeps,
): Promise<{ ok: boolean; reason: string }> {
if (cfg.web?.enabled === false) {
@@ -184,7 +184,7 @@ async function resolveWhatsAppReadiness(
}
export function resolveHeartbeatDeliveryTarget(params: {
cfg: ClawdisConfig;
cfg: ClawdbotConfig;
entry?: SessionEntry;
}): HeartbeatDeliveryTarget {
const { cfg, entry } = params;
@@ -417,7 +417,7 @@ async function deliverHeartbeatReply(params: {
}
export async function runHeartbeatOnce(opts: {
cfg?: ClawdisConfig;
cfg?: ClawdbotConfig;
reason?: string;
deps?: HeartbeatDeps;
}): Promise<HeartbeatRunResult> {
@@ -568,7 +568,7 @@ export async function runHeartbeatOnce(opts: {
}
export function startHeartbeatRunner(opts: {
cfg?: ClawdisConfig;
cfg?: ClawdbotConfig;
runtime?: RuntimeEnv;
abortSignal?: AbortSignal;
}) {

View File

@@ -28,7 +28,7 @@ describe("isMainModule", () => {
it("returns false when running under PM2 but this module is imported", () => {
expect(
isMainModule({
currentFile: "/repo/node_modules/clawdis/dist/index.js",
currentFile: "/repo/node_modules/clawdbot/dist/index.js",
argv: ["node", "/repo/app.js"],
cwd: "/repo",
env: { pm_exec_path: "/repo/app.js", pm_id: "0" },

View File

@@ -24,7 +24,7 @@ function fallbackHostName() {
os
.hostname()
.replace(/\.local$/i, "")
.trim() || "clawdis"
.trim() || "clawdbot"
);
}

View File

@@ -49,7 +49,7 @@ type NodePairingStateFile = {
const PENDING_TTL_MS = 5 * 60 * 1000;
function defaultBaseDir() {
return path.join(os.homedir(), ".clawdis");
return path.join(os.homedir(), ".clawdbot");
}
function resolvePaths(baseDir?: string) {

View File

@@ -4,24 +4,24 @@ import path from "node:path";
import { describe, expect, it } from "vitest";
import { ensureClawdisCliOnPath } from "./path-env.js";
import { ensureClawdbotCliOnPath } from "./path-env.js";
describe("ensureClawdisCliOnPath", () => {
it("prepends the bundled Relay dir when a sibling clawdis exists", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "clawdis-path-"));
describe("ensureClawdbotCliOnPath", () => {
it("prepends the bundled Relay dir when a sibling clawdbot exists", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-path-"));
try {
const relayDir = path.join(tmp, "Relay");
await fs.mkdir(relayDir, { recursive: true });
const cliPath = path.join(relayDir, "clawdis");
const cliPath = path.join(relayDir, "clawdbot");
await fs.writeFile(cliPath, "#!/bin/sh\necho ok\n", "utf-8");
await fs.chmod(cliPath, 0o755);
const originalPath = process.env.PATH;
const originalFlag = process.env.CLAWDIS_PATH_BOOTSTRAPPED;
const originalFlag = process.env.CLAWDBOT_PATH_BOOTSTRAPPED;
process.env.PATH = "/usr/bin";
delete process.env.CLAWDIS_PATH_BOOTSTRAPPED;
delete process.env.CLAWDBOT_PATH_BOOTSTRAPPED;
try {
ensureClawdisCliOnPath({
ensureClawdbotCliOnPath({
execPath: cliPath,
cwd: tmp,
homeDir: tmp,
@@ -32,8 +32,8 @@ describe("ensureClawdisCliOnPath", () => {
} finally {
process.env.PATH = originalPath;
if (originalFlag === undefined)
delete process.env.CLAWDIS_PATH_BOOTSTRAPPED;
else process.env.CLAWDIS_PATH_BOOTSTRAPPED = originalFlag;
delete process.env.CLAWDBOT_PATH_BOOTSTRAPPED;
else process.env.CLAWDBOT_PATH_BOOTSTRAPPED = originalFlag;
}
} finally {
await fs.rm(tmp, { recursive: true, force: true });
@@ -42,11 +42,11 @@ describe("ensureClawdisCliOnPath", () => {
it("is idempotent", () => {
const originalPath = process.env.PATH;
const originalFlag = process.env.CLAWDIS_PATH_BOOTSTRAPPED;
const originalFlag = process.env.CLAWDBOT_PATH_BOOTSTRAPPED;
process.env.PATH = "/bin";
process.env.CLAWDIS_PATH_BOOTSTRAPPED = "1";
process.env.CLAWDBOT_PATH_BOOTSTRAPPED = "1";
try {
ensureClawdisCliOnPath({
ensureClawdbotCliOnPath({
execPath: "/tmp/does-not-matter",
cwd: "/tmp",
homeDir: "/tmp",
@@ -56,26 +56,26 @@ describe("ensureClawdisCliOnPath", () => {
} finally {
process.env.PATH = originalPath;
if (originalFlag === undefined)
delete process.env.CLAWDIS_PATH_BOOTSTRAPPED;
else process.env.CLAWDIS_PATH_BOOTSTRAPPED = originalFlag;
delete process.env.CLAWDBOT_PATH_BOOTSTRAPPED;
else process.env.CLAWDBOT_PATH_BOOTSTRAPPED = originalFlag;
}
});
it("prepends mise shims when available", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "clawdis-path-"));
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-path-"));
const originalPath = process.env.PATH;
const originalFlag = process.env.CLAWDIS_PATH_BOOTSTRAPPED;
const originalFlag = process.env.CLAWDBOT_PATH_BOOTSTRAPPED;
const originalMiseDataDir = process.env.MISE_DATA_DIR;
try {
const relayDir = path.join(tmp, "Relay");
await fs.mkdir(relayDir, { recursive: true });
const relayCli = path.join(relayDir, "clawdis");
const relayCli = path.join(relayDir, "clawdbot");
await fs.writeFile(relayCli, "#!/bin/sh\necho ok\n", "utf-8");
await fs.chmod(relayCli, 0o755);
const localBinDir = path.join(tmp, "node_modules", ".bin");
await fs.mkdir(localBinDir, { recursive: true });
const localCli = path.join(localBinDir, "clawdis");
const localCli = path.join(localBinDir, "clawdbot");
await fs.writeFile(localCli, "#!/bin/sh\necho ok\n", "utf-8");
await fs.chmod(localCli, 0o755);
@@ -84,9 +84,9 @@ describe("ensureClawdisCliOnPath", () => {
await fs.mkdir(shimsDir, { recursive: true });
process.env.MISE_DATA_DIR = miseDataDir;
process.env.PATH = "/usr/bin";
delete process.env.CLAWDIS_PATH_BOOTSTRAPPED;
delete process.env.CLAWDBOT_PATH_BOOTSTRAPPED;
ensureClawdisCliOnPath({
ensureClawdbotCliOnPath({
execPath: relayCli,
cwd: tmp,
homeDir: tmp,
@@ -104,8 +104,8 @@ describe("ensureClawdisCliOnPath", () => {
} finally {
process.env.PATH = originalPath;
if (originalFlag === undefined)
delete process.env.CLAWDIS_PATH_BOOTSTRAPPED;
else process.env.CLAWDIS_PATH_BOOTSTRAPPED = originalFlag;
delete process.env.CLAWDBOT_PATH_BOOTSTRAPPED;
else process.env.CLAWDBOT_PATH_BOOTSTRAPPED = originalFlag;
if (originalMiseDataDir === undefined) delete process.env.MISE_DATA_DIR;
else process.env.MISE_DATA_DIR = originalMiseDataDir;
await fs.rm(tmp, { recursive: true, force: true });

View File

@@ -2,7 +2,7 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
type EnsureClawdisPathOpts = {
type EnsureClawdbotPathOpts = {
execPath?: string;
cwd?: string;
homeDir?: string;
@@ -47,7 +47,7 @@ function mergePath(params: { existing: string; prepend: string[] }): string {
return merged.join(path.delimiter);
}
function candidateBinDirs(opts: EnsureClawdisPathOpts): string[] {
function candidateBinDirs(opts: EnsureClawdbotPathOpts): string[] {
const execPath = opts.execPath ?? process.execPath;
const cwd = opts.cwd ?? process.cwd();
const homeDir = opts.homeDir ?? os.homedir();
@@ -55,19 +55,19 @@ function candidateBinDirs(opts: EnsureClawdisPathOpts): string[] {
const candidates: string[] = [];
// Bun bundled (macOS app): `clawdis` lives in the Relay dir (process.execPath).
// Bun bundled (macOS app): `clawdbot` lives in the Relay dir (process.execPath).
try {
const execDir = path.dirname(execPath);
const siblingClawdis = path.join(execDir, "clawdis");
if (isExecutable(siblingClawdis)) candidates.push(execDir);
const siblingClawdbot = path.join(execDir, "clawdbot");
if (isExecutable(siblingClawdbot)) candidates.push(execDir);
} catch {
// ignore
}
// Project-local installs (best effort): if a `node_modules/.bin/clawdis` exists near cwd,
// Project-local installs (best effort): if a `node_modules/.bin/clawdbot` exists near cwd,
// include it. This helps when running under launchd or other minimal PATH environments.
const localBinDir = path.join(cwd, "node_modules", ".bin");
if (isExecutable(path.join(localBinDir, "clawdis")))
if (isExecutable(path.join(localBinDir, "clawdbot")))
candidates.push(localBinDir);
const miseDataDir =
@@ -90,12 +90,12 @@ function candidateBinDirs(opts: EnsureClawdisPathOpts): string[] {
}
/**
* Best-effort PATH bootstrap so skills that require the `clawdis` CLI can run
* Best-effort PATH bootstrap so skills that require the `clawdbot` CLI can run
* under launchd/minimal environments (and inside the macOS bun bundle).
*/
export function ensureClawdisCliOnPath(opts: EnsureClawdisPathOpts = {}) {
if (process.env.CLAWDIS_PATH_BOOTSTRAPPED === "1") return;
process.env.CLAWDIS_PATH_BOOTSTRAPPED = "1";
export function ensureClawdbotCliOnPath(opts: EnsureClawdbotPathOpts = {}) {
if (process.env.CLAWDBOT_PATH_BOOTSTRAPPED === "1") return;
process.env.CLAWDBOT_PATH_BOOTSTRAPPED = "1";
const existing = opts.pathEnv ?? process.env.PATH ?? "";
const prepend = candidateBinDirs(opts);

View File

@@ -85,10 +85,10 @@ export async function handlePortError(
if (details) {
runtime.error(info("Port listener details:"));
runtime.error(details);
if (/clawdis|src\/index\.ts|dist\/index\.js/.test(details)) {
if (/clawdbot|src\/index\.ts|dist\/index\.js/.test(details)) {
runtime.error(
warn(
"It looks like another clawdis instance is already running. Stop it or pick a different port.",
"It looks like another clawdbot instance is already running. Stop it or pick a different port.",
),
);
}

View File

@@ -1,5 +1,5 @@
import chalk from "chalk";
import { type ClawdisConfig, loadConfig } from "../config/config.js";
import { type ClawdbotConfig, loadConfig } from "../config/config.js";
import { resolveTelegramToken } from "../telegram/token.js";
import { normalizeE164 } from "../utils.js";
import {
@@ -9,7 +9,7 @@ import {
} from "../web/session.js";
export async function buildProviderSummary(
cfg?: ClawdisConfig,
cfg?: ClawdbotConfig,
): Promise<string[]> {
const effective = cfg ?? loadConfig();
const lines: string[] = [];

View File

@@ -1,15 +1,15 @@
import { spawnSync } from "node:child_process";
const DEFAULT_LAUNCHD_LABEL = "com.clawdis.mac";
const DEFAULT_SYSTEMD_UNIT = "clawdis-gateway.service";
const DEFAULT_LAUNCHD_LABEL = "com.clawdbot.mac";
const DEFAULT_SYSTEMD_UNIT = "clawdbot-gateway.service";
export function triggerClawdisRestart():
export function triggerClawdbotRestart():
| "launchctl"
| "systemd"
| "supervisor" {
if (process.platform !== "darwin") {
if (process.platform === "linux") {
const unit = process.env.CLAWDIS_SYSTEMD_UNIT || DEFAULT_SYSTEMD_UNIT;
const unit = process.env.CLAWDBOT_SYSTEMD_UNIT || DEFAULT_SYSTEMD_UNIT;
const userRestart = spawnSync("systemctl", ["--user", "restart", unit], {
stdio: "ignore",
});
@@ -27,7 +27,7 @@ export function triggerClawdisRestart():
return "supervisor";
}
const label = process.env.CLAWDIS_LAUNCHD_LABEL || DEFAULT_LAUNCHD_LABEL;
const label = process.env.CLAWDBOT_LAUNCHD_LABEL || DEFAULT_LAUNCHD_LABEL;
const uid =
typeof process.getuid === "function" ? process.getuid() : undefined;
const target = uid !== undefined ? `gui/${uid}/${label}` : label;

View File

@@ -73,11 +73,11 @@ export function assertSupportedRuntime(
runtime.error(
[
"clawdis requires Node >=22.0.0.",
"clawdbot requires Node >=22.0.0.",
`Detected: ${runtimeLabel} (exec: ${execLabel}).`,
`PATH searched: ${details.pathEnv}`,
"Install Node: https://nodejs.org/en/download",
"Upgrade Node and re-run clawdis.",
"Upgrade Node and re-run clawdbot.",
].join("\n"),
);
runtime.exit(1);

View File

@@ -12,7 +12,7 @@ describe("system-presence", () => {
const instanceIdLower = instanceIdUpper.toLowerCase();
upsertPresence(instanceIdUpper, {
host: "clawdis",
host: "clawdbot",
mode: "app",
instanceId: instanceIdUpper,
reason: "connect",

View File

@@ -57,7 +57,7 @@ function initSelfPresence() {
const host = os.hostname();
const ip = resolvePrimaryIPv4() ?? undefined;
const version =
process.env.CLAWDIS_VERSION ?? process.env.npm_package_version ?? "unknown";
process.env.CLAWDBOT_VERSION ?? process.env.npm_package_version ?? "unknown";
const modelIdentifier = (() => {
const p = os.platform();
if (p === "darwin") {

View File

@@ -176,7 +176,7 @@ export async function ensureFunnel(
);
runtime.error(
info(
"Tip: Funnel is optional for CLAWDIS. You can keep running the web gateway without it: `pnpm clawdis gateway`",
"Tip: Funnel is optional for CLAWDBOT. You can keep running the web gateway without it: `pnpm clawdbot gateway`",
),
);
if (shouldLogVerbose()) {

View File

@@ -13,7 +13,7 @@ import {
describe("voicewake store", () => {
it("returns defaults when missing", async () => {
const baseDir = await fs.mkdtemp(
path.join(os.tmpdir(), "clawdis-voicewake-"),
path.join(os.tmpdir(), "clawdbot-voicewake-"),
);
const cfg = await loadVoiceWakeConfig(baseDir);
expect(cfg.triggers).toEqual(defaultVoiceWakeTriggers());
@@ -22,7 +22,7 @@ describe("voicewake store", () => {
it("sanitizes and persists triggers", async () => {
const baseDir = await fs.mkdtemp(
path.join(os.tmpdir(), "clawdis-voicewake-"),
path.join(os.tmpdir(), "clawdbot-voicewake-"),
);
const saved = await setVoiceWakeTriggers(
[" hi ", "", " there "],
@@ -38,7 +38,7 @@ describe("voicewake store", () => {
it("falls back to defaults when triggers empty", async () => {
const baseDir = await fs.mkdtemp(
path.join(os.tmpdir(), "clawdis-voicewake-"),
path.join(os.tmpdir(), "clawdbot-voicewake-"),
);
const saved = await setVoiceWakeTriggers(["", " "], baseDir);
expect(saved.triggers).toEqual(defaultVoiceWakeTriggers());

View File

@@ -11,7 +11,7 @@ export type VoiceWakeConfig = {
const DEFAULT_TRIGGERS = ["clawd", "claude", "computer"];
function defaultBaseDir() {
return path.join(os.homedir(), ".clawdis");
return path.join(os.homedir(), ".clawdbot");
}
function resolvePath(baseDir?: string) {

View File

@@ -6,11 +6,11 @@ import {
} from "./widearea-dns.js";
describe("wide-area DNS-SD zone rendering", () => {
it("renders a clawdis.internal zone with bridge PTR/SRV/TXT records", () => {
it("renders a clawdbot.internal zone with bridge PTR/SRV/TXT records", () => {
const txt = renderWideAreaBridgeZoneText({
serial: 2025121701,
bridgePort: 18790,
displayName: "Mac Studio (Clawdis)",
displayName: "Mac Studio (Clawdbot)",
tailnetIPv4: "100.123.224.76",
tailnetIPv6: "fd7a:115c:a1e0::8801:e04c",
hostLabel: "studio-london",
@@ -21,19 +21,19 @@ describe("wide-area DNS-SD zone rendering", () => {
expect(txt).toContain(`studio-london IN A 100.123.224.76`);
expect(txt).toContain(`studio-london IN AAAA fd7a:115c:a1e0::8801:e04c`);
expect(txt).toContain(
`_clawdis-bridge._tcp IN PTR studio-london._clawdis-bridge._tcp`,
`_clawdbot-bridge._tcp IN PTR studio-london._clawdbot-bridge._tcp`,
);
expect(txt).toContain(
`studio-london._clawdis-bridge._tcp IN SRV 0 0 18790 studio-london`,
`studio-london._clawdbot-bridge._tcp IN SRV 0 0 18790 studio-london`,
);
expect(txt).toContain(`displayName=Mac Studio (Clawdis)`);
expect(txt).toContain(`displayName=Mac Studio (Clawdbot)`);
});
it("includes tailnetDns when provided", () => {
const txt = renderWideAreaBridgeZoneText({
serial: 2025121701,
bridgePort: 18790,
displayName: "Mac Studio (Clawdis)",
displayName: "Mac Studio (Clawdbot)",
tailnetIPv4: "100.123.224.76",
tailnetDns: "peters-mac-studio-1.sheep-coho.ts.net",
hostLabel: "studio-london",

View File

@@ -4,8 +4,8 @@ import path from "node:path";
import { CONFIG_DIR, ensureDir } from "../utils.js";
export const WIDE_AREA_DISCOVERY_DOMAIN = "clawdis.internal.";
export const WIDE_AREA_ZONE_FILENAME = "clawdis.internal.db";
export const WIDE_AREA_DISCOVERY_DOMAIN = "clawdbot.internal.";
export const WIDE_AREA_ZONE_FILENAME = "clawdbot.internal.db";
export function getWideAreaZonePath(): string {
return path.join(CONFIG_DIR, "dns", WIDE_AREA_ZONE_FILENAME);
@@ -54,7 +54,7 @@ function extractSerial(zoneText: string): number | null {
}
function extractContentHash(zoneText: string): string | null {
const match = zoneText.match(/^\s*;\s*clawdis-content-hash:\s*(\S+)\s*$/m);
const match = zoneText.match(/^\s*;\s*clawdbot-content-hash:\s*(\S+)\s*$/m);
return match?.[1] ?? null;
}
@@ -79,11 +79,11 @@ export type WideAreaBridgeZoneOpts = {
};
function renderZone(opts: WideAreaBridgeZoneOpts & { serial: number }): string {
const hostname = os.hostname().split(".")[0] ?? "clawdis";
const hostLabel = dnsLabel(opts.hostLabel ?? hostname, "clawdis");
const hostname = os.hostname().split(".")[0] ?? "clawdbot";
const hostLabel = dnsLabel(opts.hostLabel ?? hostname, "clawdbot");
const instanceLabel = dnsLabel(
opts.instanceLabel ?? `${hostname}-bridge`,
"clawdis-bridge",
"clawdbot-bridge",
);
const txt = [
@@ -109,13 +109,13 @@ function renderZone(opts: WideAreaBridgeZoneOpts & { serial: number }): string {
}
records.push(
`_clawdis-bridge._tcp IN PTR ${instanceLabel}._clawdis-bridge._tcp`,
`_clawdbot-bridge._tcp IN PTR ${instanceLabel}._clawdbot-bridge._tcp`,
);
records.push(
`${instanceLabel}._clawdis-bridge._tcp IN SRV 0 0 ${opts.bridgePort} ${hostLabel}`,
`${instanceLabel}._clawdbot-bridge._tcp IN SRV 0 0 ${opts.bridgePort} ${hostLabel}`,
);
records.push(
`${instanceLabel}._clawdis-bridge._tcp IN TXT ${txt.map(txtQuote).join(" ")}`,
`${instanceLabel}._clawdbot-bridge._tcp IN TXT ${txt.map(txtQuote).join(" ")}`,
);
const contentBody = `${records.join("\n")}\n`;
@@ -128,7 +128,7 @@ function renderZone(opts: WideAreaBridgeZoneOpts & { serial: number }): string {
.join("\n")}\n`;
const contentHash = computeContentHash(hashBody);
return `; clawdis-content-hash: ${contentHash}\n${contentBody}`;
return `; clawdbot-content-hash: ${contentHash}\n${contentBody}`;
}
export function renderWideAreaBridgeZoneText(