@rozek/nanoclaw 1.2.17

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.
Files changed (305) hide show
  1. package/.claude/settings.json +1 -0
  2. package/.claude/skills/add-compact/SKILL.md +135 -0
  3. package/.claude/skills/add-discord/SKILL.md +203 -0
  4. package/.claude/skills/add-gmail/SKILL.md +220 -0
  5. package/.claude/skills/add-image-vision/SKILL.md +94 -0
  6. package/.claude/skills/add-ollama-tool/SKILL.md +153 -0
  7. package/.claude/skills/add-parallel/SKILL.md +290 -0
  8. package/.claude/skills/add-pdf-reader/SKILL.md +104 -0
  9. package/.claude/skills/add-reactions/SKILL.md +117 -0
  10. package/.claude/skills/add-slack/SKILL.md +207 -0
  11. package/.claude/skills/add-telegram/SKILL.md +222 -0
  12. package/.claude/skills/add-telegram-swarm/SKILL.md +384 -0
  13. package/.claude/skills/add-voice-transcription/SKILL.md +148 -0
  14. package/.claude/skills/add-whatsapp/SKILL.md +372 -0
  15. package/.claude/skills/convert-to-apple-container/SKILL.md +175 -0
  16. package/.claude/skills/customize/SKILL.md +110 -0
  17. package/.claude/skills/debug/SKILL.md +349 -0
  18. package/.claude/skills/get-qodo-rules/SKILL.md +122 -0
  19. package/.claude/skills/get-qodo-rules/references/output-format.md +41 -0
  20. package/.claude/skills/get-qodo-rules/references/pagination.md +33 -0
  21. package/.claude/skills/get-qodo-rules/references/repository-scope.md +26 -0
  22. package/.claude/skills/qodo-pr-resolver/SKILL.md +326 -0
  23. package/.claude/skills/qodo-pr-resolver/resources/providers.md +329 -0
  24. package/.claude/skills/setup/SKILL.md +218 -0
  25. package/.claude/skills/update-nanoclaw/SKILL.md +235 -0
  26. package/.claude/skills/update-skills/SKILL.md +130 -0
  27. package/.claude/skills/use-local-whisper/SKILL.md +152 -0
  28. package/.claude/skills/x-integration/SKILL.md +417 -0
  29. package/.claude/skills/x-integration/agent.ts +243 -0
  30. package/.claude/skills/x-integration/host.ts +159 -0
  31. package/.claude/skills/x-integration/lib/browser.ts +148 -0
  32. package/.claude/skills/x-integration/lib/config.ts +62 -0
  33. package/.claude/skills/x-integration/scripts/like.ts +56 -0
  34. package/.claude/skills/x-integration/scripts/post.ts +66 -0
  35. package/.claude/skills/x-integration/scripts/quote.ts +80 -0
  36. package/.claude/skills/x-integration/scripts/reply.ts +74 -0
  37. package/.claude/skills/x-integration/scripts/retweet.ts +62 -0
  38. package/.claude/skills/x-integration/scripts/setup.ts +87 -0
  39. package/.env.example +1 -0
  40. package/.github/CODEOWNERS +10 -0
  41. package/.github/PULL_REQUEST_TEMPLATE.md +14 -0
  42. package/.github/workflows/bump-version.yml +32 -0
  43. package/.github/workflows/ci.yml +25 -0
  44. package/.github/workflows/merge-forward-skills.yml +160 -0
  45. package/.github/workflows/update-tokens.yml +42 -0
  46. package/.husky/pre-commit +1 -0
  47. package/.mcp.json +3 -0
  48. package/.nvmrc +1 -0
  49. package/.prettierrc +3 -0
  50. package/CHANGELOG.md +8 -0
  51. package/CLAUDE.md +64 -0
  52. package/CONTRIBUTING.md +23 -0
  53. package/CONTRIBUTORS.md +15 -0
  54. package/LICENSE +21 -0
  55. package/NanoClaw_with_Web-Support.md +290 -0
  56. package/README.md +261 -0
  57. package/README_zh.md +200 -0
  58. package/assets/nanoclaw-favicon.png +0 -0
  59. package/assets/nanoclaw-icon.png +0 -0
  60. package/assets/nanoclaw-logo-dark.png +0 -0
  61. package/assets/nanoclaw-logo.png +0 -0
  62. package/assets/nanoclaw-profile.jpeg +0 -0
  63. package/assets/nanoclaw-sales.png +0 -0
  64. package/assets/social-preview.jpg +0 -0
  65. package/config-examples/mount-allowlist.json +25 -0
  66. package/container/Dockerfile +70 -0
  67. package/container/agent-runner/package-lock.json +1524 -0
  68. package/container/agent-runner/package.json +21 -0
  69. package/container/agent-runner/src/index.ts +558 -0
  70. package/container/agent-runner/src/ipc-mcp-stdio.ts +338 -0
  71. package/container/agent-runner/tsconfig.json +15 -0
  72. package/container/build.sh +23 -0
  73. package/container/skills/agent-browser/SKILL.md +159 -0
  74. package/container/skills/capabilities/SKILL.md +100 -0
  75. package/container/skills/status/SKILL.md +104 -0
  76. package/dist/channels/index.d.ts +2 -0
  77. package/dist/channels/index.d.ts.map +1 -0
  78. package/dist/channels/index.js +9 -0
  79. package/dist/channels/index.js.map +1 -0
  80. package/dist/channels/registry.d.ts +13 -0
  81. package/dist/channels/registry.d.ts.map +1 -0
  82. package/dist/channels/registry.js +11 -0
  83. package/dist/channels/registry.js.map +1 -0
  84. package/dist/channels/registry.test.d.ts +2 -0
  85. package/dist/channels/registry.test.d.ts.map +1 -0
  86. package/dist/channels/registry.test.js +32 -0
  87. package/dist/channels/registry.test.js.map +1 -0
  88. package/dist/channels/web.d.ts +2 -0
  89. package/dist/channels/web.d.ts.map +1 -0
  90. package/dist/channels/web.js +1738 -0
  91. package/dist/channels/web.js.map +1 -0
  92. package/dist/cli.d.ts +11 -0
  93. package/dist/cli.d.ts.map +1 -0
  94. package/dist/cli.js +182 -0
  95. package/dist/cli.js.map +1 -0
  96. package/dist/config.d.ts +19 -0
  97. package/dist/config.d.ts.map +1 -0
  98. package/dist/config.js +36 -0
  99. package/dist/config.js.map +1 -0
  100. package/dist/container-runner.d.ts +44 -0
  101. package/dist/container-runner.d.ts.map +1 -0
  102. package/dist/container-runner.js +467 -0
  103. package/dist/container-runner.js.map +1 -0
  104. package/dist/container-runner.test.d.ts +2 -0
  105. package/dist/container-runner.test.d.ts.map +1 -0
  106. package/dist/container-runner.test.js +150 -0
  107. package/dist/container-runner.test.js.map +1 -0
  108. package/dist/container-runtime.d.ts +22 -0
  109. package/dist/container-runtime.d.ts.map +1 -0
  110. package/dist/container-runtime.js +96 -0
  111. package/dist/container-runtime.js.map +1 -0
  112. package/dist/container-runtime.test.d.ts +2 -0
  113. package/dist/container-runtime.test.d.ts.map +1 -0
  114. package/dist/container-runtime.test.js +93 -0
  115. package/dist/container-runtime.test.js.map +1 -0
  116. package/dist/credential-proxy.d.ts +21 -0
  117. package/dist/credential-proxy.d.ts.map +1 -0
  118. package/dist/credential-proxy.js +95 -0
  119. package/dist/credential-proxy.js.map +1 -0
  120. package/dist/credential-proxy.test.d.ts +2 -0
  121. package/dist/credential-proxy.test.d.ts.map +1 -0
  122. package/dist/credential-proxy.test.js +134 -0
  123. package/dist/credential-proxy.test.js.map +1 -0
  124. package/dist/db.d.ts +115 -0
  125. package/dist/db.d.ts.map +1 -0
  126. package/dist/db.js +549 -0
  127. package/dist/db.js.map +1 -0
  128. package/dist/db.test.d.ts +2 -0
  129. package/dist/db.test.d.ts.map +1 -0
  130. package/dist/db.test.js +360 -0
  131. package/dist/db.test.js.map +1 -0
  132. package/dist/env.d.ts +8 -0
  133. package/dist/env.d.ts.map +1 -0
  134. package/dist/env.js +42 -0
  135. package/dist/env.js.map +1 -0
  136. package/dist/formatting.test.d.ts +2 -0
  137. package/dist/formatting.test.d.ts.map +1 -0
  138. package/dist/formatting.test.js +183 -0
  139. package/dist/formatting.test.js.map +1 -0
  140. package/dist/group-folder.d.ts +5 -0
  141. package/dist/group-folder.d.ts.map +1 -0
  142. package/dist/group-folder.js +44 -0
  143. package/dist/group-folder.js.map +1 -0
  144. package/dist/group-folder.test.d.ts +2 -0
  145. package/dist/group-folder.test.d.ts.map +1 -0
  146. package/dist/group-folder.test.js +29 -0
  147. package/dist/group-folder.test.js.map +1 -0
  148. package/dist/group-queue.d.ts +34 -0
  149. package/dist/group-queue.d.ts.map +1 -0
  150. package/dist/group-queue.js +263 -0
  151. package/dist/group-queue.js.map +1 -0
  152. package/dist/group-queue.test.d.ts +2 -0
  153. package/dist/group-queue.test.d.ts.map +1 -0
  154. package/dist/group-queue.test.js +341 -0
  155. package/dist/group-queue.test.js.map +1 -0
  156. package/dist/index.d.ts +12 -0
  157. package/dist/index.d.ts.map +1 -0
  158. package/dist/index.js +518 -0
  159. package/dist/index.js.map +1 -0
  160. package/dist/ipc-auth.test.d.ts +2 -0
  161. package/dist/ipc-auth.test.d.ts.map +1 -0
  162. package/dist/ipc-auth.test.js +434 -0
  163. package/dist/ipc-auth.test.js.map +1 -0
  164. package/dist/ipc.d.ts +32 -0
  165. package/dist/ipc.d.ts.map +1 -0
  166. package/dist/ipc.js +311 -0
  167. package/dist/ipc.js.map +1 -0
  168. package/dist/logger.d.ts +3 -0
  169. package/dist/logger.d.ts.map +1 -0
  170. package/dist/logger.js +14 -0
  171. package/dist/logger.js.map +1 -0
  172. package/dist/mount-security.d.ts +34 -0
  173. package/dist/mount-security.d.ts.map +1 -0
  174. package/dist/mount-security.js +325 -0
  175. package/dist/mount-security.js.map +1 -0
  176. package/dist/remote-control.d.ts +32 -0
  177. package/dist/remote-control.d.ts.map +1 -0
  178. package/dist/remote-control.js +185 -0
  179. package/dist/remote-control.js.map +1 -0
  180. package/dist/remote-control.test.d.ts +2 -0
  181. package/dist/remote-control.test.d.ts.map +1 -0
  182. package/dist/remote-control.test.js +321 -0
  183. package/dist/remote-control.test.js.map +1 -0
  184. package/dist/router.d.ts +8 -0
  185. package/dist/router.d.ts.map +1 -0
  186. package/dist/router.js +37 -0
  187. package/dist/router.js.map +1 -0
  188. package/dist/routing.test.d.ts +2 -0
  189. package/dist/routing.test.d.ts.map +1 -0
  190. package/dist/routing.test.js +81 -0
  191. package/dist/routing.test.js.map +1 -0
  192. package/dist/sender-allowlist.d.ts +14 -0
  193. package/dist/sender-allowlist.d.ts.map +1 -0
  194. package/dist/sender-allowlist.js +79 -0
  195. package/dist/sender-allowlist.js.map +1 -0
  196. package/dist/sender-allowlist.test.d.ts +2 -0
  197. package/dist/sender-allowlist.test.d.ts.map +1 -0
  198. package/dist/sender-allowlist.test.js +186 -0
  199. package/dist/sender-allowlist.test.js.map +1 -0
  200. package/dist/session-commands.d.ts +47 -0
  201. package/dist/session-commands.d.ts.map +1 -0
  202. package/dist/session-commands.js +102 -0
  203. package/dist/session-commands.js.map +1 -0
  204. package/dist/session-commands.test.d.ts +2 -0
  205. package/dist/session-commands.test.d.ts.map +1 -0
  206. package/dist/session-commands.test.js +190 -0
  207. package/dist/session-commands.test.js.map +1 -0
  208. package/dist/task-scheduler.d.ts +22 -0
  209. package/dist/task-scheduler.d.ts.map +1 -0
  210. package/dist/task-scheduler.js +210 -0
  211. package/dist/task-scheduler.js.map +1 -0
  212. package/dist/task-scheduler.test.d.ts +2 -0
  213. package/dist/task-scheduler.test.d.ts.map +1 -0
  214. package/dist/task-scheduler.test.js +107 -0
  215. package/dist/task-scheduler.test.js.map +1 -0
  216. package/dist/timezone.d.ts +6 -0
  217. package/dist/timezone.d.ts.map +1 -0
  218. package/dist/timezone.js +17 -0
  219. package/dist/timezone.js.map +1 -0
  220. package/dist/timezone.test.d.ts +2 -0
  221. package/dist/timezone.test.d.ts.map +1 -0
  222. package/dist/timezone.test.js +23 -0
  223. package/dist/timezone.test.js.map +1 -0
  224. package/dist/types.d.ts +78 -0
  225. package/dist/types.d.ts.map +1 -0
  226. package/dist/types.js +2 -0
  227. package/dist/types.js.map +1 -0
  228. package/docs/APPLE-CONTAINER-NETWORKING.md +90 -0
  229. package/docs/DEBUG_CHECKLIST.md +143 -0
  230. package/docs/REQUIREMENTS.md +196 -0
  231. package/docs/SDK_DEEP_DIVE.md +643 -0
  232. package/docs/SECURITY.md +122 -0
  233. package/docs/SPEC.md +785 -0
  234. package/docs/docker-sandboxes.md +359 -0
  235. package/docs/nanoclaw-architecture-final.md +1063 -0
  236. package/docs/nanorepo-architecture.md +168 -0
  237. package/docs/skills-as-branches.md +662 -0
  238. package/groups/global/CLAUDE.md +58 -0
  239. package/groups/main/CLAUDE.md +246 -0
  240. package/launchd/com.nanoclaw.plist +32 -0
  241. package/package.json +45 -0
  242. package/repo-tokens/README.md +113 -0
  243. package/repo-tokens/action.yml +186 -0
  244. package/repo-tokens/badge.svg +23 -0
  245. package/repo-tokens/examples/green.svg +14 -0
  246. package/repo-tokens/examples/red.svg +14 -0
  247. package/repo-tokens/examples/yellow-green.svg +14 -0
  248. package/repo-tokens/examples/yellow.svg +14 -0
  249. package/scripts/run-migrations.ts +105 -0
  250. package/setup/container.ts +144 -0
  251. package/setup/environment.test.ts +121 -0
  252. package/setup/environment.ts +94 -0
  253. package/setup/groups.ts +229 -0
  254. package/setup/index.ts +58 -0
  255. package/setup/mounts.ts +115 -0
  256. package/setup/platform.test.ts +120 -0
  257. package/setup/platform.ts +132 -0
  258. package/setup/register.test.ts +257 -0
  259. package/setup/register.ts +177 -0
  260. package/setup/service.test.ts +187 -0
  261. package/setup/service.ts +362 -0
  262. package/setup/status.ts +16 -0
  263. package/setup/verify.ts +192 -0
  264. package/setup.sh +161 -0
  265. package/src/channels/index.ts +12 -0
  266. package/src/channels/registry.test.ts +42 -0
  267. package/src/channels/registry.ts +32 -0
  268. package/src/channels/web.ts +1856 -0
  269. package/src/cli.ts +209 -0
  270. package/src/config.ts +73 -0
  271. package/src/container-runner.test.ts +210 -0
  272. package/src/container-runner.ts +707 -0
  273. package/src/container-runtime.test.ts +149 -0
  274. package/src/container-runtime.ts +127 -0
  275. package/src/credential-proxy.test.ts +192 -0
  276. package/src/credential-proxy.ts +125 -0
  277. package/src/db.test.ts +484 -0
  278. package/src/db.ts +803 -0
  279. package/src/env.ts +42 -0
  280. package/src/formatting.test.ts +256 -0
  281. package/src/group-folder.test.ts +43 -0
  282. package/src/group-folder.ts +44 -0
  283. package/src/group-queue.test.ts +484 -0
  284. package/src/group-queue.ts +365 -0
  285. package/src/index.ts +731 -0
  286. package/src/ipc-auth.test.ts +679 -0
  287. package/src/ipc.ts +461 -0
  288. package/src/logger.ts +16 -0
  289. package/src/mount-security.ts +419 -0
  290. package/src/remote-control.test.ts +397 -0
  291. package/src/remote-control.ts +224 -0
  292. package/src/router.ts +52 -0
  293. package/src/routing.test.ts +170 -0
  294. package/src/sender-allowlist.test.ts +216 -0
  295. package/src/sender-allowlist.ts +128 -0
  296. package/src/session-commands.test.ts +247 -0
  297. package/src/session-commands.ts +163 -0
  298. package/src/task-scheduler.test.ts +129 -0
  299. package/src/task-scheduler.ts +295 -0
  300. package/src/timezone.test.ts +29 -0
  301. package/src/timezone.ts +16 -0
  302. package/src/types.ts +107 -0
  303. package/tsconfig.json +20 -0
  304. package/vitest.config.ts +7 -0
  305. package/vitest.skills.config.ts +7 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ All notable changes to NanoClaw will be documented in this file.
