clawhouse 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amin Yekani
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # Clawhouse
2
+
3
+ **Live cost + model control for your [OpenClaw](https://openclaw.dev) fleet — in a pixel-art office your agents actually live in.**
4
+
5
+ > Part of **Clawvision** — the visualization family for OpenClaw. Clawhouse is the office; sibling apps will follow.
6
+
7
+ Other pixel-office projects show your agents walking around. This one is the only one that also tracks **what each session costs**, **which model is burning your budget**, and **lets you swap models without editing JSON**. The pixels are the hook; the cost panel is the reason to keep it open.
8
+
9
+ > _Demo GIF goes here — record with `npm run demo` and any screen recorder._
10
+
11
+ ---
12
+
13
+ ## Why this one
14
+
15
+ | | Clawhouse | [pixel-agents](https://github.com/pablodelucca/pixel-agents) | [Star-Office-UI](https://github.com/ringhyacinth/Star-Office-UI) | [agent-office](https://github.com/harishkotra/agent-office) |
16
+ |---|---|---|---|---|
17
+ | OpenClaw native (sessions, cron, sub-agents) | ✅ | ❌ Claude Code only | ✅ | ❌ Ollama |
18
+ | Live USD cost per agent / per window | ✅ | ❌ | ❌ | ❌ |
19
+ | Cost-aware room glow (red when burning hot) | ✅ | ❌ | ❌ | ❌ |
20
+ | Model switcher in-UI | ✅ | ❌ | ❌ | ❌ |
21
+ | Sub-agent visualisation | ✅ | ✅ | ❌ | ✅ |
22
+ | Speech bubbles for "needs attention" | ✅ | ✅ | ❌ | ❌ |
23
+ | Task-completion sound chime | ✅ | ✅ | ❌ | ❌ |
24
+ | Zero npm dependencies | ✅ | ❌ build chain | ❌ Python+pip | ❌ TS monorepo |
25
+ | One-command demo (no install) | ✅ `npm run demo` | ❌ | ❌ | ❌ |
26
+
27
+ ## Features at a glance
28
+
29
+ - **Live cost panel** — per-agent USD spend rolled up by current session / 24h / 30d / 365d, with provider breakdown (Anthropic / OpenAI). Subscription-aware: prorates a flat monthly fee instead of pretending sub usage is per-token billed.
30
+ - **Cost-aware room glow** — agent's room flashes amber when this session is burning ≥40% of its 24h budget, red-pulsing when ≥75%. The "is this expensive?" gut check, visible at a glance.
31
+ - **Speech bubbles** — agents call out when they crash, fail consecutively, run hot on context, or are actively thinking. Severity-coloured (red / amber / blue) so a glance tells you which room to click.
32
+ - **Sub-agent minions** — small sprites cluster next to the parent when an agent has spawned background workers. `+N` badge appears past 3.
33
+ - **Sound chime** — opt-in (🔔 button in the topbar) WebAudio ding when an agent transitions from `running` to `done`. State persists in `localStorage`.
34
+ - **Model switcher** — drop-down in the side panel calls `openclaw config set` so you can demote Opus → Sonnet → Haiku without touching `~/.openclaw/openclaw.json`.
35
+ - **Products rail** — optional launcher strip above the office grid for apps and dashboards your agents build (`products.json`).
36
+ - **Stats panel** — token usage, context %, cache hit rate, model in use, recent sessions, scheduled cron jobs, queued tasks — all the data that's already in `~/.openclaw/` rendered without the JSON.
37
+
38
+ ## Quick start
39
+
40
+ ```bash
41
+ # Run instantly with no install (demo mode)
42
+ npx clawhouse --demo
43
+
44
+ # Or clone for local dev:
45
+ git clone https://github.com/aminyekani/clawhouse.git
46
+ cd clawhouse
47
+ npm run demo # synthetic full-cast demo, no OpenClaw needed
48
+ node server.js # live mode if OpenClaw is running on this machine
49
+ ```
50
+
51
+ Open **http://localhost:18890**. Demo mode is auto-enabled when `~/.openclaw` doesn't exist, or force it with `PIXEL_OFFICE_DEMO=1`.
52
+
53
+ ## Requirements
54
+
55
+ | | |
56
+ |---|---|
57
+ | Node.js ≥ 22 | Uses built-in `node:sqlite` |
58
+ | OpenClaw | Optional — only needed for live fleet data |
59
+
60
+ ## Configuration
61
+
62
+ All configuration via environment variables — no config file:
63
+
64
+ | Variable | Default | Description |
65
+ |---|---|---|
66
+ | `PIXEL_OFFICE_PORT` | `18890` | HTTP listen port |
67
+ | `PIXEL_OFFICE_HOST` | `0.0.0.0` | Bind address (`127.0.0.1` for local-only) |
68
+ | `OPENCLAW_URL` | `http://127.0.0.1:18789/` | OpenClaw gateway URL (for model-switch actions) |
69
+ | `OPENCLAW_STATE_DIR` | `~/.openclaw` | Path to your OpenClaw state directory |
70
+ | `PIXEL_OFFICE_DEMO` | _(unset)_ | Set `1` to force demo mode |
71
+ | `PIXEL_OFFICE_MODELS` | _(built-in list)_ | JSON array of `{id, label}` to offer in the model switcher |
72
+
73
+ ## Customising your fleet
74
+
75
+ See **[docs/CUSTOMIZE.md](docs/CUSTOMIZE.md)** for step-by-step instructions on:
76
+
77
+ - Adding a new agent room (sprite, props, monitor, room theme)
78
+ - Changing an agent's appearance (skin, hair, outfit, face type, accessories)
79
+ - Writing a custom wall prop or monitor screen in the build scripts
80
+ - Adding products to the launcher rail
81
+
82
+ ## Building sprite atlases
83
+
84
+ The PNG sprite sheets are pre-built and committed, so you only need to rebuild after changing visual definitions:
85
+
86
+ ```bash
87
+ npm run build # rebuild all atlases (sprites, props, monitors, furniture, icons)
88
+ npm run build:sprites # character sprites only
89
+ npm run build:profiles # export 768×768 profile pics (Telegram-ready)
90
+ ```
91
+
92
+ ## Running as a service (systemd)
93
+
94
+ ```ini
95
+ # ~/.config/systemd/user/clawhouse.service
96
+ [Unit]
97
+ Description=Clawhouse fleet board
98
+ After=network.target
99
+
100
+ [Service]
101
+ WorkingDirectory=/path/to/clawhouse
102
+ ExecStart=/usr/bin/node server.js
103
+ Restart=on-failure
104
+ Environment=PIXEL_OFFICE_PORT=18890
105
+
106
+ [Install]
107
+ WantedBy=default.target
108
+ ```
109
+
110
+ ```bash
111
+ systemctl --user daemon-reload
112
+ systemctl --user enable --now clawhouse
113
+ ```
114
+
115
+ ## Optional: products.json
116
+
117
+ Drop a `products.json` next to `server.js` to add a launch strip above the office grid. See `products.example.json` for the full schema. Each product declares:
118
+
119
+ ```jsonc
120
+ {
121
+ "products": [
122
+ {
123
+ "id": "my-dashboard",
124
+ "agentId": "analyst",
125
+ "name": "My Dashboard",
126
+ "description": "Short blurb shown in the card.",
127
+ "status": "live",
128
+ "port": 8787,
129
+ "path": "/dashboard/",
130
+ "start": {
131
+ "cwd": "/path/to/project",
132
+ "cmd": "node",
133
+ "args": ["start.mjs"]
134
+ }
135
+ }
136
+ ]
137
+ }
138
+ ```
139
+
140
+ ## Status rules
141
+
142
+ | Age of last session activity | Status |
143
+ |---|---|
144
+ | < 1 minute | 🟢 active |
145
+ | 1–10 minutes | 🟡 idle |
146
+ | ≥ 10 minutes | ⚪ away |
147
+
148
+ ## Burn-rate rules
149
+
150
+ The room glow compares the current session's billed cost to the trailing 24h:
151
+
152
+ | `session.billed / day.billed` | Visual |
153
+ |---|---|
154
+ | < 40% | normal room glow |
155
+ | 40 – 75% | 🟠 amber static glow ("hot") |
156
+ | ≥ 75% | 🔴 red pulse glow ("critical") |
157
+
158
+ ## Speech-bubble rules
159
+
160
+ | Trigger | Variant |
161
+ |---|---|
162
+ | Last session ended mid-run (`abortedLastRun`) | 🔴 alert (pulse) |
163
+ | Same task failed ≥ 2× in a row | 🔴 alert (pulse) |
164
+ | Task issue in last 6h | 🟠 warn |
165
+ | Context window ≥ 95% full | 🟠 warn |
166
+ | Session running, agent active | 🔵 busy |
167
+ | Otherwise | personality quip (rotates each minute) |
168
+
169
+ ## License
170
+
171
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ // npx entrypoint — forwards CLI flags into env vars so `npx clawhouse`
3
+ // launches the same server.js the repo's `node server.js` does.
4
+ //
5
+ // --demo force demo mode (no ~/.openclaw needed)
6
+ // --port <n> listen port (overrides PIXEL_OFFICE_PORT)
7
+ // --host <addr> bind address (overrides PIXEL_OFFICE_HOST)
8
+ // --state-dir <d> path to OpenClaw state (overrides OPENCLAW_STATE_DIR)
9
+ //
10
+ // Anything else is passed straight through; defaults live in server.js.
11
+
12
+ const path = require('path');
13
+
14
+ const argv = process.argv.slice(2);
15
+ for (let i = 0; i < argv.length; i++) {
16
+ const flag = argv[i];
17
+ const next = argv[i + 1];
18
+ if (flag === '--demo') process.env.PIXEL_OFFICE_DEMO = '1';
19
+ else if (flag === '--port' && next) { process.env.PIXEL_OFFICE_PORT = next; i++; }
20
+ else if (flag === '--host' && next) { process.env.PIXEL_OFFICE_HOST = next; i++; }
21
+ else if (flag === '--state-dir' && next) { process.env.OPENCLAW_STATE_DIR = next; i++; }
22
+ else if (flag === '--openclaw' && next) { process.env.OPENCLAW_URL = next; i++; }
23
+ else if (flag === '--help' || flag === '-h') {
24
+ console.log('Usage: clawhouse [--demo] [--port N] [--host ADDR] [--state-dir PATH] [--openclaw URL]');
25
+ process.exit(0);
26
+ }
27
+ }
28
+
29
+ require(path.join(__dirname, '..', 'server.js'));