@rozek/nanoclaw 0.0.1

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 (306) 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 +325 -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.json +21 -0
  68. package/container/agent-runner/src/index.ts +774 -0
  69. package/container/agent-runner/src/ipc-mcp-stdio.ts +338 -0
  70. package/container/agent-runner/tsconfig.json +15 -0
  71. package/container/build.sh +23 -0
  72. package/container/skills/agent-browser/SKILL.md +159 -0
  73. package/container/skills/capabilities/SKILL.md +100 -0
  74. package/container/skills/cwd/SKILL.md +32 -0
  75. package/container/skills/pwd/SKILL.md +19 -0
  76. package/container/skills/status/SKILL.md +104 -0
  77. package/dist/channels/index.d.ts +2 -0
  78. package/dist/channels/index.d.ts.map +1 -0
  79. package/dist/channels/index.js +10 -0
  80. package/dist/channels/index.js.map +1 -0
  81. package/dist/channels/registry.d.ts +13 -0
  82. package/dist/channels/registry.d.ts.map +1 -0
  83. package/dist/channels/registry.js +11 -0
  84. package/dist/channels/registry.js.map +1 -0
  85. package/dist/channels/registry.test.d.ts +2 -0
  86. package/dist/channels/registry.test.d.ts.map +1 -0
  87. package/dist/channels/registry.test.js +32 -0
  88. package/dist/channels/registry.test.js.map +1 -0
  89. package/dist/channels/web.d.ts +2 -0
  90. package/dist/channels/web.d.ts.map +1 -0
  91. package/dist/channels/web.js +1843 -0
  92. package/dist/channels/web.js.map +1 -0
  93. package/dist/cli.d.ts +11 -0
  94. package/dist/cli.d.ts.map +1 -0
  95. package/dist/cli.js +182 -0
  96. package/dist/cli.js.map +1 -0
  97. package/dist/config.d.ts +19 -0
  98. package/dist/config.d.ts.map +1 -0
  99. package/dist/config.js +36 -0
  100. package/dist/config.js.map +1 -0
  101. package/dist/container-runner.d.ts +44 -0
  102. package/dist/container-runner.d.ts.map +1 -0
  103. package/dist/container-runner.js +511 -0
  104. package/dist/container-runner.js.map +1 -0
  105. package/dist/container-runner.test.d.ts +2 -0
  106. package/dist/container-runner.test.d.ts.map +1 -0
  107. package/dist/container-runner.test.js +150 -0
  108. package/dist/container-runner.test.js.map +1 -0
  109. package/dist/container-runtime.d.ts +22 -0
  110. package/dist/container-runtime.d.ts.map +1 -0
  111. package/dist/container-runtime.js +96 -0
  112. package/dist/container-runtime.js.map +1 -0
  113. package/dist/container-runtime.test.d.ts +2 -0
  114. package/dist/container-runtime.test.d.ts.map +1 -0
  115. package/dist/container-runtime.test.js +93 -0
  116. package/dist/container-runtime.test.js.map +1 -0
  117. package/dist/credential-proxy.d.ts +21 -0
  118. package/dist/credential-proxy.d.ts.map +1 -0
  119. package/dist/credential-proxy.js +95 -0
  120. package/dist/credential-proxy.js.map +1 -0
  121. package/dist/credential-proxy.test.d.ts +2 -0
  122. package/dist/credential-proxy.test.d.ts.map +1 -0
  123. package/dist/credential-proxy.test.js +134 -0
  124. package/dist/credential-proxy.test.js.map +1 -0
  125. package/dist/db.d.ts +115 -0
  126. package/dist/db.d.ts.map +1 -0
  127. package/dist/db.js +549 -0
  128. package/dist/db.js.map +1 -0
  129. package/dist/db.test.d.ts +2 -0
  130. package/dist/db.test.d.ts.map +1 -0
  131. package/dist/db.test.js +360 -0
  132. package/dist/db.test.js.map +1 -0
  133. package/dist/env.d.ts +8 -0
  134. package/dist/env.d.ts.map +1 -0
  135. package/dist/env.js +42 -0
  136. package/dist/env.js.map +1 -0
  137. package/dist/formatting.test.d.ts +2 -0
  138. package/dist/formatting.test.d.ts.map +1 -0
  139. package/dist/formatting.test.js +183 -0
  140. package/dist/formatting.test.js.map +1 -0
  141. package/dist/group-folder.d.ts +5 -0
  142. package/dist/group-folder.d.ts.map +1 -0
  143. package/dist/group-folder.js +44 -0
  144. package/dist/group-folder.js.map +1 -0
  145. package/dist/group-folder.test.d.ts +2 -0
  146. package/dist/group-folder.test.d.ts.map +1 -0
  147. package/dist/group-folder.test.js +29 -0
  148. package/dist/group-folder.test.js.map +1 -0
  149. package/dist/group-queue.d.ts +40 -0
  150. package/dist/group-queue.d.ts.map +1 -0
  151. package/dist/group-queue.js +276 -0
  152. package/dist/group-queue.js.map +1 -0
  153. package/dist/group-queue.test.d.ts +2 -0
  154. package/dist/group-queue.test.d.ts.map +1 -0
  155. package/dist/group-queue.test.js +341 -0
  156. package/dist/group-queue.test.js.map +1 -0
  157. package/dist/index.d.ts +13 -0
  158. package/dist/index.d.ts.map +1 -0
  159. package/dist/index.js +592 -0
  160. package/dist/index.js.map +1 -0
  161. package/dist/ipc-auth.test.d.ts +2 -0
  162. package/dist/ipc-auth.test.d.ts.map +1 -0
  163. package/dist/ipc-auth.test.js +434 -0
  164. package/dist/ipc-auth.test.js.map +1 -0
  165. package/dist/ipc.d.ts +32 -0
  166. package/dist/ipc.d.ts.map +1 -0
  167. package/dist/ipc.js +311 -0
  168. package/dist/ipc.js.map +1 -0
  169. package/dist/logger.d.ts +3 -0
  170. package/dist/logger.d.ts.map +1 -0
  171. package/dist/logger.js +14 -0
  172. package/dist/logger.js.map +1 -0
  173. package/dist/mount-security.d.ts +34 -0
  174. package/dist/mount-security.d.ts.map +1 -0
  175. package/dist/mount-security.js +325 -0
  176. package/dist/mount-security.js.map +1 -0
  177. package/dist/remote-control.d.ts +32 -0
  178. package/dist/remote-control.d.ts.map +1 -0
  179. package/dist/remote-control.js +185 -0
  180. package/dist/remote-control.js.map +1 -0
  181. package/dist/remote-control.test.d.ts +2 -0
  182. package/dist/remote-control.test.d.ts.map +1 -0
  183. package/dist/remote-control.test.js +321 -0
  184. package/dist/remote-control.test.js.map +1 -0
  185. package/dist/router.d.ts +8 -0
  186. package/dist/router.d.ts.map +1 -0
  187. package/dist/router.js +37 -0
  188. package/dist/router.js.map +1 -0
  189. package/dist/routing.test.d.ts +2 -0
  190. package/dist/routing.test.d.ts.map +1 -0
  191. package/dist/routing.test.js +81 -0
  192. package/dist/routing.test.js.map +1 -0
  193. package/dist/sender-allowlist.d.ts +14 -0
  194. package/dist/sender-allowlist.d.ts.map +1 -0
  195. package/dist/sender-allowlist.js +79 -0
  196. package/dist/sender-allowlist.js.map +1 -0
  197. package/dist/sender-allowlist.test.d.ts +2 -0
  198. package/dist/sender-allowlist.test.d.ts.map +1 -0
  199. package/dist/sender-allowlist.test.js +186 -0
  200. package/dist/sender-allowlist.test.js.map +1 -0
  201. package/dist/session-commands.d.ts +47 -0
  202. package/dist/session-commands.d.ts.map +1 -0
  203. package/dist/session-commands.js +104 -0
  204. package/dist/session-commands.js.map +1 -0
  205. package/dist/session-commands.test.d.ts +2 -0
  206. package/dist/session-commands.test.d.ts.map +1 -0
  207. package/dist/session-commands.test.js +194 -0
  208. package/dist/session-commands.test.js.map +1 -0
  209. package/dist/task-scheduler.d.ts +22 -0
  210. package/dist/task-scheduler.d.ts.map +1 -0
  211. package/dist/task-scheduler.js +241 -0
  212. package/dist/task-scheduler.js.map +1 -0
  213. package/dist/task-scheduler.test.d.ts +2 -0
  214. package/dist/task-scheduler.test.d.ts.map +1 -0
  215. package/dist/task-scheduler.test.js +107 -0
  216. package/dist/task-scheduler.test.js.map +1 -0
  217. package/dist/timezone.d.ts +6 -0
  218. package/dist/timezone.d.ts.map +1 -0
  219. package/dist/timezone.js +17 -0
  220. package/dist/timezone.js.map +1 -0
  221. package/dist/timezone.test.d.ts +2 -0
  222. package/dist/timezone.test.d.ts.map +1 -0
  223. package/dist/timezone.test.js +23 -0
  224. package/dist/timezone.test.js.map +1 -0
  225. package/dist/types.d.ts +79 -0
  226. package/dist/types.d.ts.map +1 -0
  227. package/dist/types.js +2 -0
  228. package/dist/types.js.map +1 -0
  229. package/docs/APPLE-CONTAINER-NETWORKING.md +90 -0
  230. package/docs/DEBUG_CHECKLIST.md +143 -0
  231. package/docs/REQUIREMENTS.md +196 -0
  232. package/docs/SDK_DEEP_DIVE.md +643 -0
  233. package/docs/SECURITY.md +122 -0
  234. package/docs/SPEC.md +785 -0
  235. package/docs/docker-sandboxes.md +359 -0
  236. package/docs/nanoclaw-architecture-final.md +1063 -0
  237. package/docs/nanorepo-architecture.md +168 -0
  238. package/docs/skills-as-branches.md +662 -0
  239. package/groups/global/CLAUDE.md +58 -0
  240. package/groups/main/CLAUDE.md +246 -0
  241. package/launchd/com.nanoclaw.plist +32 -0
  242. package/package.json +45 -0
  243. package/repo-tokens/README.md +113 -0
  244. package/repo-tokens/action.yml +186 -0
  245. package/repo-tokens/badge.svg +23 -0
  246. package/repo-tokens/examples/green.svg +14 -0
  247. package/repo-tokens/examples/red.svg +14 -0
  248. package/repo-tokens/examples/yellow-green.svg +14 -0
  249. package/repo-tokens/examples/yellow.svg +14 -0
  250. package/scripts/run-migrations.ts +105 -0
  251. package/setup/container.ts +144 -0
  252. package/setup/environment.test.ts +121 -0
  253. package/setup/environment.ts +94 -0
  254. package/setup/groups.ts +229 -0
  255. package/setup/index.ts +58 -0
  256. package/setup/mounts.ts +115 -0
  257. package/setup/platform.test.ts +120 -0
  258. package/setup/platform.ts +132 -0
  259. package/setup/register.test.ts +257 -0
  260. package/setup/register.ts +177 -0
  261. package/setup/service.test.ts +187 -0
  262. package/setup/service.ts +362 -0
  263. package/setup/status.ts +16 -0
  264. package/setup/verify.ts +192 -0
  265. package/setup.sh +161 -0
  266. package/src/channels/index.ts +15 -0
  267. package/src/channels/registry.test.ts +42 -0
  268. package/src/channels/registry.ts +32 -0
  269. package/src/channels/web.ts +1931 -0
  270. package/src/cli.ts +209 -0
  271. package/src/config.ts +73 -0
  272. package/src/container-runner.test.ts +210 -0
  273. package/src/container-runner.ts +768 -0
  274. package/src/container-runtime.test.ts +149 -0
  275. package/src/container-runtime.ts +127 -0
  276. package/src/credential-proxy.test.ts +192 -0
  277. package/src/credential-proxy.ts +125 -0
  278. package/src/db.test.ts +484 -0
  279. package/src/db.ts +803 -0
  280. package/src/env.ts +42 -0
  281. package/src/formatting.test.ts +256 -0
  282. package/src/group-folder.test.ts +43 -0
  283. package/src/group-folder.ts +44 -0
  284. package/src/group-queue.test.ts +484 -0
  285. package/src/group-queue.ts +379 -0
  286. package/src/index.ts +832 -0
  287. package/src/ipc-auth.test.ts +679 -0
  288. package/src/ipc.ts +461 -0
  289. package/src/logger.ts +16 -0
  290. package/src/mount-security.ts +419 -0
  291. package/src/remote-control.test.ts +397 -0
  292. package/src/remote-control.ts +224 -0
  293. package/src/router.ts +52 -0
  294. package/src/routing.test.ts +170 -0
  295. package/src/sender-allowlist.test.ts +216 -0
  296. package/src/sender-allowlist.ts +128 -0
  297. package/src/session-commands.test.ts +247 -0
  298. package/src/session-commands.ts +163 -0
  299. package/src/task-scheduler.test.ts +129 -0
  300. package/src/task-scheduler.ts +328 -0
  301. package/src/timezone.test.ts +29 -0
  302. package/src/timezone.ts +16 -0
  303. package/src/types.ts +109 -0
  304. package/tsconfig.json +20 -0
  305. package/vitest.config.ts +7 -0
  306. package/vitest.skills.config.ts +7 -0
