@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
@@ -0,0 +1,143 @@
1
+ # NanoClaw Debug Checklist
2
+
3
+ ## Known Issues (2026-02-08)
4
+
5
+ ### 1. [FIXED] Resume branches from stale tree position
6
+ When agent teams spawns subagent CLI processes, they write to the same session JSONL. On subsequent `query()` resumes, the CLI reads the JSONL but may pick a stale branch tip (from before the subagent activity), causing the agent's response to land on a branch the host never receives a `result` for. **Fix**: pass `resumeSessionAt` with the last assistant message UUID to explicitly anchor each resume.
7
+
8
+ ### 2. IDLE_TIMEOUT == CONTAINER_TIMEOUT (both 30 min)
9
+ Both timers fire at the same time, so containers always exit via hard SIGKILL (code 137) instead of graceful `_close` sentinel shutdown. The idle timeout should be shorter (e.g., 5 min) so containers wind down between messages, while container timeout stays at 30 min as a safety net for stuck agents.
10
+
11
+ ### 3. Cursor advanced before agent succeeds
12
+ `processGroupMessages` advances `lastAgentTimestamp` before the agent runs. If the container times out, retries find no messages (cursor already past them). Messages are permanently lost on timeout.
13
+
14
+ ## Quick Status Check
15
+
16
+ ```bash
17
+ # 1. Is the service running?
18
+ launchctl list | grep nanoclaw
19
+ # Expected: PID 0 com.nanoclaw (PID = running, "-" = not running, non-zero exit = crashed)
20
+
21
+ # 2. Any running containers?
22
+ container ls --format '{{.Names}} {{.Status}}' 2>/dev/null | grep nanoclaw
23
+
24
+ # 3. Any stopped/orphaned containers?
25
+ container ls -a --format '{{.Names}} {{.Status}}' 2>/dev/null | grep nanoclaw
26
+
27
+ # 4. Recent errors in service log?
28
+ grep -E 'ERROR|WARN' logs/nanoclaw.log | tail -20
29
+
30
+ # 5. Is WhatsApp connected? (look for last connection event)
31
+ grep -E 'Connected to WhatsApp|Connection closed|connection.*close' logs/nanoclaw.log | tail -5
32
+
33
+ # 6. Are groups loaded?
34
+ grep 'groupCount' logs/nanoclaw.log | tail -3
35
+ ```
36
+
37
+ ## Session Transcript Branching
38
+
39
+ ```bash
40
+ # Check for concurrent CLI processes in session debug logs
41
+ ls -la data/sessions/<group>/.claude/debug/
42
+
43
+ # Count unique SDK processes that handled messages
44
+ # Each .txt file = one CLI subprocess. Multiple = concurrent queries.
45
+
46
+ # Check parentUuid branching in transcript
47
+ python3 -c "
48
+ import json, sys
49
+ lines = open('data/sessions/<group>/.claude/projects/-workspace-group/<session>.jsonl').read().strip().split('\n')
50
+ for i, line in enumerate(lines):
51
+ try:
52
+ d = json.loads(line)
53
+ if d.get('type') == 'user' and d.get('message'):
54
+ parent = d.get('parentUuid', 'ROOT')[:8]
55
+ content = str(d['message'].get('content', ''))[:60]
56
+ print(f'L{i+1} parent={parent} {content}')
57
+ except: pass
58
+ "
59
+ ```
60
+
61
+ ## Container Timeout Investigation
62
+
63
+ ```bash
64
+ # Check for recent timeouts
65
+ grep -E 'Container timeout|timed out' logs/nanoclaw.log | tail -10
66
+
67
+ # Check container log files for the timed-out container
68
+ ls -lt groups/*/logs/container-*.log | head -10
69
+
70
+ # Read the most recent container log (replace path)
71
+ cat groups/<group>/logs/container-<timestamp>.log
72
+
73
+ # Check if retries were scheduled and what happened
74
+ grep -E 'Scheduling retry|retry|Max retries' logs/nanoclaw.log | tail -10
75
+ ```
76
+
77
+ ## Agent Not Responding
78
+
79
+ ```bash
80
+ # Check if messages are being received from WhatsApp
81
+ grep 'New messages' logs/nanoclaw.log | tail -10
82
+
83
+ # Check if messages are being processed (container spawned)
84
+ grep -E 'Processing messages|Spawning container' logs/nanoclaw.log | tail -10
85
+
86
+ # Check if messages are being piped to active container
87
+ grep -E 'Piped messages|sendMessage' logs/nanoclaw.log | tail -10
88
+
89
+ # Check the queue state — any active containers?
90
+ grep -E 'Starting container|Container active|concurrency limit' logs/nanoclaw.log | tail -10
91
+
92
+ # Check lastAgentTimestamp vs latest message timestamp
93
+ sqlite3 store/messages.db "SELECT chat_jid, MAX(timestamp) as latest FROM messages GROUP BY chat_jid ORDER BY latest DESC LIMIT 5;"
94
+ ```
95
+
96
+ ## Container Mount Issues
97
+
98
+ ```bash
99
+ # Check mount validation logs (shows on container spawn)
100
+ grep -E 'Mount validated|Mount.*REJECTED|mount' logs/nanoclaw.log | tail -10
101
+
102
+ # Verify the mount allowlist is readable
103
+ cat ~/.config/nanoclaw/mount-allowlist.json
104
+
105
+ # Check group's container_config in DB
106
+ sqlite3 store/messages.db "SELECT name, container_config FROM registered_groups;"
107
+
108
+ # Test-run a container to check mounts (dry run)
109
+ # Replace <group-folder> with the group's folder name
110
+ container run -i --rm --entrypoint ls nanoclaw-agent:latest /workspace/extra/
111
+ ```
112
+
113
+ ## WhatsApp Auth Issues
114
+
115
+ ```bash
116
+ # Check if QR code was requested (means auth expired)
117
+ grep 'QR\|authentication required\|qr' logs/nanoclaw.log | tail -5
118
+
119
+ # Check auth files exist
120
+ ls -la store/auth/
121
+
122
+ # Re-authenticate if needed
123
+ npm run auth
124
+ ```
125
+
126
+ ## Service Management
127
+
128
+ ```bash
129
+ # Restart the service
130
+ launchctl kickstart -k gui/$(id -u)/com.nanoclaw
131
+
132
+ # View live logs
133
+ tail -f logs/nanoclaw.log
134
+
135
+ # Stop the service (careful — running containers are detached, not killed)
136
+ launchctl bootout gui/$(id -u)/com.nanoclaw
137
+
138
+ # Start the service
139
+ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.nanoclaw.plist
140
+
141
+ # Rebuild after code changes
142
+ npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw
143
+ ```
@@ -0,0 +1,196 @@
1
+ # NanoClaw Requirements
2
+
3
+ Original requirements and design decisions from the project creator.
4
+
5
+ ---
6
+
7
+ ## Why This Exists
8
+
9
+ This is a lightweight, secure alternative to OpenClaw (formerly ClawBot). That project became a monstrosity - 4-5 different processes running different gateways, endless configuration files, endless integrations. It's a security nightmare where agents don't run in isolated processes; there's all kinds of leaky workarounds trying to prevent them from accessing parts of the system they shouldn't. It's impossible for anyone to realistically understand the whole codebase. When you run it you're kind of just yoloing it.
10
+
11
+ NanoClaw gives you the core functionality without that mess.
12
+
13
+ ---
14
+
15
+ ## Philosophy
16
+
17
+ ### Small Enough to Understand
18
+
19
+ The entire codebase should be something you can read and understand. One Node.js process. A handful of source files. No microservices, no message queues, no abstraction layers.
20
+
21
+ ### Security Through True Isolation
22
+
23
+ Instead of application-level permission systems trying to prevent agents from accessing things, agents run in actual Linux containers. The isolation is at the OS level. Agents can only see what's explicitly mounted. Bash access is safe because commands run inside the container, not on your Mac.
24
+
25
+ ### Built for One User
26
+
27
+ This isn't a framework or a platform. It's working software for my specific needs. I use WhatsApp and Email, so it supports WhatsApp and Email. I don't use Telegram, so it doesn't support Telegram. I add the integrations I actually want, not every possible integration.
28
+
29
+ ### Customization = Code Changes
30
+
31
+ No configuration sprawl. If you want different behavior, modify the code. The codebase is small enough that this is safe and practical. Very minimal things like the trigger word are in config. Everything else - just change the code to do what you want.
32
+
33
+ ### AI-Native Development
34
+
35
+ I don't need an installation wizard - Claude Code guides the setup. I don't need a monitoring dashboard - I ask Claude Code what's happening. I don't need elaborate logging UIs - I ask Claude to read the logs. I don't need debugging tools - I describe the problem and Claude fixes it.
36
+
37
+ The codebase assumes you have an AI collaborator. It doesn't need to be excessively self-documenting or self-debugging because Claude is always there.
38
+
39
+ ### Skills Over Features
40
+
41
+ When people contribute, they shouldn't add "Telegram support alongside WhatsApp." They should contribute a skill like `/add-telegram` that transforms the codebase. Users fork the repo, run skills to customize, and end up with clean code that does exactly what they need - not a bloated system trying to support everyone's use case simultaneously.
42
+
43
+ ---
44
+
45
+ ## RFS (Request for Skills)
46
+
47
+ Skills we'd love contributors to build:
48
+
49
+ ### Communication Channels
50
+ Skills to add or switch to different messaging platforms:
51
+ - `/add-telegram` - Add Telegram as an input channel
52
+ - `/add-slack` - Add Slack as an input channel
53
+ - `/add-discord` - Add Discord as an input channel
54
+ - `/add-sms` - Add SMS via Twilio or similar
55
+ - `/convert-to-telegram` - Replace WhatsApp with Telegram entirely
56
+
57
+ ### Container Runtime
58
+ The project uses Docker by default (cross-platform). For macOS users who prefer Apple Container:
59
+ - `/convert-to-apple-container` - Switch from Docker to Apple Container (macOS-only)
60
+
61
+ ### Platform Support
62
+ - `/setup-linux` - Make the full setup work on Linux (depends on Docker conversion)
63
+ - `/setup-windows` - Windows support via WSL2 + Docker
64
+
65
+ ---
66
+
67
+ ## Vision
68
+
69
+ A personal Claude assistant accessible via WhatsApp, with minimal custom code.
70
+
71
+ **Core components:**
72
+ - **Claude Agent SDK** as the core agent
73
+ - **Containers** for isolated agent execution (Linux VMs)
74
+ - **WhatsApp** as the primary I/O channel
75
+ - **Persistent memory** per conversation and globally
76
+ - **Scheduled tasks** that run Claude and can message back
77
+ - **Web access** for search and browsing
78
+ - **Browser automation** via agent-browser
79
+
80
+ **Implementation approach:**
81
+ - Use existing tools (WhatsApp connector, Claude Agent SDK, MCP servers)
82
+ - Minimal glue code
83
+ - File-based systems where possible (CLAUDE.md for memory, folders for groups)
84
+
85
+ ---
86
+
87
+ ## Architecture Decisions
88
+
89
+ ### Message Routing
90
+ - A router listens to WhatsApp and routes messages based on configuration
91
+ - Only messages from registered groups are processed
92
+ - Trigger: `@Andy` prefix (case insensitive), configurable via `ASSISTANT_NAME` env var
93
+ - Unregistered groups are ignored completely
94
+
95
+ ### Memory System
96
+ - **Per-group memory**: Each group has a folder with its own `CLAUDE.md`
97
+ - **Global memory**: Root `CLAUDE.md` is read by all groups, but only writable from "main" (self-chat)
98
+ - **Files**: Groups can create/read files in their folder and reference them
99
+ - Agent runs in the group's folder, automatically inherits both CLAUDE.md files
100
+
101
+ ### Session Management
102
+ - Each group maintains a conversation session (via Claude Agent SDK)
103
+ - Sessions auto-compact when context gets too long, preserving critical information
104
+
105
+ ### Container Isolation
106
+ - All agents run inside containers (lightweight Linux VMs)
107
+ - Each agent invocation spawns a container with mounted directories
108
+ - Containers provide filesystem isolation - agents can only see mounted paths
109
+ - Bash access is safe because commands run inside the container, not on the host
110
+ - Browser automation via agent-browser with Chromium in the container
111
+
112
+ ### Scheduled Tasks
113
+ - Users can ask Claude to schedule recurring or one-time tasks from any group
114
+ - Tasks run as full agents in the context of the group that created them
115
+ - Tasks have access to all tools including Bash (safe in container)
116
+ - Tasks can optionally send messages to their group via `send_message` tool, or complete silently
117
+ - Task runs are logged to the database with duration and result
118
+ - Schedule types: cron expressions, intervals (ms), or one-time (ISO timestamp)
119
+ - From main: can schedule tasks for any group, view/manage all tasks
120
+ - From other groups: can only manage that group's tasks
121
+
122
+ ### Group Management
123
+ - New groups are added explicitly via the main channel
124
+ - Groups are registered in SQLite (via the main channel or IPC `register_group` command)
125
+ - Each group gets a dedicated folder under `groups/`
126
+ - Groups can have additional directories mounted via `containerConfig`
127
+
128
+ ### Main Channel Privileges
129
+ - Main channel is the admin/control group (typically self-chat)
130
+ - Can write to global memory (`groups/CLAUDE.md`)
131
+ - Can schedule tasks for any group
132
+ - Can view and manage tasks from all groups
133
+ - Can configure additional directory mounts for any group
134
+
135
+ ---
136
+
137
+ ## Integration Points
138
+
139
+ ### WhatsApp
140
+ - Using baileys library for WhatsApp Web connection
141
+ - Messages stored in SQLite, polled by router
142
+ - QR code authentication during setup
143
+
144
+ ### Scheduler
145
+ - Built-in scheduler runs on the host, spawns containers for task execution
146
+ - Custom `nanoclaw` MCP server (inside container) provides scheduling tools
147
+ - Tools: `schedule_task`, `list_tasks`, `pause_task`, `resume_task`, `cancel_task`, `send_message`
148
+ - Tasks stored in SQLite with run history
149
+ - Scheduler loop checks for due tasks every minute
150
+ - Tasks execute Claude Agent SDK in containerized group context
151
+
152
+ ### Web Access
153
+ - Built-in WebSearch and WebFetch tools
154
+ - Standard Claude Agent SDK capabilities
155
+
156
+ ### Browser Automation
157
+ - agent-browser CLI with Chromium in container
158
+ - Snapshot-based interaction with element references (@e1, @e2, etc.)
159
+ - Screenshots, PDFs, video recording
160
+ - Authentication state persistence
161
+
162
+ ---
163
+
164
+ ## Setup & Customization
165
+
166
+ ### Philosophy
167
+ - Minimal configuration files
168
+ - Setup and customization done via Claude Code
169
+ - Users clone the repo and run Claude Code to configure
170
+ - Each user gets a custom setup matching their exact needs
171
+
172
+ ### Skills
173
+ - `/setup` - Install dependencies, authenticate WhatsApp, configure scheduler, start services
174
+ - `/customize` - General-purpose skill for adding capabilities (new channels like Telegram, new integrations, behavior changes)
175
+ - `/update` - Pull upstream changes, merge with customizations, run migrations
176
+
177
+ ### Deployment
178
+ - Runs on local Mac via launchd
179
+ - Single Node.js process handles everything
180
+
181
+ ---
182
+
183
+ ## Personal Configuration (Reference)
184
+
185
+ These are the creator's settings, stored here for reference:
186
+
187
+ - **Trigger**: `@Andy` (case insensitive)
188
+ - **Response prefix**: `Andy:`
189
+ - **Persona**: Default Claude (no custom personality)
190
+ - **Main channel**: Self-chat (messaging yourself in WhatsApp)
191
+
192
+ ---
193
+
194
+ ## Project Name
195
+
196
+ **NanoClaw** - A reference to Clawdbot (now OpenClaw).