From 5878b15be1bb75d48ca0058d6c1311179befc012 Mon Sep 17 00:00:00 2001 From: Luciano Castillo <2213102+luccast@users.noreply.github.com> Date: Sun, 1 Feb 2026 20:03:06 -0500 Subject: [PATCH] refactor: rename clawdbot to openclaw (#32) * feat: add OpenClaw integration with client and persistence services - Introduced ClawdbotClient for WebSocket communication with the OpenClaw gateway. - Implemented persistence service for managing session, action, and execution event data. - Added protocol definitions for request and response frames, chat and agent events. - Created utility functions for parsing events and managing collections of sessions and actions. - Included initial documentation for the OpenClaw repository structure and usage. * refactor: update references from Clawdbot to OpenClaw - Renamed instances of Clawdbot to OpenClaw across documentation and codebase. - Updated file paths and configuration references to reflect the new OpenClaw integration. - Adjusted WebSocket connection messages and error handling to align with OpenClaw terminology. - Enhanced README and other documentation to provide accurate information regarding the OpenClaw setup and usage. --- CLAUDE.md | 6 +-- README.md | 10 ++--- bin/crabwalk | 4 +- .../{clawdbot-repo.md => openclaw-repo.md} | 6 +-- public/skill.md | 2 +- src/components/monitor/ActionGraph.tsx | 2 +- src/components/monitor/ActionNode.tsx | 2 +- src/components/monitor/ExecNode.tsx | 2 +- src/components/monitor/SessionList.tsx | 2 +- src/components/monitor/SessionNode.tsx | 2 +- .../{clawdbot => openclaw}/client.ts | 4 +- .../{clawdbot => openclaw}/collections.ts | 6 +-- .../{clawdbot => openclaw}/index.ts | 0 .../{clawdbot => openclaw}/parser.ts | 0 .../{clawdbot => openclaw}/persistence.ts | 0 .../{clawdbot => openclaw}/protocol.ts | 0 src/integrations/trpc/router.ts | 18 ++++----- src/lib/graph-layout.ts | 2 +- src/routes/index.tsx | 2 +- src/routes/monitor/index.tsx | 38 +++++++++---------- 20 files changed, 54 insertions(+), 54 deletions(-) rename documents/{clawdbot-repo.md => openclaw-repo.md} (95%) rename src/integrations/{clawdbot => openclaw}/client.ts (98%) rename src/integrations/{clawdbot => openclaw}/collections.ts (99%) rename src/integrations/{clawdbot => openclaw}/index.ts (100%) rename src/integrations/{clawdbot => openclaw}/parser.ts (100%) rename src/integrations/{clawdbot => openclaw}/persistence.ts (100%) rename src/integrations/{clawdbot => openclaw}/protocol.ts (100%) diff --git a/CLAUDE.md b/CLAUDE.md index a63b5cc..42f940d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -36,15 +36,15 @@ Full-stack React app using TanStack Start (file-based routing, SSR). **TanStack DB pattern:** Create collections, use `useLiveQuery()` for reactive reads, `createTransaction()` for writes. -## Moltbot (Clawdbot) Monitor +## OpenClaw (Clawdbot) Monitor Real-time agent activity monitor at `/monitor`. **Key paths:** -- `src/integrations/clawdbot/` - gateway client, protocol types, parser, collections +- `src/integrations/openclaw/` - gateway client, protocol types, parser, collections - `src/components/monitor/` - ReactFlow graph, session list, custom nodes - `src/routes/monitor/index.tsx` - main monitor page -**Data flow:** clawdbot gateway (ws://127.0.0.1:18789) -> TanStack Start server (WS client) -> tRPC -> browser (TanStack DB collections -> ReactFlow) +**Data flow:** openclaw gateway (ws://127.0.0.1:18789) -> TanStack Start server (WS client) -> tRPC -> browser (TanStack DB collections -> ReactFlow) **Config:** Set `CLAWDBOT_API_TOKEN` env var for gateway auth. diff --git a/README.md b/README.md index 78edb53..1ab9c2e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Watch your AI agents work across WhatsApp, Telegram, Discord, and Slack in a liv - **Live activity graph** - ReactFlow visualization of agent sessions and action chains - **Multi-platform** - Monitor agents across all messaging platforms simultaneously -- **Real-time streaming** - WebSocket connection to clawdbot gateway +- **Real-time streaming** - WebSocket connection to openclaw gateway - **Action tracing** - Expand nodes to inspect tool args and payloads - **Session filtering** - Filter by platform, search by recipient @@ -115,23 +115,23 @@ Requires OpenClaw gateway running on the same machine. ### Gateway Token -Find your token in the clawdbot config file: +Find your token in the openclaw config file: ```bash # Look for gateway.auth.token -cat ~/.clawdbot/clawdbot.json | rg "gateway\.auth\.token" +cat ~/.openclaw/openclaw.json | rg "gateway\.auth\.token" ``` Or with jq: ```bash -jq '.gateway.auth.token' ~/.clawdbot/clawdbot.json +jq '.gateway.auth.token' ~/.openclaw/openclaw.json ``` Or copy it directly: ```bash -export CLAWDBOT_API_TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.clawdbot/clawdbot.json')))['gateway']['auth']['token'])") +export CLAWDBOT_API_TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.openclaw/openclaw.json')))['gateway']['auth']['token'])") ``` ## Stack diff --git a/bin/crabwalk b/bin/crabwalk index 7e41c08..767b688 100755 --- a/bin/crabwalk +++ b/bin/crabwalk @@ -21,8 +21,8 @@ get_version() { # Auto-detect token from OpenClaw config auto_token() { - if [ -f "$HOME/.clawdbot/clawdbot.json" ]; then - python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.clawdbot/clawdbot.json')))['gateway']['auth']['token'])" 2>/dev/null || true + if [ -f "$HOME/.openclaw/openclaw.json" ]; then + python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.openclaw/openclaw.json')))['gateway']['auth']['token'])" 2>/dev/null || true fi } diff --git a/documents/clawdbot-repo.md b/documents/openclaw-repo.md similarity index 95% rename from documents/clawdbot-repo.md rename to documents/openclaw-repo.md index c2b8091..d7b0cc9 100644 --- a/documents/clawdbot-repo.md +++ b/documents/openclaw-repo.md @@ -1,9 +1,9 @@ # Overview -Repo: clawdbot/clawdbot +Repo: openclaw/openclaw Ref: 50b4126c79536a9645cddcfe6801916b5f6d9343 -Base URL: https://codebase.md/clawdbot/clawdbot +Base URL: https://codebase.md/openclaw/openclaw Note: This repo is currently being built in the background. -Status: /status/clawdbot/clawdbot/50b4126c79536a9645cddcfe6801916b5f6d9343 +Status: /status/openclaw/openclaw/50b4126c79536a9645cddcfe6801916b5f6d9343 Estimated build time: ~96 seconds. Try again in 60 seconds. diff --git a/public/skill.md b/public/skill.md index 3fa032f..e436ce1 100644 --- a/public/skill.md +++ b/public/skill.md @@ -58,7 +58,7 @@ Options: -p, --port Server port (default: 3000) -H, --host Bind address (default: 0.0.0.0) -g, --gateway Gateway WebSocket URL - -t, --token Gateway auth token (auto-detects from ~/.clawdbot/clawdbot.json) + -t, --token Gateway auth token (auto-detects from ~/.openclaw/openclaw.json) -d, --daemon Run in background -v, --version Show version -h, --help Show help diff --git a/src/components/monitor/ActionGraph.tsx b/src/components/monitor/ActionGraph.tsx index 5b4cd25..badba8d 100644 --- a/src/components/monitor/ActionGraph.tsx +++ b/src/components/monitor/ActionGraph.tsx @@ -27,7 +27,7 @@ import type { MonitorSession, MonitorAction, MonitorExecProcess, -} from '~/integrations/clawdbot' +} from '~/integrations/openclaw' interface ActionGraphProps { sessions: MonitorSession[] diff --git a/src/components/monitor/ActionNode.tsx b/src/components/monitor/ActionNode.tsx index 076f825..039083e 100644 --- a/src/components/monitor/ActionNode.tsx +++ b/src/components/monitor/ActionNode.tsx @@ -11,7 +11,7 @@ import { MessageCircle, Bot, } from 'lucide-react' -import type { MonitorAction } from '~/integrations/clawdbot' +import type { MonitorAction } from '~/integrations/openclaw' interface ActionNodeProps { data: MonitorAction diff --git a/src/components/monitor/ExecNode.tsx b/src/components/monitor/ExecNode.tsx index 43264eb..9855821 100644 --- a/src/components/monitor/ExecNode.tsx +++ b/src/components/monitor/ExecNode.tsx @@ -2,7 +2,7 @@ import { memo, useCallback, useMemo, useState } from 'react' import { Handle, Position } from '@xyflow/react' import { motion, AnimatePresence } from 'framer-motion' import { CheckCircle, Copy, Check, Loader2, Terminal, XCircle } from 'lucide-react' -import type { MonitorExecProcess, MonitorExecOutputChunk } from '~/integrations/clawdbot' +import type { MonitorExecProcess, MonitorExecOutputChunk } from '~/integrations/openclaw' interface ExecNodeProps { data: MonitorExecProcess diff --git a/src/components/monitor/SessionList.tsx b/src/components/monitor/SessionList.tsx index 6f1eb62..62f21ee 100644 --- a/src/components/monitor/SessionList.tsx +++ b/src/components/monitor/SessionList.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { Users, ChevronLeft, ChevronRight, ChevronDown, Github } from "lucide-react"; import { StatusIndicator } from "./StatusIndicator"; -import type { MonitorSession } from "~/integrations/clawdbot"; +import type { MonitorSession } from "~/integrations/openclaw"; function isSubagent(session: MonitorSession): boolean { return Boolean(session.spawnedBy) || session.platform === "subagent" || session.key.includes("subagent"); diff --git a/src/components/monitor/SessionNode.tsx b/src/components/monitor/SessionNode.tsx index 88c3c52..b0563ee 100644 --- a/src/components/monitor/SessionNode.tsx +++ b/src/components/monitor/SessionNode.tsx @@ -3,7 +3,7 @@ import { Handle, Position } from '@xyflow/react' import { motion, AnimatePresence } from 'framer-motion' import { Users, User, Clock, Copy, Check } from 'lucide-react' import { StatusIndicator } from './StatusIndicator' -import type { MonitorSession } from '~/integrations/clawdbot' +import type { MonitorSession } from '~/integrations/openclaw' interface SessionNodeProps { data: MonitorSession diff --git a/src/integrations/clawdbot/client.ts b/src/integrations/openclaw/client.ts similarity index 98% rename from src/integrations/clawdbot/client.ts rename to src/integrations/openclaw/client.ts index e56cdd8..e1e7cde 100644 --- a/src/integrations/clawdbot/client.ts +++ b/src/integrations/openclaw/client.ts @@ -49,7 +49,7 @@ export class ClawdbotClient { const timeout = setTimeout(() => { this._connecting = false this.ws?.close() - reject(new Error('Connection timeout - is clawdbot gateway running?')) + reject(new Error('Connection timeout - is openclaw gateway running?')) }, 10000) try { @@ -77,7 +77,7 @@ export class ClawdbotClient { this.handleMessage(msg, resolve, reject, timeout) } catch (e) { - console.error('[clawdbot] Failed to parse message:', e) + console.error('[openclaw] Failed to parse message:', e) } }) diff --git a/src/integrations/clawdbot/collections.ts b/src/integrations/openclaw/collections.ts similarity index 99% rename from src/integrations/clawdbot/collections.ts rename to src/integrations/openclaw/collections.ts index 6ed7ca4..18018d3 100644 --- a/src/integrations/clawdbot/collections.ts +++ b/src/integrations/openclaw/collections.ts @@ -84,21 +84,21 @@ function inferSpawnedBy(subagentKey: string, timestamp?: number): string | undef export const sessionsCollection = createCollection( localOnlyCollectionOptions({ - id: 'clawdbot-sessions', + id: 'openclaw-sessions', getKey: (item) => item.key, }) ) export const actionsCollection = createCollection( localOnlyCollectionOptions({ - id: 'clawdbot-actions', + id: 'openclaw-actions', getKey: (item) => item.id, }) ) export const execsCollection = createCollection( localOnlyCollectionOptions({ - id: 'clawdbot-execs', + id: 'openclaw-execs', getKey: (item) => item.id, }) ) diff --git a/src/integrations/clawdbot/index.ts b/src/integrations/openclaw/index.ts similarity index 100% rename from src/integrations/clawdbot/index.ts rename to src/integrations/openclaw/index.ts diff --git a/src/integrations/clawdbot/parser.ts b/src/integrations/openclaw/parser.ts similarity index 100% rename from src/integrations/clawdbot/parser.ts rename to src/integrations/openclaw/parser.ts diff --git a/src/integrations/clawdbot/persistence.ts b/src/integrations/openclaw/persistence.ts similarity index 100% rename from src/integrations/clawdbot/persistence.ts rename to src/integrations/openclaw/persistence.ts diff --git a/src/integrations/clawdbot/protocol.ts b/src/integrations/openclaw/protocol.ts similarity index 100% rename from src/integrations/clawdbot/protocol.ts rename to src/integrations/openclaw/protocol.ts diff --git a/src/integrations/trpc/router.ts b/src/integrations/trpc/router.ts index cd13bbb..a08cae9 100644 --- a/src/integrations/trpc/router.ts +++ b/src/integrations/trpc/router.ts @@ -2,15 +2,15 @@ import { initTRPC } from '@trpc/server' import { observable } from '@trpc/server/observable' import superjson from 'superjson' import { z } from 'zod' -import { getClawdbotClient } from '~/integrations/clawdbot/client' -import { getPersistenceService } from '~/integrations/clawdbot/persistence' +import { getClawdbotClient } from '~/integrations/openclaw/client' +import { getPersistenceService } from '~/integrations/openclaw/persistence' import { parseEventFrame, sessionInfoToMonitor, type MonitorSession, type MonitorAction, type MonitorExecEvent, -} from '~/integrations/clawdbot' +} from '~/integrations/openclaw' import { listDirectory, readFile, @@ -36,7 +36,7 @@ export const router = t.router export const publicProcedure = t.procedure // Clawdbot router -const clawdbotRouter = router({ +const openclawRouter = router({ connect: publicProcedure.mutation(async () => { const client = getClawdbotClient() if (client.connected) { @@ -73,7 +73,7 @@ const clawdbotRouter = router({ .input(z.object({ enabled: z.boolean() })) .mutation(({ input }) => { debugMode = input.enabled - console.log(`[clawdbot] debug mode ${debugMode ? 'enabled' : 'disabled'}`) + console.log(`[openclaw] debug mode ${debugMode ? 'enabled' : 'disabled'}`) return { debugMode } }), @@ -87,9 +87,9 @@ const clawdbotRouter = router({ .mutation(({ input }) => { collectLogs = input.enabled if (input.enabled) { - console.log(`[clawdbot] log collection started`) + console.log(`[openclaw] log collection started`) } else { - console.log(`[clawdbot] log collection stopped, ${collectedEvents.length} events collected`) + console.log(`[openclaw] log collection stopped, ${collectedEvents.length} events collected`) } return { collectLogs, eventCount: collectedEvents.length } }), @@ -109,7 +109,7 @@ const clawdbotRouter = router({ clearLogs: publicProcedure.mutation(() => { const count = collectedEvents.length collectedEvents.length = 0 - console.log(`[clawdbot] cleared ${count} collected events`) + console.log(`[openclaw] cleared ${count} collected events`) return { cleared: count } }), @@ -303,7 +303,7 @@ export const appRouter = router({ ] }), - clawdbot: clawdbotRouter, + openclaw: openclawRouter, workspace: workspaceRouter, }) diff --git a/src/lib/graph-layout.ts b/src/lib/graph-layout.ts index 09a6e1a..f491791 100644 --- a/src/lib/graph-layout.ts +++ b/src/lib/graph-layout.ts @@ -3,7 +3,7 @@ import type { MonitorSession, MonitorAction, MonitorExecProcess, -} from '~/integrations/clawdbot' +} from '~/integrations/openclaw' /** Cast domain data to ReactFlow's Node data type */ function nodeData(data: T): Record { diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 9b11cef..1e9c38a 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -123,7 +123,7 @@ function Home() { transition={{ duration: 0.5, delay: 0.3 }} className="font-console font-bold text-lg text-gray-400 mb-4 tracking-wide uppercase" > - Open-Source Moltbot (Clawdbot) Companion + Open-Source OpenClaw Companion {/* Console-style description */} diff --git a/src/routes/monitor/index.tsx b/src/routes/monitor/index.tsx index 6033bfb..559b1a9 100644 --- a/src/routes/monitor/index.tsx +++ b/src/routes/monitor/index.tsx @@ -15,7 +15,7 @@ import { clearCollections, hydrateFromServer, clearCompletedExecs, -} from '~/integrations/clawdbot' +} from '~/integrations/openclaw' import { ActionGraph, SessionList, @@ -112,7 +112,7 @@ function MonitorPage() { const checkPersistenceStatus = async () => { try { - const status = await trpc.clawdbot.persistenceStatus.query() + const status = await trpc.openclaw.persistenceStatus.query() setPersistenceEnabled(status.enabled) setPersistenceStartedAt(status.startedAt) setPersistenceSessionCount(status.sessionCount) @@ -124,7 +124,7 @@ function MonitorPage() { const checkStatus = async () => { try { - const status = await trpc.clawdbot.status.query() + const status = await trpc.openclaw.status.query() setConnected(status.connected) } catch { setConnected(false) @@ -135,7 +135,7 @@ function MonitorPage() { setConnecting(true) setRetryCount(retry) try { - const result = await trpc.clawdbot.connect.mutate() + const result = await trpc.openclaw.connect.mutate() if (result.status === 'connected' || result.status === 'already_connected') { setConnected(true) setRetryCount(0) @@ -158,9 +158,9 @@ function MonitorPage() { const hydrateFromPersistence = async () => { try { - const status = await trpc.clawdbot.persistenceStatus.query() + const status = await trpc.openclaw.persistenceStatus.query() if (status.sessionCount > 0 || status.actionCount > 0 || status.execEventCount > 0) { - const data = await trpc.clawdbot.persistenceHydrate.query() + const data = await trpc.openclaw.persistenceHydrate.query() hydrateFromServer(data.sessions, data.actions, data.execEvents ?? []) console.log( `[monitor] hydrated ${data.sessions.length} sessions, ${data.actions.length} actions, ${(data.execEvents ?? []).length} exec events` @@ -177,7 +177,7 @@ function MonitorPage() { const handleDisconnect = async () => { try { - await trpc.clawdbot.disconnect.mutate() + await trpc.openclaw.disconnect.mutate() setConnected(false) clearCollections() } catch (e) { @@ -187,7 +187,7 @@ function MonitorPage() { const loadSessions = async () => { try { - const result = await trpc.clawdbot.sessions.query( + const result = await trpc.openclaw.sessions.query( historicalMode ? { activeMinutes: 1440 } : { activeMinutes: 60 } ) if (result.sessions) { @@ -214,7 +214,7 @@ function MonitorPage() { const handleDebugModeChange = async (enabled: boolean) => { setDebugMode(enabled) try { - await trpc.clawdbot.setDebugMode.mutate({ enabled }) + await trpc.openclaw.setDebugMode.mutate({ enabled }) } catch (e) { console.error('Failed to set debug mode:', e) } @@ -223,7 +223,7 @@ function MonitorPage() { const handleLogCollectionChange = async (enabled: boolean) => { setLogCollection(enabled) try { - const result = await trpc.clawdbot.setLogCollection.mutate({ enabled }) + const result = await trpc.openclaw.setLogCollection.mutate({ enabled }) setLogCount(result.eventCount) } catch (e) { console.error('Failed to set log collection:', e) @@ -232,12 +232,12 @@ function MonitorPage() { const handleDownloadLogs = async () => { try { - const result = await trpc.clawdbot.downloadLogs.query() + const result = await trpc.openclaw.downloadLogs.query() const blob = new Blob([JSON.stringify(result, null, 2)], { type: 'application/json' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url - a.download = `clawdbot-events-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.json` + a.download = `openclaw-events-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.json` document.body.appendChild(a) a.click() document.body.removeChild(a) @@ -249,7 +249,7 @@ function MonitorPage() { const handleClearLogs = async () => { try { - await trpc.clawdbot.clearLogs.mutate() + await trpc.openclaw.clearLogs.mutate() setLogCount(0) } catch (e) { console.error('Failed to clear logs:', e) @@ -258,7 +258,7 @@ function MonitorPage() { const handlePersistenceStart = async () => { try { - const result = await trpc.clawdbot.persistenceStart.mutate() + const result = await trpc.openclaw.persistenceStart.mutate() setPersistenceEnabled(result.enabled) setPersistenceStartedAt(result.startedAt) } catch (e) { @@ -268,7 +268,7 @@ function MonitorPage() { const handlePersistenceStop = async () => { try { - const result = await trpc.clawdbot.persistenceStop.mutate() + const result = await trpc.openclaw.persistenceStop.mutate() setPersistenceEnabled(result.enabled) setPersistenceStartedAt(null) } catch (e) { @@ -278,7 +278,7 @@ function MonitorPage() { const handlePersistenceClear = async () => { try { - await trpc.clawdbot.persistenceClear.mutate() + await trpc.openclaw.persistenceClear.mutate() setPersistenceSessionCount(0) setPersistenceActionCount(0) clearCollections() @@ -292,7 +292,7 @@ function MonitorPage() { if (!logCollection) return const interval = setInterval(async () => { try { - const result = await trpc.clawdbot.getLogCollection.query() + const result = await trpc.openclaw.getLogCollection.query() setLogCount(result.eventCount) } catch { // ignore @@ -305,7 +305,7 @@ function MonitorPage() { useEffect(() => { const interval = setInterval(async () => { try { - const status = await trpc.clawdbot.persistenceStatus.query() + const status = await trpc.openclaw.persistenceStatus.query() setPersistenceEnabled(status.enabled) setPersistenceStartedAt(status.startedAt) setPersistenceSessionCount(status.sessionCount) @@ -341,7 +341,7 @@ function MonitorPage() { useEffect(() => { if (!connected) return - const subscription = trpc.clawdbot.events.subscribe(undefined, { + const subscription = trpc.openclaw.events.subscribe(undefined, { onData: (data) => { if (data.type === 'session' && data.session?.key && data.session.status) { updateSessionStatus(data.session.key, data.session.status)