@@ -0,0 +1,153 @@
1
+ ---
2
+ name: add-ollama-tool
3
+ description: Add Ollama MCP server so the container agent can call local models for cheaper/faster tasks like summarization, translation, or general queries.
4
+ ---
5
+
6
+ # Add Ollama Integration
7
+
8
+ This skill adds a stdio-based MCP server that exposes local Ollama models as tools for the container agent. Claude remains the orchestrator but can offload work to local models.
9
+
10
+ Tools added:
11
+ - `ollama_list_models` — lists installed Ollama models
12
+ - `ollama_generate` — sends a prompt to a specified model and returns the response
13
+
14
+ ## Phase 1: Pre-flight
15
+
16
+ ### Check if already applied
17
+
18
+ Check if `container/agent-runner/src/ollama-mcp-stdio.ts` exists. If it does, skip to Phase 3 (Configure).
19
+
20
+ ### Check prerequisites
21
+
22
+ Verify Ollama is installed and running on the host:
23
+
24
+ ```bash
25
+ ollama list
26
+ ```
27
+
28
+ If Ollama is not installed, direct the user to https://ollama.com/download.
29
+
30
+ If no models are installed, suggest pulling one:
31
+
32
+ > You need at least one model. I recommend:
33
+ >
34
+ > ```bash
35
+ > ollama pull gemma3:1b # Small, fast (1GB)
36
+ > ollama pull llama3.2 # Good general purpose (2GB)
37
+ > ollama pull qwen3-coder:30b # Best for code tasks (18GB)
38
+ > ```
39
+
40
+ ## Phase 2: Apply Code Changes
41
+
42
+ ### Ensure upstream remote
43
+
44
+ ```bash
45
+ git remote -v
46
+ ```
47
+
48
+ If `upstream` is missing, add it:
49
+
50
+ ```bash
51
+ git remote add upstream https://github.com/qwibitai/nanoclaw.git
52
+ ```
53
+
54
+ ### Merge the skill branch
55
+
56
+ ```bash
57
+ git fetch upstream skill/ollama-tool
58
+ git merge upstream/skill/ollama-tool
59
+ ```
60
+
61
+ This merges in:
62
+ - `container/agent-runner/src/ollama-mcp-stdio.ts` (Ollama MCP server)
63
+ - `scripts/ollama-watch.sh` (macOS notification watcher)
64
+ - Ollama MCP config in `container/agent-runner/src/index.ts` (allowedTools + mcpServers)
65
+ - `[OLLAMA]` log surfacing in `src/container-runner.ts`
66
+ - `OLLAMA_HOST` in `.env.example`
67
+
68
+ If the merge reports conflicts, resolve them by reading the conflicted files and understanding the intent of both sides.
69
+
70
+ ### Copy to per-group agent-runner
71
+
72
+ Existing groups have a cached copy of the agent-runner source. Copy the new files:
73
+
74
+ ```bash
75
+ for dir in data/sessions/*/agent-runner-src; do
76
+ cp container/agent-runner/src/ollama-mcp-stdio.ts "$dir/"
77
+ cp container/agent-runner/src/index.ts "$dir/"
78
+ done
79
+ ```
80
+
81
+ ### Validate code changes
82
+
83
+ ```bash
84
+ npm run build
85
+ ./container/build.sh
86
+ ```
87
+
88
+ Build must be clean before proceeding.
89
+
90
+ ## Phase 3: Configure
91
+
92
+ ### Set Ollama host (optional)
93
+
94
+ By default, the MCP server connects to `http://host.docker.internal:11434` (Docker Desktop) with a fallback to `localhost`. To use a custom Ollama host, add to `.env`:
95
+
96
+ ```bash
97
+ OLLAMA_HOST=http://your-ollama-host:11434
98
+ ```
99
+
100
+ ### Restart the service
101
+
102
+ ```bash
103
+ launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
104
+ # Linux: systemctl --user restart nanoclaw
105
+ ```
106
+
107
+ ## Phase 4: Verify
108
+
109
+ ### Test via WhatsApp
110
+
111
+ Tell the user:
112
+
113
+ > Send a message like: "use ollama to tell me the capital of France"
114
+ >
115
+ > The agent should use `ollama_list_models` to find available models, then `ollama_generate` to get a response.
116
+
117
+ ### Monitor activity (optional)
118
+
119
+ Run the watcher script for macOS notifications when Ollama is used:
120
+
121
+ ```bash
122
+ ./scripts/ollama-watch.sh
123
+ ```
124
+
125
+ ### Check logs if needed
126
+
127
+ ```bash
128
+ tail -f logs/nanoclaw.log | grep -i ollama
129
+ ```
130
+
131
+ Look for:
132
+ - `Agent output: ... Ollama ...` — agent used Ollama successfully
133
+ - `[OLLAMA] >>> Generating` — generation started (if log surfacing works)
134
+ - `[OLLAMA] <<< Done` — generation completed
135
+
136
+ ## Troubleshooting
137
+
138
+ ### Agent says "Ollama is not installed"
139
+
140
+ The agent is trying to run `ollama` CLI inside the container instead of using the MCP tools. This means:
141
+ 1. The MCP server wasn't registered — check `container/agent-runner/src/index.ts` has the `ollama` entry in `mcpServers`
142
+ 2. The per-group source wasn't updated — re-copy files (see Phase 2)
143
+ 3. The container wasn't rebuilt — run `./container/build.sh`
144
+
145
+ ### "Failed to connect to Ollama"
146
+
147
+ 1. Verify Ollama is running: `ollama list`
148
+ 2. Check Docker can reach the host: `docker run --rm curlimages/curl curl -s http://host.docker.internal:11434/api/tags`
149
+ 3. If using a custom host, check `OLLAMA_HOST` in `.env`
150
+
151
+ ### Agent doesn't use Ollama tools
152
+
153
+ The agent may not know about the tools. Try being explicit: "use the ollama_generate tool with gemma3:1b to answer: ..."
@@ -0,0 +1,290 @@
1
+ # Add Parallel AI Integration
2
+
3
+ Adds Parallel AI MCP integration to NanoClaw for advanced web research capabilities.
4
+
5
+ ## What This Adds
6
+
7
+ - **Quick Search** - Fast web lookups using Parallel Search API (free to use)
8
+ - **Deep Research** - Comprehensive analysis using Parallel Task API (asks permission)
9
+ - **Non-blocking Design** - Uses NanoClaw scheduler for result polling (no container blocking)
10
+
11
+ ## Prerequisites
12
+
13
+ User must have:
14
+ 1. Parallel AI API key from https://platform.parallel.ai
15
+ 2. NanoClaw already set up and running
16
+ 3. Docker installed and running
17
+
18
+ ## Implementation Steps
19
+
20
+ Run all steps automatically. Only pause for user input when explicitly needed.
21
+
22
+ ### 1. Get Parallel AI API Key
23
+
24
+ Use `AskUserQuestion: Do you have a Parallel AI API key, or should I help you get one?`
25
+
26
+ **If they have one:**
27
+ Collect it now.
28
+
29
+ **If they need one:**
30
+ Tell them:
31
+ > 1. Go to https://platform.parallel.ai
32
+ > 2. Sign up or log in
33
+ > 3. Navigate to API Keys section
34
+ > 4. Create a new API key
35
+ > 5. Copy the key and paste it here
36
+
37
+ Wait for the API key.
38
+
39
+ ### 2. Add API Key to Environment
40
+
41
+ Add `PARALLEL_API_KEY` to `.env`:
42
+
43
+ ```bash
44
+ # Check if .env exists, create if not
45
+ if [ ! -f .env ]; then
46
+ touch .env
47
+ fi
48
+
49
+ # Add PARALLEL_API_KEY if not already present
50
+ if ! grep -q "PARALLEL_API_KEY=" .env; then
51
+ echo "PARALLEL_API_KEY=${API_KEY_FROM_USER}" >> .env
52
+ echo "✓ Added PARALLEL_API_KEY to .env"
53
+ else
54
+ # Update existing key
55
+ sed -i.bak "s/^PARALLEL_API_KEY=.*/PARALLEL_API_KEY=${API_KEY_FROM_USER}/" .env
56
+ echo "✓ Updated PARALLEL_API_KEY in .env"
57
+ fi
58
+ ```
59
+
60
+ Verify:
61
+ ```bash
62
+ grep "PARALLEL_API_KEY" .env | head -c 50
63
+ ```
64
+
65
+ ### 3. Update Container Runner
66
+
67
+ Add `PARALLEL_API_KEY` to allowed environment variables in `src/container-runner.ts`:
68
+
69
+ Find the line:
70
+ ```typescript
71
+ const allowedVars = ['CLAUDE_CODE_OAUTH_TOKEN', 'ANTHROPIC_API_KEY'];
72
+ ```
73
+
74
+ Replace with:
75
+ ```typescript
76
+ const allowedVars = ['CLAUDE_CODE_OAUTH_TOKEN', 'ANTHROPIC_API_KEY', 'PARALLEL_API_KEY'];
77
+ ```
78
+
79
+ ### 4. Configure MCP Servers in Agent Runner
80
+
81
+ Update `container/agent-runner/src/index.ts`:
82
+
83
+ Find the section where `mcpServers` is configured (around line 237-252):
84
+ ```typescript
85
+ const mcpServers: Record<string, any> = {
86
+ nanoclaw: ipcMcp
87
+ };
88
+ ```
89
+
90
+ Add Parallel AI MCP servers after the nanoclaw server:
91
+ ```typescript
92
+ const mcpServers: Record<string, any> = {
93
+ nanoclaw: ipcMcp
94
+ };
95
+
96
+ // Add Parallel AI MCP servers if API key is available
97
+ const parallelApiKey = process.env.PARALLEL_API_KEY;
98
+ if (parallelApiKey) {
99
+ mcpServers['parallel-search'] = {
100
+ type: 'http', // REQUIRED: Must specify type for HTTP MCP servers
101
+ url: 'https://search-mcp.parallel.ai/mcp',
102
+ headers: {
103
+ 'Authorization': `Bearer ${parallelApiKey}`
104
+ }
105
+ };
106
+ mcpServers['parallel-task'] = {
107
+ type: 'http', // REQUIRED: Must specify type for HTTP MCP servers
108
+ url: 'https://task-mcp.parallel.ai/mcp',
109
+ headers: {
110
+ 'Authorization': `Bearer ${parallelApiKey}`
111
+ }
112
+ };
113
+ log('Parallel AI MCP servers configured');
114
+ } else {
115
+ log('PARALLEL_API_KEY not set, skipping Parallel AI integration');
116
+ }
117
+ ```
118
+
119
+ Also update the `allowedTools` array to include Parallel MCP tools (around line 242-248):
120
+ ```typescript
121
+ allowedTools: [
122
+ 'Bash',
123
+ 'Read', 'Write', 'Edit', 'Glob', 'Grep',
124
+ 'WebSearch', 'WebFetch',
125
+ 'mcp__nanoclaw__*',
126
+ 'mcp__parallel-search__*',
127
+ 'mcp__parallel-task__*'
128
+ ],
129
+ ```
130
+
131
+ ### 5. Add Usage Instructions to CLAUDE.md
132
+
133
+ Add Parallel AI usage instructions to `groups/main/CLAUDE.md`:
134
+
135
+ Find the "## What You Can Do" section and add after the existing bullet points:
136
+ ```markdown
137
+ - Use Parallel AI for web research and deep learning tasks
138
+ ```
139
+
140
+ Then add a new section after "## What You Can Do":
141
+ ```markdown
142
+ ## Web Research Tools
143
+
144
+ You have access to two Parallel AI research tools:
145
+
146
+ ### Quick Web Search (`mcp__parallel-search__search`)
147
+ **When to use:** Freely use for factual lookups, current events, definitions, recent information, or verifying facts.
148
+
149
+ **Examples:**
150
+ - "Who invented the transistor?"
151
+ - "What's the latest news about quantum computing?"
152
+ - "When was the UN founded?"
153
+ - "What are the top programming languages in 2026?"
154
+
155
+ **Speed:** Fast (2-5 seconds)
156
+ **Cost:** Low
157
+ **Permission:** Not needed - use whenever it helps answer the question
158
+
159
+ ### Deep Research (`mcp__parallel-task__create_task_run`)
160
+ **When to use:** Comprehensive analysis, learning about complex topics, comparing concepts, historical overviews, or structured research.
161
+
162
+ **Examples:**
163
+ - "Explain the development of quantum mechanics from 1900-1930"
164
+ - "Compare the literary styles of Hemingway and Faulkner"
165
+ - "Research the evolution of jazz from bebop to fusion"
166
+ - "Analyze the causes of the French Revolution"
167
+
168
+ **Speed:** Slower (1-20 minutes depending on depth)
169
+ **Cost:** Higher (varies by processor tier)
170
+ **Permission:** ALWAYS use `AskUserQuestion` before using this tool
171
+
172
+ **How to ask permission:**
173
+ ```
174
+ AskUserQuestion: I can do deep research on [topic] using Parallel's Task API. This will take 2-5 minutes and provide comprehensive analysis with citations. Should I proceed?
175
+ ```
176
+
177
+ **After permission - DO NOT BLOCK! Use scheduler instead:**
178
+
179
+ 1. Create the task using `mcp__parallel-task__create_task_run`
180
+ 2. Get the `run_id` from the response
181
+ 3. Create a polling scheduled task using `mcp__nanoclaw__schedule_task`:
182
+ ```
183
+ Prompt: "Check Parallel AI task run [run_id] and send results when ready.
184
+
185
+ 1. Use the Parallel Task MCP to check the task status
186
+ 2. If status is 'completed', extract the results
187
+ 3. Send results to user with mcp__nanoclaw__send_message
188
+ 4. Use mcp__nanoclaw__complete_scheduled_task to mark this task as done
189
+
190
+ If status is still 'running' or 'pending', do nothing (task will run again in 30s).
191
+ If status is 'failed', send error message and complete the task."
192
+
193
+ Schedule: interval every 30 seconds
194
+ Context mode: isolated
195
+ ```
196
+ 4. Send acknowledgment with tracking link
197
+ 5. Exit immediately - scheduler handles the rest
198
+
199
+ ### Choosing Between Them
200
+
201
+ **Use Search when:**
202
+ - Question needs a quick fact or recent information
203
+ - Simple definition or clarification
204
+ - Verifying specific details
205
+ - Current events or news
206
+
207
+ **Use Deep Research (with permission) when:**
208
+ - User wants to learn about a complex topic
209
+ - Question requires analysis or comparison
210
+ - Historical context or evolution of concepts
211
+ - Structured, comprehensive understanding needed
212
+ - User explicitly asks to "research" or "explain in depth"
213
+
214
+ **Default behavior:** Prefer search for most questions. Only suggest deep research when the topic genuinely requires comprehensive analysis.
215
+ ```
216
+
217
+ ### 6. Rebuild Container
218
+
219
+ Build the container with updated agent runner:
220
+
221
+ ```bash
222
+ ./container/build.sh
223
+ ```
224
+
225
+ Verify the build:
226
+ ```bash
227
+ echo '{}' | docker run -i --entrypoint /bin/echo nanoclaw-agent:latest "Container OK"
228
+ ```
229
+
230
+ ### 7. Restart Service
231
+
232
+ Rebuild the main app and restart:
233
+
234
+ ```bash
235
+ npm run build
236
+ launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
237
+ # Linux: systemctl --user restart nanoclaw
238
+ ```
239
+
240
+ Wait 3 seconds for service to start, then verify:
241
+ ```bash
242
+ sleep 3
243
+ launchctl list | grep nanoclaw # macOS
244
+ # Linux: systemctl --user status nanoclaw
245
+ ```
246
+
247
+ ### 8. Test Integration
248
+
249
+ Tell the user to test:
250
+ > Send a message to your assistant: `@[YourAssistantName] what's the latest news about AI?`
251
+ >
252
+ > The assistant should use Parallel Search API to find current information.
253
+ >
254
+ > Then try: `@[YourAssistantName] can you research the history of artificial intelligence?`
255
+ >
256
+ > The assistant should ask for permission before using the Task API.
257
+
258
+ Check logs to verify MCP servers loaded:
259
+ ```bash
260
+ tail -20 logs/nanoclaw.log
261
+ ```
262
+
263
+ Look for: `Parallel AI MCP servers configured`
264
+
265
+ ## Troubleshooting
266
+
267
+ **Container hangs or times out:**
268
+ - Check that `type: 'http'` is specified in MCP server config
269
+ - Verify API key is correct in .env
270
+ - Check container logs: `cat groups/main/logs/container-*.log | tail -50`
271
+
272
+ **MCP servers not loading:**
273
+ - Ensure PARALLEL_API_KEY is in .env
274
+ - Verify container-runner.ts includes PARALLEL_API_KEY in allowedVars
275
+ - Check agent-runner logs for "Parallel AI MCP servers configured" message
276
+
277
+ **Task polling not working:**
278
+ - Verify scheduled task was created: `sqlite3 store/messages.db "SELECT * FROM scheduled_tasks"`
279
+ - Check task runs: `tail -f logs/nanoclaw.log | grep "scheduled task"`
280
+ - Ensure task prompt includes proper Parallel MCP tool names
281
+
282
+ ## Uninstalling
283
+
284
+ To remove Parallel AI integration:
285
+
286
+ 1. Remove from .env: `sed -i.bak '/PARALLEL_API_KEY/d' .env`
287
+ 2. Revert changes to container-runner.ts and agent-runner/src/index.ts
288
+ 3. Remove Web Research Tools section from groups/main/CLAUDE.md
289
+ 4. Rebuild: `./container/build.sh && npm run build`
290
+ 5. Restart: `launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `systemctl --user restart nanoclaw` (Linux)
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: add-pdf-reader
3
+ description: Add PDF reading to NanoClaw agents. Extracts text from PDFs via pdftotext CLI. Handles WhatsApp attachments, URLs, and local files.
4
+ ---
5
+
6
+ # Add PDF Reader
7
+
8
+ Adds PDF reading capability to all container agents using poppler-utils (pdftotext/pdfinfo). PDFs sent as WhatsApp attachments are auto-downloaded to the group workspace.
9
+
10
+ ## Phase 1: Pre-flight
11
+
12
+ 1. Check if `container/skills/pdf-reader/pdf-reader` exists — skip to Phase 3 if already applied
13
+ 2. Confirm WhatsApp is installed first (`skill/whatsapp` merged). This skill modifies WhatsApp channel files.
14
+
15
+ ## Phase 2: Apply Code Changes
16
+
17
+ ### Ensure WhatsApp fork remote
18
+
19
+ ```bash
20
+ git remote -v
21
+ ```
22
+
23
+ If `whatsapp` is missing, add it:
24
+
25
+ ```bash
26
+ git remote add whatsapp https://github.com/qwibitai/nanoclaw-whatsapp.git
27
+ ```
28
+
29
+ ### Merge the skill branch
30
+
31
+ ```bash
32
+ git fetch whatsapp skill/pdf-reader
33
+ git merge whatsapp/skill/pdf-reader || {
34
+ git checkout --theirs package-lock.json
35
+ git add package-lock.json
36
+ git merge --continue
37
+ }
38
+ ```
39
+
40
+ This merges in:
41
+ - `container/skills/pdf-reader/SKILL.md` (agent-facing documentation)
42
+ - `container/skills/pdf-reader/pdf-reader` (CLI script)
43
+ - `poppler-utils` in `container/Dockerfile`
44
+ - PDF attachment download in `src/channels/whatsapp.ts`
45
+ - PDF tests in `src/channels/whatsapp.test.ts`
46
+
47
+ If the merge reports conflicts, resolve them by reading the conflicted files and understanding the intent of both sides.
48
+
49
+ ### Validate
50
+
51
+ ```bash
52
+ npm run build
53
+ npx vitest run src/channels/whatsapp.test.ts
54
+ ```
55
+
56
+ ### Rebuild container
57
+
58
+ ```bash
59
+ ./container/build.sh
60
+ ```
61
+
62
+ ### Restart service
63
+
64
+ ```bash
65
+ launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
66
+ # Linux: systemctl --user restart nanoclaw
67
+ ```
68
+
69
+ ## Phase 3: Verify
70
+
71
+ ### Test PDF extraction
72
+
73
+ Send a PDF file in any registered WhatsApp chat. The agent should:
74
+ 1. Download the PDF to `attachments/`
75
+ 2. Respond acknowledging the PDF
76
+ 3. Be able to extract text when asked
77
+
78
+ ### Test URL fetching
79
+
80
+ Ask the agent to read a PDF from a URL. It should use `pdf-reader fetch <url>`.
81
+
82
+ ### Check logs if needed
83
+
84
+ ```bash
85
+ tail -f logs/nanoclaw.log | grep -i pdf
86
+ ```
87
+
88
+ Look for:
89
+ - `Downloaded PDF attachment` — successful download
90
+ - `Failed to download PDF attachment` — media download issue
91
+
92
+ ## Troubleshooting
93
+
94
+ ### Agent says pdf-reader command not found
95
+
96
+ Container needs rebuilding. Run `./container/build.sh` and restart the service.
97
+
98
+ ### PDF text extraction is empty
99
+
100
+ The PDF may be scanned (image-based). pdftotext only handles text-based PDFs. Consider using the agent-browser to open the PDF visually instead.
101
+
102
+ ### WhatsApp PDF not detected
103
+
104
+ Verify the message has `documentMessage` with `mimetype: application/pdf`. Some file-sharing apps send PDFs as generic files without the correct mimetype.
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: add-reactions
3
+ description: Add WhatsApp emoji reaction support — receive, send, store, and search reactions.
4
+ ---
5
+
6
+ # Add Reactions
7
+
8
+ This skill adds emoji reaction support to NanoClaw's WhatsApp channel: receive and store reactions, send reactions from the container agent via MCP tool, and query reaction history from SQLite.
9
+
10
+ ## Phase 1: Pre-flight
11
+
12
+ ### Check if already applied
13
+
14
+ Check if `src/status-tracker.ts` exists:
15
+
16
+ ```bash
17
+ test -f src/status-tracker.ts && echo "Already applied" || echo "Not applied"
18
+ ```
19
+
20
+ If already applied, skip to Phase 3 (Verify).
21
+
22
+ ## Phase 2: Apply Code Changes
23
+
24
+ ### Ensure WhatsApp fork remote
25
+
26
+ ```bash
27
+ git remote -v
28
+ ```
29
+
30
+ If `whatsapp` is missing, add it:
31
+
32
+ ```bash
33
+ git remote add whatsapp https://github.com/qwibitai/nanoclaw-whatsapp.git
34
+ ```
35
+
36
+ ### Merge the skill branch
37
+
38
+ ```bash
39
+ git fetch whatsapp skill/reactions
40
+ git merge whatsapp/skill/reactions || {
41
+ git checkout --theirs package-lock.json
42
+ git add package-lock.json
43
+ git merge --continue
44
+ }
45
+ ```
46
+
47
+ This adds:
48
+ - `scripts/migrate-reactions.ts` (database migration for `reactions` table with composite PK and indexes)
49
+ - `src/status-tracker.ts` (forward-only emoji state machine for message lifecycle signaling, with persistence and retry)
50
+ - `src/status-tracker.test.ts` (unit tests for StatusTracker)
51
+ - `container/skills/reactions/SKILL.md` (agent-facing documentation for the `react_to_message` MCP tool)
52
+ - Reaction support in `src/db.ts`, `src/channels/whatsapp.ts`, `src/types.ts`, `src/ipc.ts`, `src/index.ts`, `src/group-queue.ts`, and `container/agent-runner/src/ipc-mcp-stdio.ts`
53
+
54
+ ### Run database migration
55
+
56
+ ```bash
57
+ npx tsx scripts/migrate-reactions.ts
58
+ ```
59
+
60
+ ### Validate code changes
61
+
62
+ ```bash
63
+ npm test
64
+ npm run build
65
+ ```
66
+
67
+ All tests must pass and build must be clean before proceeding.
68
+
69
+ ## Phase 3: Verify
70
+
71
+ ### Build and restart
72
+
73
+ ```bash
74
+ npm run build
75
+ ```
76
+
77
+ Linux:
78
+ ```bash
79
+ systemctl --user restart nanoclaw
80
+ ```
81
+
82
+ macOS:
83
+ ```bash
84
+ launchctl kickstart -k gui/$(id -u)/com.nanoclaw
85
+ ```
86
+
87
+ ### Test receiving reactions
88
+
89
+ 1. Send a message from your phone
90
+ 2. React to it with an emoji on WhatsApp
91
+ 3. Check the database:
92
+
93
+ ```bash
94
+ sqlite3 store/messages.db "SELECT * FROM reactions ORDER BY timestamp DESC LIMIT 5;"
95
+ ```
96
+
97
+ ### Test sending reactions
98
+
99
+ Ask the agent to react to a message via the `react_to_message` MCP tool. Check your phone — the reaction should appear on the message.
100
+
101
+ ## Troubleshooting
102
+
103
+ ### Reactions not appearing in database
104
+
105
+ - Check NanoClaw logs for `Failed to process reaction` errors
106
+ - Verify the chat is registered
107
+ - Confirm the service is running
108
+
109
+ ### Migration fails
110
+
111
+ - Ensure `store/messages.db` exists and is accessible
112
+ - If "table reactions already exists", the migration already ran — skip it
113
+
114
+ ### Agent can't send reactions
115
+
116
+ - Check IPC logs for `Unauthorized IPC reaction attempt blocked` — the agent can only react in its own group's chat
117
+ - Verify WhatsApp is connected: check logs for connection status