Compare commits

...
Author SHA1 Message Date
luccast f5eb110123 docs: add comment about cumulative delta behavior 2026-01-28 09:32:07 -05:00
Ubuntu 9181d11047 fix: replace streaming content instead of appending
Clawdbot gateway sends cumulative text with each delta event
(full message so far), not incremental characters. The previous
append logic caused duplicated/garbled text in chat nodes.
2026-01-27 17:55:28 +00:00
luccast 2155d0cffa Update references from Clawdbot to Moltbot in documentation and UI
- Changed "Clawdbot" to "Moltbot (Clawdbot)" in CLAUDE.md and README.md for consistency.
- Updated the title in the Home component to reflect the new naming convention.
2026-01-27 10:27:07 -05:00
luccast a132a33c6b 1.0.4 2026-01-27 09:43:33 -05:00
Luciano Castillo c39ae8a375 Merge pull request #6 from llirik0/fix/docker-image-runtime
fix(docker): make image runnable + document CLAWDBOT_URL
2026-01-27 06:46:25 -05:00
Kirill 6811bf7c60 fix(docker): make image runnable + document CLAWDBOT_URL 2026-01-26 23:50:17 -08:00
8 changed files with 31 additions and 33 deletions
+1 -1
View File
@@ -36,7 +36,7 @@ Full-stack React app using TanStack Start (file-based routing, SSR).
**TanStack DB pattern:** Create collections, use `useLiveQuery()` for reactive reads, `createTransaction()` for writes.
## Clawdbot Monitor
## Moltbot (Clawdbot) Monitor
Real-time agent activity monitor at `/monitor`.
+10 -4
View File
@@ -9,16 +9,22 @@ RUN npm ci
COPY . .
RUN npm run build
# Production stage
# Runtime stage
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# NOTE: TanStack Start server entry produced by `vite build` does not bind a port
# on its own in this repo, so we run the Vite dev server in Docker for now.
# This makes the published image functional while we figure out a proper prod server.
ENV NODE_ENV=development
COPY package*.json ./
RUN npm ci
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
EXPOSE 3000
CMD ["node", "dist/server/server.js"]
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0", "--port", "3000"]
+9 -4
View File
@@ -1,6 +1,6 @@
# 🦀 Crabwalk
Real-time companion monitor for [Clawdbot](https://github.com/clawdbot/clawdbot) agents by [@luccasveg](https://x.com/luccasveg).
Real-time companion monitor for [Moltbot (Clawdbot)](https://github.com/moltbot/moltbot) agents by [@luccasveg](https://x.com/luccasveg).
Watch your AI agents work across WhatsApp, Telegram, Discord, and Slack in a live node graph. See thinking states, tool calls, and response chains as they happen.
@@ -24,14 +24,18 @@ Watch your AI agents work across WhatsApp, Telegram, Discord, and Slack in a liv
docker run -d \
-p 3000:3000 \
-e CLAWDBOT_API_TOKEN=your-token \
-e CLAWDBOT_URL=ws://host.docker.internal:18789 \
ghcr.io/luccast/crabwalk:latest
```
> Note: When running Crabwalk in Docker, the Clawdbot gateway typically runs on the *host*.
> Use `CLAWDBOT_URL=ws://host.docker.internal:18789` so the container can connect.
Or with docker-compose:
```bash
curl -O https://raw.githubusercontent.com/luccast/crabwalk/master/docker-compose.yml
CLAWDBOT_API_TOKEN=your-token docker-compose up -d
CLAWDBOT_API_TOKEN=your-token CLAWDBOT_URL=ws://host.docker.internal:18789 docker-compose up -d
```
### From source
@@ -54,13 +58,14 @@ Requires clawdbot gateway running on the same machine.
Find your token in the clawdbot config file:
```bash
cat ~/.clawdbot/clawdbot.json | grep api_token
# Look for gateway.auth.token
cat ~/.clawdbot/clawdbot.json | rg "gateway\.auth\.token"
```
Or copy it directly:
```bash
export CLAWDBOT_API_TOKEN=$(cat ~/.clawdbot/clawdbot.json | grep -o '"api_token": *"[^"]*"' | cut -d'"' -f4)
export CLAWDBOT_API_TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.clawdbot/clawdbot.json')))['gateway']['auth']['token'])")
```
## Stack
+4 -19
View File
@@ -1,14 +1,15 @@
{
"name": "crabwalk",
"version": "1.0.3",
"version": "1.0.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "crabwalk",
"version": "1.0.3",
"version": "1.0.4",
"dependencies": {
"@tanstack/db": "^0.5.0",
"@tanstack/history": "^1.132.0",
"@tanstack/react-db": "^0.1.0",
"@tanstack/react-query": "^5.0.0",
"@tanstack/react-router": "^1.132.0",
@@ -69,7 +70,6 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz",
"integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.28.6",
"@babel/generator": "^7.28.6",
@@ -1547,7 +1547,6 @@
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.20.tgz",
"integrity": "sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@tanstack/query-core": "5.90.20"
},
@@ -1582,7 +1581,6 @@
"resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.157.13.tgz",
"integrity": "sha512-rLr6swdDhLjadAHbukg/XYurNi4q8AmmjP99QiWUnhRPKfrfmQ/O1UCvaowQ9GcaiyOG2COiJ9OlDAQU3k9MFQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@tanstack/history": "1.154.14",
"@tanstack/react-store": "^0.8.0",
@@ -1729,7 +1727,6 @@
"resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.157.13.tgz",
"integrity": "sha512-dl1avpRH2Pi1tYhxDzGEqI6DU9VQUf5zBeW1JJFs3LfJuVkGd2lG93dSUzH9seJNp77hm8JWhoX+k4QYMEB6KA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@tanstack/history": "1.154.14",
"@tanstack/store": "^0.8.0",
@@ -2040,7 +2037,6 @@
"https://trpc.io/sponsor"
],
"license": "MIT",
"peer": true,
"peerDependencies": {
"typescript": ">=5.7.2"
}
@@ -2208,7 +2204,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.9.tgz",
"integrity": "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==",
"license": "MIT",
"peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -2437,7 +2432,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -2672,8 +2666,7 @@
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/d3-color": {
"version": "3.1.0",
@@ -2732,7 +2725,6 @@
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"license": "ISC",
"peer": true,
"engines": {
"node": ">=12"
}
@@ -4576,7 +4568,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -4586,7 +4577,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -4786,7 +4776,6 @@
"resolved": "https://registry.npmjs.org/seroval/-/seroval-1.5.0.tgz",
"integrity": "sha512-OE4cvmJ1uSPrKorFIH9/w/Qwuvi/IMcGbv5RKgcJ/zjA/IohDLU6SVaxFN9FwajbP7nsX0dQqMDes1whk3y+yw==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=10"
}
@@ -4964,7 +4953,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -5054,7 +5042,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -5271,7 +5258,6 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@@ -5382,7 +5368,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "crabwalk",
"version": "1.0.3",
"version": "1.0.4",
"private": true,
"type": "module",
"scripts": {
@@ -28,7 +28,8 @@
"superjson": "^2.2.0",
"vite-tsconfig-paths": "^5.1.4",
"ws": "^8.19.0",
"zod": "^3.24.0"
"zod": "^3.24.0",
"@tanstack/history": "^1.132.0"
},
"devDependencies": {
"@tailwindcss/vite": "^4.0.0",
+2 -2
View File
@@ -67,10 +67,10 @@ export function addAction(action: MonitorAction) {
const streamingId = `${action.runId}-stream`
const existing = actionsCollection.state.get(streamingId)
if (existing) {
// Append content and update sessionKey if we learned it
// Replace content (gateway sends cumulative text, not incremental deltas)
actionsCollection.update(streamingId, (draft) => {
if (action.content) {
draft.content = (draft.content || '') + action.content
draft.content = action.content
}
draft.seq = action.seq
draft.timestamp = action.timestamp
+1
View File
@@ -60,6 +60,7 @@ export interface PresenceEntry {
}
// Chat events
// Note: gateway sends cumulative message content with each delta, not incremental chars
export interface ChatEvent {
runId: string
sessionKey: string
+1 -1
View File
@@ -122,7 +122,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 Clawdbot Companion
Open-Source Moltbot (Clawdbot) Companion
</motion.p>
{/* Console-style description */}