@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.
- package/.claude/settings.json +1 -0
- package/.claude/skills/add-compact/SKILL.md +135 -0
- package/.claude/skills/add-discord/SKILL.md +203 -0
- package/.claude/skills/add-gmail/SKILL.md +220 -0
- package/.claude/skills/add-image-vision/SKILL.md +94 -0
- package/.claude/skills/add-ollama-tool/SKILL.md +153 -0
- package/.claude/skills/add-parallel/SKILL.md +290 -0
- package/.claude/skills/add-pdf-reader/SKILL.md +104 -0
- package/.claude/skills/add-reactions/SKILL.md +117 -0
- package/.claude/skills/add-slack/SKILL.md +207 -0
- package/.claude/skills/add-telegram/SKILL.md +222 -0
- package/.claude/skills/add-telegram-swarm/SKILL.md +384 -0
- package/.claude/skills/add-voice-transcription/SKILL.md +148 -0
- package/.claude/skills/add-whatsapp/SKILL.md +372 -0
- package/.claude/skills/convert-to-apple-container/SKILL.md +175 -0
- package/.claude/skills/customize/SKILL.md +110 -0
- package/.claude/skills/debug/SKILL.md +349 -0
- package/.claude/skills/get-qodo-rules/SKILL.md +122 -0
- package/.claude/skills/get-qodo-rules/references/output-format.md +41 -0
- package/.claude/skills/get-qodo-rules/references/pagination.md +33 -0
- package/.claude/skills/get-qodo-rules/references/repository-scope.md +26 -0
- package/.claude/skills/qodo-pr-resolver/SKILL.md +326 -0
- package/.claude/skills/qodo-pr-resolver/resources/providers.md +329 -0
- package/.claude/skills/setup/SKILL.md +218 -0
- package/.claude/skills/update-nanoclaw/SKILL.md +235 -0
- package/.claude/skills/update-skills/SKILL.md +130 -0
- package/.claude/skills/use-local-whisper/SKILL.md +152 -0
- package/.claude/skills/x-integration/SKILL.md +417 -0
- package/.claude/skills/x-integration/agent.ts +243 -0
- package/.claude/skills/x-integration/host.ts +159 -0
- package/.claude/skills/x-integration/lib/browser.ts +148 -0
- package/.claude/skills/x-integration/lib/config.ts +62 -0
- package/.claude/skills/x-integration/scripts/like.ts +56 -0
- package/.claude/skills/x-integration/scripts/post.ts +66 -0
- package/.claude/skills/x-integration/scripts/quote.ts +80 -0
- package/.claude/skills/x-integration/scripts/reply.ts +74 -0
- package/.claude/skills/x-integration/scripts/retweet.ts +62 -0
- package/.claude/skills/x-integration/scripts/setup.ts +87 -0
- package/.env.example +1 -0
- package/.github/CODEOWNERS +10 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +14 -0
- package/.github/workflows/bump-version.yml +32 -0
- package/.github/workflows/ci.yml +25 -0
- package/.github/workflows/merge-forward-skills.yml +160 -0
- package/.github/workflows/update-tokens.yml +42 -0
- package/.husky/pre-commit +1 -0
- package/.mcp.json +3 -0
- package/.nvmrc +1 -0
- package/.prettierrc +3 -0
- package/CHANGELOG.md +8 -0
- package/CLAUDE.md +64 -0
- package/CONTRIBUTING.md +23 -0
- package/CONTRIBUTORS.md +15 -0
- package/LICENSE +21 -0
- package/NanoClaw_with_Web-Support.md +290 -0
- package/README.md +261 -0
- package/README_zh.md +200 -0
- package/assets/nanoclaw-favicon.png +0 -0
- package/assets/nanoclaw-icon.png +0 -0
- package/assets/nanoclaw-logo-dark.png +0 -0
- package/assets/nanoclaw-logo.png +0 -0
- package/assets/nanoclaw-profile.jpeg +0 -0
- package/assets/nanoclaw-sales.png +0 -0
- package/assets/social-preview.jpg +0 -0
- package/config-examples/mount-allowlist.json +25 -0
- package/container/Dockerfile +70 -0
- package/container/agent-runner/package-lock.json +1524 -0
- package/container/agent-runner/package.json +21 -0
- package/container/agent-runner/src/index.ts +558 -0
- package/container/agent-runner/src/ipc-mcp-stdio.ts +338 -0
- package/container/agent-runner/tsconfig.json +15 -0
- package/container/build.sh +23 -0
- package/container/skills/agent-browser/SKILL.md +159 -0
- package/container/skills/capabilities/SKILL.md +100 -0
- package/container/skills/status/SKILL.md +104 -0
- package/dist/channels/index.d.ts +2 -0
- package/dist/channels/index.d.ts.map +1 -0
- package/dist/channels/index.js +9 -0
- package/dist/channels/index.js.map +1 -0
- package/dist/channels/registry.d.ts +13 -0
- package/dist/channels/registry.d.ts.map +1 -0
- package/dist/channels/registry.js +11 -0
- package/dist/channels/registry.js.map +1 -0
- package/dist/channels/registry.test.d.ts +2 -0
- package/dist/channels/registry.test.d.ts.map +1 -0
- package/dist/channels/registry.test.js +32 -0
- package/dist/channels/registry.test.js.map +1 -0
- package/dist/channels/web.d.ts +2 -0
- package/dist/channels/web.d.ts.map +1 -0
- package/dist/channels/web.js +1738 -0
- package/dist/channels/web.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +182 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +36 -0
- package/dist/config.js.map +1 -0
- package/dist/container-runner.d.ts +44 -0
- package/dist/container-runner.d.ts.map +1 -0
- package/dist/container-runner.js +467 -0
- package/dist/container-runner.js.map +1 -0
- package/dist/container-runner.test.d.ts +2 -0
- package/dist/container-runner.test.d.ts.map +1 -0
- package/dist/container-runner.test.js +150 -0
- package/dist/container-runner.test.js.map +1 -0
- package/dist/container-runtime.d.ts +22 -0
- package/dist/container-runtime.d.ts.map +1 -0
- package/dist/container-runtime.js +96 -0
- package/dist/container-runtime.js.map +1 -0
- package/dist/container-runtime.test.d.ts +2 -0
- package/dist/container-runtime.test.d.ts.map +1 -0
- package/dist/container-runtime.test.js +93 -0
- package/dist/container-runtime.test.js.map +1 -0
- package/dist/credential-proxy.d.ts +21 -0
- package/dist/credential-proxy.d.ts.map +1 -0
- package/dist/credential-proxy.js +95 -0
- package/dist/credential-proxy.js.map +1 -0
- package/dist/credential-proxy.test.d.ts +2 -0
- package/dist/credential-proxy.test.d.ts.map +1 -0
- package/dist/credential-proxy.test.js +134 -0
- package/dist/credential-proxy.test.js.map +1 -0
- package/dist/db.d.ts +115 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +549 -0
- package/dist/db.js.map +1 -0
- package/dist/db.test.d.ts +2 -0
- package/dist/db.test.d.ts.map +1 -0
- package/dist/db.test.js +360 -0
- package/dist/db.test.js.map +1 -0
- package/dist/env.d.ts +8 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +42 -0
- package/dist/env.js.map +1 -0
- package/dist/formatting.test.d.ts +2 -0
- package/dist/formatting.test.d.ts.map +1 -0
- package/dist/formatting.test.js +183 -0
- package/dist/formatting.test.js.map +1 -0
- package/dist/group-folder.d.ts +5 -0
- package/dist/group-folder.d.ts.map +1 -0
- package/dist/group-folder.js +44 -0
- package/dist/group-folder.js.map +1 -0
- package/dist/group-folder.test.d.ts +2 -0
- package/dist/group-folder.test.d.ts.map +1 -0
- package/dist/group-folder.test.js +29 -0
- package/dist/group-folder.test.js.map +1 -0
- package/dist/group-queue.d.ts +34 -0
- package/dist/group-queue.d.ts.map +1 -0
- package/dist/group-queue.js +263 -0
- package/dist/group-queue.js.map +1 -0
- package/dist/group-queue.test.d.ts +2 -0
- package/dist/group-queue.test.d.ts.map +1 -0
- package/dist/group-queue.test.js +341 -0
- package/dist/group-queue.test.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +518 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc-auth.test.d.ts +2 -0
- package/dist/ipc-auth.test.d.ts.map +1 -0
- package/dist/ipc-auth.test.js +434 -0
- package/dist/ipc-auth.test.js.map +1 -0
- package/dist/ipc.d.ts +32 -0
- package/dist/ipc.d.ts.map +1 -0
- package/dist/ipc.js +311 -0
- package/dist/ipc.js.map +1 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +14 -0
- package/dist/logger.js.map +1 -0
- package/dist/mount-security.d.ts +34 -0
- package/dist/mount-security.d.ts.map +1 -0
- package/dist/mount-security.js +325 -0
- package/dist/mount-security.js.map +1 -0
- package/dist/remote-control.d.ts +32 -0
- package/dist/remote-control.d.ts.map +1 -0
- package/dist/remote-control.js +185 -0
- package/dist/remote-control.js.map +1 -0
- package/dist/remote-control.test.d.ts +2 -0
- package/dist/remote-control.test.d.ts.map +1 -0
- package/dist/remote-control.test.js +321 -0
- package/dist/remote-control.test.js.map +1 -0
- package/dist/router.d.ts +8 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +37 -0
- package/dist/router.js.map +1 -0
- package/dist/routing.test.d.ts +2 -0
- package/dist/routing.test.d.ts.map +1 -0
- package/dist/routing.test.js +81 -0
- package/dist/routing.test.js.map +1 -0
- package/dist/sender-allowlist.d.ts +14 -0
- package/dist/sender-allowlist.d.ts.map +1 -0
- package/dist/sender-allowlist.js +79 -0
- package/dist/sender-allowlist.js.map +1 -0
- package/dist/sender-allowlist.test.d.ts +2 -0
- package/dist/sender-allowlist.test.d.ts.map +1 -0
- package/dist/sender-allowlist.test.js +186 -0
- package/dist/sender-allowlist.test.js.map +1 -0
- package/dist/session-commands.d.ts +47 -0
- package/dist/session-commands.d.ts.map +1 -0
- package/dist/session-commands.js +102 -0
- package/dist/session-commands.js.map +1 -0
- package/dist/session-commands.test.d.ts +2 -0
- package/dist/session-commands.test.d.ts.map +1 -0
- package/dist/session-commands.test.js +190 -0
- package/dist/session-commands.test.js.map +1 -0
- package/dist/task-scheduler.d.ts +22 -0
- package/dist/task-scheduler.d.ts.map +1 -0
- package/dist/task-scheduler.js +210 -0
- package/dist/task-scheduler.js.map +1 -0
- package/dist/task-scheduler.test.d.ts +2 -0
- package/dist/task-scheduler.test.d.ts.map +1 -0
- package/dist/task-scheduler.test.js +107 -0
- package/dist/task-scheduler.test.js.map +1 -0
- package/dist/timezone.d.ts +6 -0
- package/dist/timezone.d.ts.map +1 -0
- package/dist/timezone.js +17 -0
- package/dist/timezone.js.map +1 -0
- package/dist/timezone.test.d.ts +2 -0
- package/dist/timezone.test.d.ts.map +1 -0
- package/dist/timezone.test.js +23 -0
- package/dist/timezone.test.js.map +1 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/docs/APPLE-CONTAINER-NETWORKING.md +90 -0
- package/docs/DEBUG_CHECKLIST.md +143 -0
- package/docs/REQUIREMENTS.md +196 -0
- package/docs/SDK_DEEP_DIVE.md +643 -0
- package/docs/SECURITY.md +122 -0
- package/docs/SPEC.md +785 -0
- package/docs/docker-sandboxes.md +359 -0
- package/docs/nanoclaw-architecture-final.md +1063 -0
- package/docs/nanorepo-architecture.md +168 -0
- package/docs/skills-as-branches.md +662 -0
- package/groups/global/CLAUDE.md +58 -0
- package/groups/main/CLAUDE.md +246 -0
- package/launchd/com.nanoclaw.plist +32 -0
- package/package.json +45 -0
- package/repo-tokens/README.md +113 -0
- package/repo-tokens/action.yml +186 -0
- package/repo-tokens/badge.svg +23 -0
- package/repo-tokens/examples/green.svg +14 -0
- package/repo-tokens/examples/red.svg +14 -0
- package/repo-tokens/examples/yellow-green.svg +14 -0
- package/repo-tokens/examples/yellow.svg +14 -0
- package/scripts/run-migrations.ts +105 -0
- package/setup/container.ts +144 -0
- package/setup/environment.test.ts +121 -0
- package/setup/environment.ts +94 -0
- package/setup/groups.ts +229 -0
- package/setup/index.ts +58 -0
- package/setup/mounts.ts +115 -0
- package/setup/platform.test.ts +120 -0
- package/setup/platform.ts +132 -0
- package/setup/register.test.ts +257 -0
- package/setup/register.ts +177 -0
- package/setup/service.test.ts +187 -0
- package/setup/service.ts +362 -0
- package/setup/status.ts +16 -0
- package/setup/verify.ts +192 -0
- package/setup.sh +161 -0
- package/src/channels/index.ts +12 -0
- package/src/channels/registry.test.ts +42 -0
- package/src/channels/registry.ts +32 -0
- package/src/channels/web.ts +1856 -0
- package/src/cli.ts +209 -0
- package/src/config.ts +73 -0
- package/src/container-runner.test.ts +210 -0
- package/src/container-runner.ts +707 -0
- package/src/container-runtime.test.ts +149 -0
- package/src/container-runtime.ts +127 -0
- package/src/credential-proxy.test.ts +192 -0
- package/src/credential-proxy.ts +125 -0
- package/src/db.test.ts +484 -0
- package/src/db.ts +803 -0
- package/src/env.ts +42 -0
- package/src/formatting.test.ts +256 -0
- package/src/group-folder.test.ts +43 -0
- package/src/group-folder.ts +44 -0
- package/src/group-queue.test.ts +484 -0
- package/src/group-queue.ts +365 -0
- package/src/index.ts +731 -0
- package/src/ipc-auth.test.ts +679 -0
- package/src/ipc.ts +461 -0
- package/src/logger.ts +16 -0
- package/src/mount-security.ts +419 -0
- package/src/remote-control.test.ts +397 -0
- package/src/remote-control.ts +224 -0
- package/src/router.ts +52 -0
- package/src/routing.test.ts +170 -0
- package/src/sender-allowlist.test.ts +216 -0
- package/src/sender-allowlist.ts +128 -0
- package/src/session-commands.test.ts +247 -0
- package/src/session-commands.ts +163 -0
- package/src/task-scheduler.test.ts +129 -0
- package/src/task-scheduler.ts +295 -0
- package/src/timezone.test.ts +29 -0
- package/src/timezone.ts +16 -0
- package/src/types.ts +107 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +7 -0
- 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`.
|
package/CONTRIBUTING.md
ADDED
|
@@ -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.
|
package/CONTRIBUTORS.md
ADDED
|
@@ -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).
|