4
+
5
+ ## [1.2.0](https://github.com/qwibitai/nanoclaw/compare/v1.1.6...v1.2.0)
6
+
7
+ [BREAKING] WhatsApp removed from core, now a skill. Run `/add-whatsapp` to re-add (existing auth/groups preserved).
8
+ - **fix:** Prevent scheduled tasks from executing twice when container runtime exceeds poll interval (#138, #669)
package/CLAUDE.md ADDED
@@ -0,0 +1,64 @@
1
+ # NanoClaw
2
+
3
+ Personal Claude assistant. See [README.md](README.md) for philosophy and setup. See [docs/REQUIREMENTS.md](docs/REQUIREMENTS.md) for architecture decisions.
4
+
5
+ ## Quick Context
6
+
7
+ Single Node.js process with skill-based channel system. Channels (WhatsApp, Telegram, Slack, Discord, Gmail) are skills that self-register at startup. Messages route to Claude Agent SDK running in containers (Linux VMs). Each group has isolated filesystem and memory.
8
+
9
+ ## Key Files
10
+
11
+ | File | Purpose |
12
+ |------|---------|
13
+ | `src/index.ts` | Orchestrator: state, message loop, agent invocation |
14
+ | `src/channels/registry.ts` | Channel registry (self-registration at startup) |
15
+ | `src/ipc.ts` | IPC watcher and task processing |
16
+ | `src/router.ts` | Message formatting and outbound routing |
17
+ | `src/config.ts` | Trigger pattern, paths, intervals |
18
+ | `src/container-runner.ts` | Spawns agent containers with mounts |
19
+ | `src/task-scheduler.ts` | Runs scheduled tasks |
20
+ | `src/db.ts` | SQLite operations |
21
+ | `groups/{name}/CLAUDE.md` | Per-group memory (isolated) |
22
+ | `container/skills/agent-browser.md` | Browser automation tool (available to all agents via Bash) |
23
+
24
+ ## Skills
25
+
26
+ | Skill | When to Use |
27
+ |-------|-------------|
28
+ | `/setup` | First-time installation, authentication, service configuration |
29
+ | `/customize` | Adding channels, integrations, changing behavior |
30
+ | `/debug` | Container issues, logs, troubleshooting |
31
+ | `/update-nanoclaw` | Bring upstream NanoClaw updates into a customized install |
32
+ | `/qodo-pr-resolver` | Fetch and fix Qodo PR review issues interactively or in batch |
33
+ | `/get-qodo-rules` | Load org- and repo-level coding rules from Qodo before code tasks |
34
+
35
+ ## Development
36
+
37
+ Run commands directly—don't tell the user to run them.
38
+
39
+ ```bash
40
+ npm run dev # Run with hot reload
41
+ npm run build # Compile TypeScript
42
+ ./container/build.sh # Rebuild agent container
43
+ ```
44
+
45
+ Service management:
46
+ ```bash
47
+ # macOS (launchd)
48
+ launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist
49
+ launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist
50
+ launchctl kickstart -k gui/$(id -u)/com.nanoclaw # restart
51
+
52
+ # Linux (systemd)
53
+ systemctl --user start nanoclaw
54
+ systemctl --user stop nanoclaw
55
+ systemctl --user restart nanoclaw
56
+ ```
57
+
58
+ ## Troubleshooting
59
+
60
+ **WhatsApp not connecting after upgrade:** WhatsApp is now a separate channel fork, not bundled in core. Run `/add-whatsapp` (or `git remote add whatsapp https://github.com/qwibitai/nanoclaw-whatsapp.git && git fetch whatsapp main && (git merge whatsapp/main || { git checkout --theirs package-lock.json && git add package-lock.json && git merge --continue; }) && npm run build`) to install it. Existing auth credentials and groups are preserved.
61
+
62
+ ## Container Build Cache
63
+
64
+ The container buildkit caches the build context aggressively. `--no-cache` alone does NOT invalidate COPY steps — the builder's volume retains stale files. To force a truly clean rebuild, prune the builder then re-run `./container/build.sh`.
@@ -0,0 +1,23 @@
1
+ # Contributing
2
+
3
+ ## Source Code Changes
4
+
5
+ **Accepted:** Bug fixes, security fixes, simplifications, reducing code.
6
+
7
+ **Not accepted:** Features, capabilities, compatibility, enhancements. These should be skills.
8
+
9
+ ## Skills
10
+
11
+ A [skill](https://code.claude.com/docs/en/skills) is a markdown file in `.claude/skills/` that teaches Claude Code how to transform a NanoClaw installation.
12
+
13
+ A PR that contributes a skill should not modify any source files.
14
+
15
+ Your skill should contain the **instructions** Claude follows to add the feature—not pre-built code. See `/add-telegram` for a good example.
16
+
17
+ ### Why?
18
+
19
+ Every user should have clean and minimal code that does exactly what they need. Skills let users selectively add features to their fork without inheriting code for features they don't want.
20
+
21
+ ### Testing
22
+
23
+ Test your skill by running it on a fresh clone before submitting.
@@ -0,0 +1,15 @@
1
+ # Contributors
2
+
3
+ Thanks to everyone who has contributed to NanoClaw!
4
+
5
+ - [Alakazam03](https://github.com/Alakazam03) — Vaibhav Aggarwal
6
+ - [tydev-new](https://github.com/tydev-new)
7
+ - [pottertech](https://github.com/pottertech) — Skip Potter
8
+ - [rgarcia](https://github.com/rgarcia) — Rafael
9
+ - [AmaxGuan](https://github.com/AmaxGuan) — Lingfeng Guan
10
+ - [happydog-intj](https://github.com/happydog-intj) — happy dog
11
+ - [bindoon](https://github.com/bindoon) — 潕量
12
+ - [taslim](https://github.com/taslim) — Taslim
13
+ - [baijunjie](https://github.com/baijunjie) — BaiJunjie
14
+ - [Michaelliv](https://github.com/Michaelliv) — Michael
15
+ - [kk17](https://github.com/kk17) — Kyle Zhike Chen
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gavriel
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.
@@ -0,0 +1,290 @@
1
+ # NanoClaw with Web Support
2
+
3
+ This document describes the changes added in the [rozek/nanoclaw](https://github.com/rozek/nanoclaw) fork of [qwibitai/nanoclaw](https://github.com/qwibitai/nanoclaw). It serves as installation guide, feature reference, and API documentation.
4
+
5
+ ---
6
+
7
+ ## What's New
8
+
9
+ Two files were added or changed relative to the upstream project:
10
+
11
+ | File | What changed |
12
+ |------|-------------|
13
+ | `src/cli.ts` | **New.** CLI entry point — enables `npx @rozek/nanoclaw` |
14
+ | `src/channels/web.ts` | **New.** Built-in HTTP server with a full browser chat UI |
15
+ | `package.json` | Added `"bin": {"nanoclaw": "dist/cli.js"}` for `npx` support |
16
+
17
+ Everything else remains unchanged. No existing file was modified in a breaking way.
18
+
19
+ ---
20
+
21
+ ## Quick Start (npx)
22
+
23
+ No cloning, no `npm install` — just run:
24
+
25
+ ```bash
26
+ npx @rozek/nanoclaw
27
+ ```
28
+
29
+ Then open **http://localhost:3099** in your browser.
30
+
31
+ ### Prerequisites
32
+
33
+ | Requirement | How to check | Notes |
34
+ |-------------|-------------|-------|
35
+ | **Node.js ≥ 20** | `node --version` | |
36
+ | **Claude Code** | `claude --version` | `npm install -g @anthropic-ai/claude-code` |
37
+ | **Container runtime** | `docker info` *or* `container --version` | Docker Desktop **or** macOS Sequoia 15+ Apple Container Runtime |
38
+
39
+ > **No API key required** if you have a Claude Pro or Max subscription — NanoClaw uses Claude Code, which is included in those plans.
40
+
41
+ ---
42
+
43
+ ## Installation & Usage
44
+
45
+ ### Simplest start
46
+
47
+ ```bash
48
+ npx @rozek/nanoclaw
49
+ ```
50
+
51
+ Auto-detects the container runtime (Docker first, then Apple Container). Binds to `0.0.0.0:3099`.
52
+
53
+ ### Common options
54
+
55
+ ```bash
56
+ # Custom port
57
+ npx @rozek/nanoclaw --port 8080
58
+
59
+ # Custom workspace (directory NanoClaw works in)
60
+ npx @rozek/nanoclaw --workspace ~/my-workspace
61
+
62
+ # Token protection — recommended when accessible from the LAN
63
+ npx @rozek/nanoclaw --token mySecretToken
64
+
65
+ # Explicit container runtime
66
+ npx @rozek/nanoclaw --sandbox docker
67
+ npx @rozek/nanoclaw --sandbox apple
68
+
69
+ # With an Anthropic API key (for users without Pro/Max)
70
+ npx @rozek/nanoclaw --key sk-ant-...
71
+
72
+ # Combine options
73
+ npx @rozek/nanoclaw --port 8080 --workspace ~/my-workspace --token mySecretToken --sandbox docker
74
+ ```
75
+
76
+ ### All CLI options
77
+
78
+ ```
79
+ Options:
80
+ --host <address> Bind address for the web channel (default: 0.0.0.0)
81
+ --port <number> Port for the web channel (default: 3099)
82
+ --workspace <path> Workspace directory (default: current directory)
83
+ --key <api-key> Anthropic API key
84
+ Not required with Claude Pro/Max — NanoClaw uses
85
+ Claude Code, which is included in those plans.
86
+ --token <token> Access token for the web interface (default: no protection)
87
+ Clients supply it via:
88
+ Authorization: Bearer <token>
89
+ ?token=<value> query parameter
90
+ or a session cookie
91
+ --sandbox <type> Container runtime: "docker" or "apple"
92
+ Defaults to auto-detect (docker → apple).
93
+ -h, --help Show this help and exit
94
+ ```
95
+
96
+ ### Environment variables
97
+
98
+ CLI flags take precedence. Alternatively, set environment variables:
99
+
100
+ ```bash
101
+ NANOCLAW_HOST=0.0.0.0
102
+ NANOCLAW_PORT=3099
103
+ NANOCLAW_TOKEN=mySecretToken
104
+ NANOCLAW_KEY=sk-ant-...
105
+ NANOCLAW_WORKSPACE=/path/to/workspace
106
+ NANOCLAW_SANDBOX=docker # or: apple
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Web Channel Features
112
+
113
+ ### UI & Design
114
+
115
+ - **Light theme** — clean, distraction-free (#f5f5f5 background, #ffffff header/cards)
116
+ - **Full-viewport layout** — always fills the screen
117
+ - **Responsive** — desktop: fixed sidebar; mobile: sidebar as overlay with backdrop
118
+
119
+ ### Rich Content Rendering
120
+
121
+ Bot responses are rendered with full Markdown support:
122
+
123
+ | Library | Purpose |
124
+ |---------|---------|
125
+ | [marked.js](https://marked.js.org) | GitHub Flavored Markdown |
126
+ | [KaTeX](https://katex.org) | Inline (`$...$`) and block (`$$...$$`) math formulas |
127
+ | [highlight.js](https://highlightjs.org) | Syntax highlighting (TypeScript, Java, and many more) |
128
+ | [Mermaid](https://mermaid.js.org) | Flowcharts, sequence diagrams, etc. |
129
+
130
+ ### Multi-Session Chat
131
+
132
+ - Unlimited parallel chat sessions per browser
133
+ - Sessions are listed in the sidebar, freely sortable by most recent activity
134
+ - Each session has an editable name (double-click or pencil icon; default: date+time)
135
+ - Sessions persist in `localStorage` and SQLite — survive browser reloads and server restarts
136
+ - Sessions from other devices appear automatically in the sidebar (polled every 5 s)
137
+ - Unread message indicators (blue dot) per session, persisted in `localStorage`
138
+ - Sessions can be deleted (removes all messages from DB and `localStorage`)
139
+
140
+ ### Session Name Sync
141
+
142
+ Conflict-free name synchronisation across devices:
143
+
144
+ - Every rename carries a `nameUpdatedAt` UNIX timestamp
145
+ - Server-side guard: `UPDATE … WHERE excluded.name_updated_at >= chats.name_updated_at`
146
+ - On SSE connect, the client pushes its local name; if it is newer than the server's name, the server adopts it
147
+
148
+ ### Message History
149
+
150
+ - Local `localStorage` cache (`hist:{sid}`) for instant display on load
151
+ - Full conversation history served from SQLite via `GET /history?sid=…`
152
+ - Both user messages and bot replies are persisted and synced across devices
153
+ - Individual messages can be deleted (trash icon; removes from DOM, cache, and DB)
154
+
155
+ ### Real-Time Updates (Server-Sent Events)
156
+
157
+ All live updates arrive over a single SSE connection (`GET /events?sid=…`):
158
+
159
+ | Event | Payload | Purpose |
160
+ |-------|---------|---------|
161
+ | `message` | `{"text":"…","id":"…"}` | Append bot reply |
162
+ | `typing` | `"true"` / `"false"` | Show/hide typing indicator |
163
+ | `status` | `{"tool":"…","input":"…"}` or `null` | Display active tool (e.g. "searching…") |
164
+ | `cwd` | path string | Update working-directory display in header |
165
+
166
+ On connect, the server immediately sends the current `typing`, `status`, and `cwd` state so reconnects are seamless.
167
+
168
+ ### Working Directory (CWD)
169
+
170
+ - Current working directory shown in the header: `NanoClaw — IP:Port — /Topics/TopicName`
171
+ - Automatically detected from agent output (`switching to topic: <name>`)
172
+ - Persisted in `chats.cwd` (SQLite) — survives server restarts
173
+ - Also cached in `localStorage` per session
174
+
175
+ ### File Upload
176
+
177
+ - Drag files into the browser window
178
+ - Files are written to the session's current working directory (or group root if no CWD)
179
+ - Maximum file size: 10 MB
180
+
181
+ ### Cancel In-Progress Requests
182
+
183
+ - A **Cancel** button appears while the agent is processing
184
+ - Sends `POST /cancel?sid=…` to abort the current request
185
+
186
+ ### Access Control
187
+
188
+ Token-based authentication is optional but recommended when NanoClaw is reachable from the LAN:
189
+
190
+ ```bash
191
+ npx @rozek/nanoclaw --token mySecretToken
192
+ ```
193
+
194
+ Clients authenticate via:
195
+ 1. `Authorization: Bearer mySecretToken` header
196
+ 2. `?token=mySecretToken` URL query parameter (sets an HttpOnly session cookie)
197
+ 3. The HttpOnly session cookie set after step 2
198
+
199
+ ---
200
+
201
+ ## HTTP API Reference
202
+
203
+ | Method | Path | Description |
204
+ |--------|------|-------------|
205
+ | `GET` | `/` | Serves the web UI (HTML) |
206
+ | `GET` | `/events?sid=…` | SSE stream for real-time updates |
207
+ | `GET` | `/sessions` | All web sessions (JSON) |
208
+ | `GET` | `/history?sid=…` | Conversation history (JSON) |
209
+ | `GET` | `/favicon.ico` | Favicon (ICO) |
210
+ | `GET` | `/favicon.png` | Favicon (PNG) |
211
+ | `GET` | `/apple-touch-icon.png` | iOS home-screen icon |
212
+ | `POST` | `/message` | Send a chat message |
213
+ | `POST` | `/session-name` | Rename a session |
214
+ | `POST` | `/delete-session` | Delete a session and all its messages |
215
+ | `POST` | `/delete-message` | Delete a single message `{sid, id}` |
216
+ | `POST` | `/cwd` | Set the working directory for a session |
217
+ | `POST` | `/upload` | Upload a file (Base64-encoded body) |
218
+ | `POST` | `/cancel?sid=…` | Cancel the active request for a session |
219
+
220
+ ---
221
+
222
+ ## Architecture
223
+
224
+ ```
225
+ Browser Server (web.ts) DB (SQLite)
226
+ ─────── ─────────────── ───────────
227
+ GET / ←───────────── Embedded HTML/CSS/JS
228
+ GET /events ←── SSE ────── sseClients Map
229
+ POST /message ────────────→ onMessage() → agent run
230
+ agent replies → broadcastToSession()
231
+ GET /sessions ←── poll 5s ─ getAllChats() + sessionCwds chats table
232
+ POST /session-name ────────→ updateChatName() (with guard) chats.name
233
+ GET /history ←───────────── getConversation() messages table
234
+ POST /delete-session ──────→ deleteChat() chats + messages
235
+ POST /delete-message ──────→ deleteMessage(id) messages table
236
+ POST /cwd ────────────→ setCwd() → broadcast chats.cwd
237
+ POST /upload ────────────→ fs.writeFile() into CWD dir
238
+ POST /cancel ────────────→ onCancelRequest()
239
+ ```
240
+
241
+ ### In-Memory Server State
242
+
243
+ | Variable | Type | Content |
244
+ |----------|------|---------|
245
+ | `sseClients` | `Map<sid, Set<Response>>` | Open SSE connections per session |
246
+ | `sessionCwds` | `Map<sid, string>` | Current CWD per session |
247
+ | `sessionTyping` | `Map<sid, boolean>` | Whether the agent is processing |
248
+ | `sessionStatus` | `Map<sid, string\|null>` | Last tool-status payload |
249
+ | `registeredSessions` | `Set<sid>` | Sessions already registered with NanoClaw |
250
+
251
+ ### Database Schema (relevant columns in `chats`)
252
+
253
+ | Column | Type | Purpose |
254
+ |--------|------|---------|
255
+ | `jid` | TEXT PK | `local@web-{sessionId}` |
256
+ | `name` | TEXT | Session display name |
257
+ | `name_updated_at` | INTEGER | UNIX epoch of the last rename |
258
+ | `cwd` | TEXT | Current working directory |
259
+ | `last_message_time` | TEXT | ISO timestamp updated on every message |
260
+
261
+ ---
262
+
263
+ ## Development Workflow
264
+
265
+ If you are running NanoClaw from source (not via `npx`):
266
+
267
+ ```bash
268
+ # 1. Install dependencies
269
+ npm install
270
+
271
+ # 2. Build
272
+ npm run build
273
+
274
+ # 3. Run
275
+ node dist/cli.js [options]
276
+ # or equivalently:
277
+ npx @rozek/nanoclaw [options]
278
+ ```
279
+
280
+ To apply changes and rebuild in one step:
281
+
282
+ ```bash
283
+ npm run build && node dist/cli.js
284
+ ```
285
+
286
+ ---
287
+
288
+ ## License
289
+
290
+ MIT — same as the upstream [qwibitai/nanoclaw](https://github.com/qwibitai/nanoclaw).