docs: convert all skill instructions from npm to pnpm

Batch update 62 files across .claude/skills/ — SKILL.md, REMOVE.md,
and script files. Conversions: npm run -> pnpm run, npm install ->
pnpm install, npx -> pnpm exec/dlx, npm uninstall -> pnpm uninstall,
package-lock.json -> pnpm-lock.yaml, shebangs updated.
This commit is contained in:
meeech
2026-04-14 00:34:36 -04:00
committed by gavrielc
parent 8fbf9861f1
commit 211d2b5877
62 changed files with 232 additions and 232 deletions
+5 -5
View File
@@ -39,8 +39,8 @@ This adds:
### Validate
```bash
npm test
npm run build
pnpm test
pnpm run build
```
### Rebuild container
@@ -60,7 +60,7 @@ launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
### Integration Test
1. Start NanoClaw in dev mode: `npm run dev`
1. Start NanoClaw in dev mode: `pnpm run dev`
2. From the **main group** (self-chat), send exactly: `/compact`
3. Verify:
- The agent acknowledges compaction (e.g., "Conversation compacted.")
@@ -104,8 +104,8 @@ launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
git clone <your-fork> /tmp/nanoclaw-test
cd /tmp/nanoclaw-test
claude # then run /add-compact
npm run build
npm test
pnpm run build
pnpm test
./container/build.sh
# Manual: send /compact from main group, verify compaction + continuation
# Manual: send @<assistant> /compact from non-main as non-admin, verify denial
+1 -1
View File
@@ -26,7 +26,7 @@ import './discord.js';
### Build
```bash
npm run build
pnpm run build
```
## Credentials
+9 -9
View File
@@ -40,8 +40,8 @@ git remote add discord https://github.com/qwibitai/nanoclaw-discord.git
```bash
git fetch discord main
git merge discord/main || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -58,9 +58,9 @@ If the merge reports conflicts, resolve them by reading the conflicted files and
### Validate code changes
```bash
npm install
npm run build
npx vitest run src/channels/discord.test.ts
pnpm install
pnpm run build
pnpm exec vitest run src/channels/discord.test.ts
```
All tests must pass (including the new Discord tests) and build must be clean before proceeding.
@@ -108,7 +108,7 @@ The container reads environment from `data/env/env`, not `.env` directly.
### Build and restart
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw
```
@@ -130,18 +130,18 @@ Wait for the user to provide the channel ID (format: `dc:1234567890123456`).
### Register the channel
The channel ID, name, and folder name are needed. Use `npx tsx setup/index.ts --step register` with the appropriate flags.
The channel ID, name, and folder name are needed. Use `pnpm exec tsx setup/index.ts --step register` with the appropriate flags.
For a main channel (responds to all messages):
```bash
npx tsx setup/index.ts --step register -- --jid "dc:<channel-id>" --name "<server-name> #<channel-name>" --folder "discord_main" --trigger "@${ASSISTANT_NAME}" --channel discord --no-trigger-required --is-main
pnpm exec tsx setup/index.ts --step register -- --jid "dc:<channel-id>" --name "<server-name> #<channel-name>" --folder "discord_main" --trigger "@${ASSISTANT_NAME}" --channel discord --no-trigger-required --is-main
```
For additional channels (trigger-only):
```bash
npx tsx setup/index.ts --step register -- --jid "dc:<channel-id>" --name "<server-name> #<channel-name>" --folder "discord_<channel-name>" --trigger "@${ASSISTANT_NAME}" --channel discord
pnpm exec tsx setup/index.ts --step register -- --jid "dc:<channel-id>" --name "<server-name> #<channel-name>" --folder "discord_<channel-name>" --trigger "@${ASSISTANT_NAME}" --channel discord
```
## Phase 5: Verify
+10 -10
View File
@@ -51,12 +51,12 @@ git fetch upstream skill/emacs
git merge upstream/skill/emacs
```
If there are merge conflicts on `package-lock.json`, resolve them by accepting the incoming
If there are merge conflicts on `pnpm-lock.yaml`, resolve them by accepting the incoming
version and continuing:
```bash
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
```
@@ -73,8 +73,8 @@ If the merge reports conflicts, resolve them by reading the conflicted files and
### Validate code changes
```bash
npm run build
npx vitest run src/channels/emacs.test.ts
pnpm run build
pnpm exec vitest run src/channels/emacs.test.ts
```
Build must be clean and tests must pass before proceeding.
@@ -158,7 +158,7 @@ If `EMACS_CHANNEL_PORT` was changed from the default, also add:
### Restart NanoClaw
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
```
@@ -246,18 +246,18 @@ If NanoClaw is cloned elsewhere, update the `load`/`load-file` path in your Emac
## After Setup
If running `npm run dev` while the service is active:
If running `pnpm run dev` while the service is active:
```bash
# macOS:
launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist
npm run dev
pnpm run dev
# When done testing:
launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist
# Linux:
# systemctl --user stop nanoclaw
# npm run dev
# pnpm run dev
# systemctl --user start nanoclaw
```
@@ -286,4 +286,4 @@ To remove the Emacs channel:
3. Remove the NanoClaw block from your Emacs config file
4. Remove Emacs registration from SQLite: `sqlite3 store/messages.db "DELETE FROM registered_groups WHERE jid = 'emacs:default'"`
5. Remove `EMACS_CHANNEL_PORT` and `EMACS_AUTH_TOKEN` from `.env` if set
6. Rebuild: `npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `npm run build && systemctl --user restart nanoclaw` (Linux)
6. Rebuild: `pnpm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `pnpm run build && systemctl --user restart nanoclaw` (Linux)
+1 -1
View File
@@ -2,5 +2,5 @@
1. Comment out `import './gchat.js'` in `src/channels/index.ts`
2. Remove `GCHAT_CREDENTIALS` from `.env`
3. `npm uninstall @chat-adapter/gchat`
3. `ppnpm uninstall @chat-adapter/gchat`
4. Rebuild and restart
+2 -2
View File
@@ -14,7 +14,7 @@ Check if `src/channels/gchat.ts` exists and the import is uncommented in `src/ch
## Install
```bash
npm install @chat-adapter/gchat
pnpm install @chat-adapter/gchat
```
Uncomment the Google Chat import in `src/channels/index.ts`:
@@ -24,7 +24,7 @@ import './gchat.js';
```
```bash
npm run build
pnpm run build
```
## Credentials
+1 -1
View File
@@ -2,5 +2,5 @@
1. Comment out `import './github.js'` in `src/channels/index.ts`
2. Remove `GITHUB_TOKEN` and `GITHUB_WEBHOOK_SECRET` from `.env`
3. `npm uninstall @chat-adapter/github`
3. `ppnpm uninstall @chat-adapter/github`
4. Rebuild and restart
+2 -2
View File
@@ -14,7 +14,7 @@ Check if `src/channels/github.ts` exists and the import is uncommented in `src/c
## Install
```bash
npm install @chat-adapter/github
pnpm install @chat-adapter/github
```
Uncomment the GitHub import in `src/channels/index.ts`:
@@ -24,7 +24,7 @@ import './github.js';
```
```bash
npm run build
pnpm run build
```
## Credentials
+13 -13
View File
@@ -41,8 +41,8 @@ git remote add gmail https://github.com/qwibitai/nanoclaw-gmail.git
```bash
git fetch gmail main
git merge gmail/main || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -70,9 +70,9 @@ When you receive an email notification (messages starting with `[Email from ...`
### Validate code changes
```bash
npm install
npm run build
npx vitest run src/channels/gmail.test.ts
pnpm install
pnpm run build
pnpm exec vitest run src/channels/gmail.test.ts
```
All tests must pass (including the new Gmail tests) and build must be clean before proceeding.
@@ -136,10 +136,10 @@ Tell the user:
Run the authorization:
```bash
npx -y @gongrzhe/server-gmail-autoauth-mcp auth
pnpm dlx @gongrzhe/server-gmail-autoauth-mcp auth
```
If that fails (some versions don't have an auth subcommand), try `timeout 60 npx -y @gongrzhe/server-gmail-autoauth-mcp || true`. Verify with `ls ~/.gmail-mcp/credentials.json`.
If that fails (some versions don't have an auth subcommand), try `timeout 60 pnpm dlx @gongrzhe/server-gmail-autoauth-mcp || true`. Verify with `ls ~/.gmail-mcp/credentials.json`.
### Build and restart
@@ -158,7 +158,7 @@ cd container && ./build.sh
Then compile and restart:
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
```
@@ -192,7 +192,7 @@ tail -f logs/nanoclaw.log
Test directly:
```bash
npx -y @gongrzhe/server-gmail-autoauth-mcp
pnpm dlx @gongrzhe/server-gmail-autoauth-mcp
```
### OAuth token expired
@@ -201,7 +201,7 @@ Re-authorize:
```bash
rm ~/.gmail-mcp/credentials.json
npx -y @gongrzhe/server-gmail-autoauth-mcp
pnpm dlx @gongrzhe/server-gmail-autoauth-mcp
```
### Container can't access Gmail
@@ -222,7 +222,7 @@ npx -y @gongrzhe/server-gmail-autoauth-mcp
2. Remove `gmail` MCP server and `mcp__gmail__*` from `container/agent-runner/src/index.ts`
3. Rebuild and restart
4. Clear stale agent-runner copies: `rm -r data/sessions/*/agent-runner-src 2>/dev/null || true`
5. Rebuild: `cd container && ./build.sh && cd .. && npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `systemctl --user restart nanoclaw` (Linux)
5. Rebuild: `cd container && ./build.sh && cd .. && pnpm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `systemctl --user restart nanoclaw` (Linux)
### Channel mode
@@ -230,7 +230,7 @@ npx -y @gongrzhe/server-gmail-autoauth-mcp
2. Remove `import './gmail.js'` from `src/channels/index.ts`
3. Remove `~/.gmail-mcp` mount from `src/container-runner.ts`
4. Remove `gmail` MCP server and `mcp__gmail__*` from `container/agent-runner/src/index.ts`
5. Uninstall: `npm uninstall googleapis`
5. Uninstall: `ppnpm uninstall googleapis`
6. Rebuild and restart
7. Clear stale agent-runner copies: `rm -r data/sessions/*/agent-runner-src 2>/dev/null || true`
8. Rebuild: `cd container && ./build.sh && cd .. && npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `systemctl --user restart nanoclaw` (Linux)
8. Rebuild: `cd container && ./build.sh && cd .. && pnpm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `systemctl --user restart nanoclaw` (Linux)
+6 -6
View File
@@ -33,8 +33,8 @@ git remote add whatsapp https://github.com/qwibitai/nanoclaw-whatsapp.git
```bash
git fetch whatsapp skill/image-vision
git merge whatsapp/skill/image-vision || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -52,9 +52,9 @@ If the merge reports conflicts, resolve them by reading the conflicted files and
### Validate code changes
```bash
npm install
npm run build
npx vitest run src/image.test.ts
pnpm install
pnpm run build
pnpm exec vitest run src/image.test.ts
```
All tests must pass and build must be clean before proceeding.
@@ -90,5 +90,5 @@ All tests must pass and build must be clean before proceeding.
## Troubleshooting
- **"Image - download failed"**: Check WhatsApp connection stability. The download may timeout on slow connections.
- **"Image - processing failed"**: Sharp may not be installed correctly. Run `npm ls sharp` to verify.
- **"Image - processing failed"**: Sharp may not be installed correctly. Run `pnpm ls sharp` to verify.
- **Agent doesn't mention image content**: Check container logs for "Loaded image" messages. If missing, ensure agent-runner source was synced to group caches.
+1 -1
View File
@@ -2,5 +2,5 @@
1. Comment out `import './imessage.js'` in `src/channels/index.ts`
2. Remove iMessage env vars (`IMESSAGE_ENABLED`, `IMESSAGE_LOCAL`, `IMESSAGE_SERVER_URL`, `IMESSAGE_API_KEY`) from `.env`
3. `npm uninstall chat-adapter-imessage`
3. `ppnpm uninstall chat-adapter-imessage`
4. Rebuild and restart
+2 -2
View File
@@ -14,7 +14,7 @@ Check if `src/channels/imessage.ts` exists and the import is uncommented in `src
## Install
```bash
npm install chat-adapter-imessage
pnpm install chat-adapter-imessage
```
Uncomment the iMessage import in `src/channels/index.ts`:
@@ -24,7 +24,7 @@ import './imessage.js';
```
```bash
npm run build
pnpm run build
```
## Credentials
@@ -19,7 +19,7 @@ AskUserQuestion: "Which group should have the wiki?"
2. **Dedicated group** — create a new group just for the wiki
3. **Other** — pick an existing group
If dedicated: ask which channel and chat, then register with `npx tsx setup/index.ts --step register`.
If dedicated: ask which channel and chat, then register with `pnpm exec tsx setup/index.ts --step register`.
## Step 3: Design collaboratively
@@ -74,7 +74,7 @@ AskUserQuestion: "Want periodic wiki health checks?"
If yes, create a NanoClaw scheduled task that runs in the wiki group. This is NOT a Claude Code cron job — it's a NanoClaw group task that runs in the agent container. Insert it into the SQLite database:
```bash
npx tsx -e "
pnpm exec tsx -e "
const Database = require('better-sqlite3');
const { CronExpressionParser } = require('cron-parser');
const db = new Database('store/messages.db');
@@ -101,7 +101,7 @@ Use the group's `folder` and `chat_jid` from the registered groups table. Cron e
## Step 6: Build and restart
```bash
npm run build
pnpm run build
./container/build.sh
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
+1 -1
View File
@@ -2,5 +2,5 @@
1. Comment out `import './linear.js'` in `src/channels/index.ts`
2. Remove `LINEAR_API_KEY` and `LINEAR_WEBHOOK_SECRET` from `.env`
3. `npm uninstall @chat-adapter/linear`
3. `ppnpm uninstall @chat-adapter/linear`
4. Rebuild and restart
+2 -2
View File
@@ -14,7 +14,7 @@ Check if `src/channels/linear.ts` exists and the import is uncommented in `src/c
## Install
```bash
npm install @chat-adapter/linear
pnpm install @chat-adapter/linear
```
Uncomment the Linear import in `src/channels/index.ts`:
@@ -24,7 +24,7 @@ import './linear.js';
```
```bash
npm run build
pnpm run build
```
## Credentials
+1 -1
View File
@@ -2,5 +2,5 @@
1. Comment out `import './matrix.js'` in `src/channels/index.ts`
2. Remove `MATRIX_BASE_URL`, `MATRIX_ACCESS_TOKEN`, `MATRIX_USER_ID`, `MATRIX_BOT_USERNAME` from `.env`
3. `npm uninstall @beeper/chat-adapter-matrix`
3. `ppnpm uninstall @beeper/chat-adapter-matrix`
4. Rebuild and restart
+2 -2
View File
@@ -14,7 +14,7 @@ Check if `src/channels/matrix.ts` exists and the import is uncommented in `src/c
## Install
```bash
npm install @beeper/chat-adapter-matrix
pnpm install @beeper/chat-adapter-matrix
```
Uncomment the Matrix import in `src/channels/index.ts`:
@@ -24,7 +24,7 @@ import './matrix.js';
```
```bash
npm run build
pnpm run build
```
## Credentials
+1 -1
View File
@@ -87,7 +87,7 @@ done
### Validate code changes
```bash
npm run build
pnpm run build
./container/build.sh
```
+2 -2
View File
@@ -232,7 +232,7 @@ echo '{}' | docker run -i --entrypoint /bin/echo nanoclaw-agent:latest "Containe
Rebuild the main app and restart:
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
```
@@ -286,5 +286,5 @@ To remove Parallel AI integration:
1. Remove from .env: `sed -i.bak '/PARALLEL_API_KEY/d' .env`
2. Revert changes to container-runner.ts and agent-runner/src/index.ts
3. Remove Web Research Tools section from groups/main/CLAUDE.md
4. Rebuild: `./container/build.sh && npm run build`
4. Rebuild: `./container/build.sh && pnpm run build`
5. Restart: `launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `systemctl --user restart nanoclaw` (Linux)
+4 -4
View File
@@ -31,8 +31,8 @@ git remote add whatsapp https://github.com/qwibitai/nanoclaw-whatsapp.git
```bash
git fetch whatsapp skill/pdf-reader
git merge whatsapp/skill/pdf-reader || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -49,8 +49,8 @@ If the merge reports conflicts, resolve them by reading the conflicted files and
### Validate
```bash
npm run build
npx vitest run src/channels/whatsapp.test.ts
pnpm run build
pnpm exec vitest run src/channels/whatsapp.test.ts
```
### Rebuild container
+6 -6
View File
@@ -38,8 +38,8 @@ git remote add whatsapp https://github.com/qwibitai/nanoclaw-whatsapp.git
```bash
git fetch whatsapp skill/reactions
git merge whatsapp/skill/reactions || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -54,14 +54,14 @@ This adds:
### Run database migration
```bash
npx tsx scripts/migrate-reactions.ts
pnpm exec tsx scripts/migrate-reactions.ts
```
### Validate code changes
```bash
npm test
npm run build
pnpm test
pnpm run build
```
All tests must pass and build must be clean before proceeding.
@@ -71,7 +71,7 @@ All tests must pass and build must be clean before proceeding.
### Build and restart
```bash
npm run build
pnpm run build
```
Linux:
+1 -1
View File
@@ -2,5 +2,5 @@
1. Comment out `import './resend.js'` in `src/channels/index.ts`
2. Remove `RESEND_API_KEY`, `RESEND_FROM_ADDRESS`, `RESEND_FROM_NAME`, `RESEND_WEBHOOK_SECRET` from `.env`
3. `npm uninstall @resend/chat-sdk-adapter`
3. `ppnpm uninstall @resend/chat-sdk-adapter`
4. Rebuild and restart
+2 -2
View File
@@ -14,7 +14,7 @@ Check if `src/channels/resend.ts` exists and the import is uncommented in `src/c
## Install
```bash
npm install @resend/chat-sdk-adapter
pnpm install @resend/chat-sdk-adapter
```
Uncomment the Resend import in `src/channels/index.ts`:
@@ -26,7 +26,7 @@ import './resend.js';
Build:
```bash
npm run build
pnpm run build
```
## Credentials
+1 -1
View File
@@ -2,5 +2,5 @@
1. Comment out `import './slack.js'` in `src/channels/index.ts`
2. Remove `SLACK_BOT_TOKEN` and `SLACK_SIGNING_SECRET` from `.env`
3. `npm uninstall @chat-adapter/slack`
3. `ppnpm uninstall @chat-adapter/slack`
4. Rebuild and restart
+2 -2
View File
@@ -16,7 +16,7 @@ Check if `src/channels/slack.ts` exists and the import is uncommented in `src/ch
### Install the adapter package
```bash
npm install @chat-adapter/slack
pnpm install @chat-adapter/slack
```
### Enable the channel
@@ -30,7 +30,7 @@ import './slack.js';
### Build
```bash
npm run build
pnpm run build
```
## Credentials
+9 -9
View File
@@ -36,8 +36,8 @@ git remote add slack https://github.com/qwibitai/nanoclaw-slack.git
```bash
git fetch slack main
git merge slack/main || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -54,9 +54,9 @@ If the merge reports conflicts, resolve them by reading the conflicted files and
### Validate code changes
```bash
npm install
npm run build
npx vitest run src/channels/slack.test.ts
pnpm install
pnpm run build
pnpm exec vitest run src/channels/slack.test.ts
```
All tests must pass (including the new Slack tests) and build must be clean before proceeding.
@@ -98,7 +98,7 @@ The container reads environment from `data/env/env`, not `.env` directly.
### Build and restart
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw
```
@@ -118,18 +118,18 @@ Wait for the user to provide the channel ID.
### Register the channel
The channel ID, name, and folder name are needed. Use `npx tsx setup/index.ts --step register` with the appropriate flags.
The channel ID, name, and folder name are needed. Use `pnpm exec tsx setup/index.ts --step register` with the appropriate flags.
For a main channel (responds to all messages):
```bash
npx tsx setup/index.ts --step register -- --jid "slack:<channel-id>" --name "<channel-name>" --folder "slack_main" --trigger "@${ASSISTANT_NAME}" --channel slack --no-trigger-required --is-main
pnpm exec tsx setup/index.ts --step register -- --jid "slack:<channel-id>" --name "<channel-name>" --folder "slack_main" --trigger "@${ASSISTANT_NAME}" --channel slack --no-trigger-required --is-main
```
For additional channels (trigger-only):
```bash
npx tsx setup/index.ts --step register -- --jid "slack:<channel-id>" --name "<channel-name>" --folder "slack_<channel-name>" --trigger "@${ASSISTANT_NAME}" --channel slack
pnpm exec tsx setup/index.ts --step register -- --jid "slack:<channel-id>" --name "<channel-name>" --folder "slack_<channel-name>" --trigger "@${ASSISTANT_NAME}" --channel slack
```
## Phase 5: Verify
+1 -1
View File
@@ -2,5 +2,5 @@
1. Comment out `import './teams.js'` in `src/channels/index.ts`
2. Remove `TEAMS_APP_ID` and `TEAMS_APP_PASSWORD` from `.env`
3. `npm uninstall @chat-adapter/teams`
3. `ppnpm uninstall @chat-adapter/teams`
4. Rebuild and restart
+2 -2
View File
@@ -14,7 +14,7 @@ Check if `src/channels/teams.ts` exists and the import is uncommented in `src/ch
## Install
```bash
npm install @chat-adapter/teams
pnpm install @chat-adapter/teams
```
Uncomment the Teams import in `src/channels/index.ts`:
@@ -26,7 +26,7 @@ import './teams.js';
Build:
```bash
npm run build
pnpm run build
```
## Credentials
+2 -2
View File
@@ -319,7 +319,7 @@ Also add `TELEGRAM_BOT_POOL` to the launchd plist (`~/Library/LaunchAgents/com.n
### Step 7: Rebuild and Restart
```bash
npm run build
pnpm run build
./container/build.sh # Required — MCP tool changed
# macOS:
launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist
@@ -381,4 +381,4 @@ To remove Agent Swarm support while keeping basic Telegram:
5. Remove `sender` param from MCP tool in `container/agent-runner/src/ipc-mcp-stdio.ts`
6. Remove Agent Teams section from group CLAUDE.md files
7. Remove `TELEGRAM_BOT_POOL` from `.env`, `data/env/env`, and launchd plist/systemd unit
8. Rebuild: `npm run build && ./container/build.sh && launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist && launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist` (macOS) or `npm run build && ./container/build.sh && systemctl --user restart nanoclaw` (Linux)
8. Rebuild: `pnpm run build && ./container/build.sh && launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist && launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist` (macOS) or `pnpm run build && ./container/build.sh && systemctl --user restart nanoclaw` (Linux)
+1 -1
View File
@@ -2,5 +2,5 @@
1. Comment out `import './telegram.js'` in `src/channels/index.ts`
2. Remove `TELEGRAM_BOT_TOKEN` from `.env`
3. `npm uninstall @chat-adapter/telegram`
3. `ppnpm uninstall @chat-adapter/telegram`
4. Rebuild and restart
+3 -3
View File
@@ -16,7 +16,7 @@ Check if `src/channels/telegram.ts` exists and the import is uncommented in `src
### Install the adapter package
```bash
npm install @chat-adapter/telegram
pnpm install @chat-adapter/telegram
```
### Enable the channel
@@ -30,7 +30,7 @@ import './telegram.js';
### Build
```bash
npm run build
pnpm run build
```
## Credentials
@@ -68,7 +68,7 @@ Otherwise, run `/manage-channels` to wire this channel to an agent group.
- **type**: `telegram`
- **terminology**: Telegram calls them "groups" and "chats." A "group" has multiple members; a "chat" is a 1:1 conversation with the bot.
- **how-to-find-id**: Do NOT ask the user for a chat ID. Telegram registration uses pairing — run `npx tsx setup/index.ts --step pair-telegram -- --intent <main|wire-to:folder|new-agent:folder>`, show the user the 4-digit `CODE` from the `PAIR_TELEGRAM_ISSUED` block (follow the `REMINDER_TO_ASSISTANT` line in that block), and tell them to send just the 4 digits as a message from the chat they want to register (DM the bot for `main`, post in the group otherwise). In groups with Group Privacy ON, prefix with the bot handle: `@<botname> CODE`. Wrong guesses invalidate the code — if a `PAIR_TELEGRAM_ATTEMPT` block arrives with a mismatched `RECEIVED_CODE`, a `PAIR_TELEGRAM_NEW_CODE` block will follow automatically (up to 5 regenerations); show the new code. On `PAIR_TELEGRAM STATUS=failed ERROR=max-regenerations-exceeded`, ask the user if they want to try again and re-invoke the step — each invocation starts a fresh 5-attempt batch. Success emits `PAIR_TELEGRAM STATUS=success` with `PLATFORM_ID`, `IS_GROUP`, and `ADMIN_USER_ID`. The service must be running for this to work (the polling adapter is what observes the code).
- **how-to-find-id**: Do NOT ask the user for a chat ID. Telegram registration uses pairing — run `pnpm exec tsx setup/index.ts --step pair-telegram -- --intent <main|wire-to:folder|new-agent:folder>`, show the user the 4-digit `CODE` from the `PAIR_TELEGRAM_ISSUED` block (follow the `REMINDER_TO_ASSISTANT` line in that block), and tell them to send just the 4 digits as a message from the chat they want to register (DM the bot for `main`, post in the group otherwise). In groups with Group Privacy ON, prefix with the bot handle: `@<botname> CODE`. Wrong guesses invalidate the code — if a `PAIR_TELEGRAM_ATTEMPT` block arrives with a mismatched `RECEIVED_CODE`, a `PAIR_TELEGRAM_NEW_CODE` block will follow automatically (up to 5 regenerations); show the new code. On `PAIR_TELEGRAM STATUS=failed ERROR=max-regenerations-exceeded`, ask the user if they want to try again and re-invoke the step — each invocation starts a fresh 5-attempt batch. Success emits `PAIR_TELEGRAM STATUS=success` with `PLATFORM_ID`, `IS_GROUP`, and `ADMIN_USER_ID`. The service must be running for this to work (the polling adapter is what observes the code).
- **supports-threads**: no
- **typical-use**: Interactive chat — direct messages or small groups
- **default-isolation**: Same agent group if you're the only participant across multiple chats. Separate agent group if different people are in different groups.
+14 -14
View File
@@ -40,8 +40,8 @@ git remote add telegram https://github.com/qwibitai/nanoclaw-telegram.git
```bash
git fetch telegram main
git merge telegram/main || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -58,9 +58,9 @@ If the merge reports conflicts, resolve them by reading the conflicted files and
### Validate code changes
```bash
npm install
npm run build
npx vitest run src/channels/telegram.test.ts
pnpm install
pnpm run build
pnpm exec vitest run src/channels/telegram.test.ts
```
All tests must pass (including the new Telegram tests) and build must be clean before proceeding.
@@ -114,7 +114,7 @@ Tell the user:
### Build and restart
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
```
@@ -133,18 +133,18 @@ Wait for the user to provide the chat ID (format: `tg:123456789` or `tg:-1001234
### Register the chat
The chat ID, name, and folder name are needed. Use `npx tsx setup/index.ts --step register` with the appropriate flags.
The chat ID, name, and folder name are needed. Use `pnpm exec tsx setup/index.ts --step register` with the appropriate flags.
For a main chat (responds to all messages):
```bash
npx tsx setup/index.ts --step register -- --jid "tg:<chat-id>" --name "<chat-name>" --folder "telegram_main" --trigger "@${ASSISTANT_NAME}" --channel telegram --no-trigger-required --is-main
pnpm exec tsx setup/index.ts --step register -- --jid "tg:<chat-id>" --name "<chat-name>" --folder "telegram_main" --trigger "@${ASSISTANT_NAME}" --channel telegram --no-trigger-required --is-main
```
For additional chats (trigger-only):
```bash
npx tsx setup/index.ts --step register -- --jid "tg:<chat-id>" --name "<chat-name>" --folder "telegram_<group-name>" --trigger "@${ASSISTANT_NAME}" --channel telegram
pnpm exec tsx setup/index.ts --step register -- --jid "tg:<chat-id>" --name "<chat-name>" --folder "telegram_<group-name>" --trigger "@${ASSISTANT_NAME}" --channel telegram
```
## Phase 5: Verify
@@ -189,16 +189,16 @@ If `/chatid` doesn't work:
## After Setup
If running `npm run dev` while the service is active:
If running `pnpm run dev` while the service is active:
```bash
# macOS:
launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist
npm run dev
pnpm run dev
# When done testing:
launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist
# Linux:
# systemctl --user stop nanoclaw
# npm run dev
# pnpm run dev
# systemctl --user start nanoclaw
```
@@ -210,5 +210,5 @@ To remove Telegram integration:
2. Remove `import './telegram.js'` from `src/channels/index.ts`
3. Remove `TELEGRAM_BOT_TOKEN` from `.env`
4. Remove Telegram registrations from SQLite: `sqlite3 store/messages.db "DELETE FROM registered_groups WHERE jid LIKE 'tg:%'"`
5. Uninstall: `npm uninstall grammy`
6. Rebuild: `npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `npm run build && systemctl --user restart nanoclaw` (Linux)
5. Uninstall: `ppnpm uninstall grammy`
6. Rebuild: `pnpm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `pnpm run build && systemctl --user restart nanoclaw` (Linux)
@@ -42,8 +42,8 @@ git remote add whatsapp https://github.com/qwibitai/nanoclaw-whatsapp.git
```bash
git fetch whatsapp skill/voice-transcription
git merge whatsapp/skill/voice-transcription || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -60,9 +60,9 @@ If the merge reports conflicts, resolve them by reading the conflicted files and
### Validate code changes
```bash
npm install --legacy-peer-deps
npm run build
npx vitest run src/channels/whatsapp.test.ts
pnpm install
pnpm run build
pnpm exec vitest run src/channels/whatsapp.test.ts
```
All tests must pass and build must be clean before proceeding.
@@ -103,7 +103,7 @@ The container reads environment from `data/env/env`, not `.env` directly.
### Build and restart
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
```
+1 -1
View File
@@ -2,5 +2,5 @@
1. Comment out `import './webex.js'` in `src/channels/index.ts`
2. Remove `WEBEX_BOT_TOKEN` and `WEBEX_WEBHOOK_SECRET` from `.env`
3. `npm uninstall @bitbasti/chat-adapter-webex`
3. `ppnpm uninstall @bitbasti/chat-adapter-webex`
4. Rebuild and restart
+2 -2
View File
@@ -14,7 +14,7 @@ Check if `src/channels/webex.ts` exists and the import is uncommented in `src/ch
## Install
```bash
npm install @bitbasti/chat-adapter-webex
pnpm install @bitbasti/chat-adapter-webex
```
Uncomment the Webex import in `src/channels/index.ts`:
@@ -24,7 +24,7 @@ import './webex.js';
```
```bash
npm run build
pnpm run build
```
## Credentials
@@ -2,5 +2,5 @@
1. Comment out `import './whatsapp-cloud.js'` in `src/channels/index.ts`
2. Remove `WHATSAPP_ACCESS_TOKEN`, `WHATSAPP_PHONE_NUMBER_ID`, `WHATSAPP_APP_SECRET`, `WHATSAPP_VERIFY_TOKEN` from `.env`
3. `npm uninstall @chat-adapter/whatsapp`
3. `ppnpm uninstall @chat-adapter/whatsapp`
4. Rebuild and restart
@@ -14,7 +14,7 @@ Check if `src/channels/whatsapp-cloud.ts` exists and the import is uncommented i
## Install
```bash
npm install @chat-adapter/whatsapp
pnpm install @chat-adapter/whatsapp
```
Uncomment the WhatsApp Cloud API import in `src/channels/index.ts`:
@@ -26,7 +26,7 @@ import './whatsapp-cloud.js';
Build:
```bash
npm run build
pnpm run build
```
## Credentials
+22 -22
View File
@@ -63,8 +63,8 @@ git remote add whatsapp https://github.com/qwibitai/nanoclaw-whatsapp.git
```bash
git fetch whatsapp main
git merge whatsapp/main || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -84,9 +84,9 @@ If the merge reports conflicts, resolve them by reading the conflicted files and
### Validate code changes
```bash
npm install
npm run build
npx vitest run src/channels/whatsapp.test.ts
pnpm install
pnpm run build
pnpm exec vitest run src/channels/whatsapp.test.ts
```
All tests must pass and build must be clean before proceeding.
@@ -104,7 +104,7 @@ rm -rf store/auth/
For QR code in browser (recommended):
```bash
npx tsx setup/index.ts --step whatsapp-auth -- --method qr-browser
pnpm exec tsx setup/index.ts --step whatsapp-auth -- --method qr-browser
```
(Bash timeout: 150000ms)
@@ -120,10 +120,10 @@ Tell the user:
For QR code in terminal:
```bash
npx tsx setup/index.ts --step whatsapp-auth -- --method qr-terminal
pnpm exec tsx setup/index.ts --step whatsapp-auth -- --method qr-terminal
```
Tell the user to run `npm run auth` in another terminal, then:
Tell the user to run `pnpm run auth` in another terminal, then:
> 1. Open WhatsApp > **Settings** > **Linked Devices** > **Link a Device**
> 2. Scan the QR code displayed in the terminal
@@ -135,7 +135,7 @@ Tell the user to have WhatsApp open on **Settings > Linked Devices > Link a Devi
Run the auth process in the background and poll `store/pairing-code.txt` for the code:
```bash
rm -f store/pairing-code.txt && npx tsx setup/index.ts --step whatsapp-auth -- --method pairing-code --phone <their-phone-number> > /tmp/wa-auth.log 2>&1 &
rm -f store/pairing-code.txt && pnpm exec tsx setup/index.ts --step whatsapp-auth -- --method pairing-code --phone <their-phone-number> > /tmp/wa-auth.log 2>&1 &
```
Then immediately poll for the code (do NOT wait for the background command to finish):
@@ -221,8 +221,8 @@ node -e "const c=JSON.parse(require('fs').readFileSync('store/auth/creds.json','
**Group (solo, existing):** Run group sync and list available groups:
```bash
npx tsx setup/index.ts --step groups
npx tsx setup/index.ts --step groups --list
pnpm exec tsx setup/index.ts --step groups
pnpm exec tsx setup/index.ts --step groups --list
```
The output shows `JID|GroupName` pairs. Present candidates as AskUserQuestion (names only, not JIDs).
@@ -230,7 +230,7 @@ The output shows `JID|GroupName` pairs. Present candidates as AskUserQuestion (n
### Register the chat
```bash
npx tsx setup/index.ts --step register \
pnpm exec tsx setup/index.ts --step register \
--jid "<jid>" \
--name "<chat-name>" \
--trigger "@<trigger>" \
@@ -244,7 +244,7 @@ npx tsx setup/index.ts --step register \
For additional groups (trigger-required):
```bash
npx tsx setup/index.ts --step register \
pnpm exec tsx setup/index.ts --step register \
--jid "<group-jid>" \
--name "<group-name>" \
--trigger "@<trigger>" \
@@ -257,7 +257,7 @@ npx tsx setup/index.ts --step register \
### Build and restart
```bash
npm run build
pnpm run build
```
Restart the service:
@@ -296,7 +296,7 @@ tail -f logs/nanoclaw.log
QR codes expire after ~60 seconds. Re-run the auth command:
```bash
rm -rf store/auth/ && npx tsx src/whatsapp-auth.ts
rm -rf store/auth/ && pnpm exec tsx src/whatsapp-auth.ts
```
### Pairing code not working
@@ -304,7 +304,7 @@ rm -rf store/auth/ && npx tsx src/whatsapp-auth.ts
Codes expire in ~60 seconds. To retry:
```bash
rm -rf store/auth/ && npx tsx src/whatsapp-auth.ts --pairing-code --phone <phone>
rm -rf store/auth/ && pnpm exec tsx src/whatsapp-auth.ts --pairing-code --phone <phone>
```
Enter the code **immediately** when it appears. Also ensure:
@@ -315,7 +315,7 @@ Enter the code **immediately** when it appears. Also ensure:
If pairing code keeps failing, switch to QR-browser auth instead:
```bash
rm -rf store/auth/ && npx tsx setup/index.ts --step whatsapp-auth -- --method qr-browser
rm -rf store/auth/ && pnpm exec tsx setup/index.ts --step whatsapp-auth -- --method qr-browser
```
### "conflict" disconnection
@@ -340,25 +340,25 @@ Check:
Run group metadata sync:
```bash
npx tsx setup/index.ts --step groups
pnpm exec tsx setup/index.ts --step groups
```
This fetches all group names from WhatsApp. Runs automatically every 24 hours.
## After Setup
If running `npm run dev` while the service is active:
If running `pnpm run dev` while the service is active:
```bash
# macOS:
launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist
npm run dev
pnpm run dev
# When done testing:
launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist
# Linux:
# systemctl --user stop nanoclaw
# npm run dev
# pnpm run dev
# systemctl --user start nanoclaw
```
@@ -369,4 +369,4 @@ To remove WhatsApp integration:
1. Delete auth credentials: `rm -rf store/auth/`
2. Remove WhatsApp registrations: `sqlite3 store/messages.db "DELETE FROM registered_groups WHERE jid LIKE '%@g.us' OR jid LIKE '%@s.whatsapp.net'"`
3. Sync env: `mkdir -p data/env && cp .env data/env/env`
4. Rebuild and restart: `npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `npm run build && systemctl --user restart nanoclaw` (Linux)
4. Rebuild and restart: `pnpm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `pnpm run build && systemctl --user restart nanoclaw` (Linux)
+8 -8
View File
@@ -51,12 +51,12 @@ git fetch upstream skill/channel-formatting
git merge upstream/skill/channel-formatting
```
If there are merge conflicts on `package-lock.json`, resolve them by accepting the incoming
If there are merge conflicts on `pnpm-lock.yaml`, resolve them by accepting the incoming
version and continuing:
```bash
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
```
@@ -74,9 +74,9 @@ This merge adds:
### Validate
```bash
npm install
npm run build
npx vitest run src/formatting.test.ts
pnpm install
pnpm run build
pnpm exec vitest run src/formatting.test.ts
```
All 73 tests should pass and the build should be clean before continuing.
@@ -86,7 +86,7 @@ All 73 tests should pass and the build should be clean before continuing.
### Rebuild and restart
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
```
@@ -133,5 +133,5 @@ git checkout upstream/main -- src/router.ts
# Revert the index.ts sendMessage call sites to plain formatOutbound(rawText)
# (edit manually or: git checkout upstream/main -- src/index.ts)
npm run build
pnpm run build
```
@@ -80,8 +80,8 @@ If the merge reports conflicts, resolve them by reading the conflicted files and
### Validate code changes
```bash
npm test
npm run build
pnpm test
pnpm run build
```
All tests must pass and build must be clean before proceeding.
@@ -172,7 +172,7 @@ Expected: Both operations succeed.
### Full integration test
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw
```
+1 -1
View File
@@ -91,7 +91,7 @@ Implementation:
Always tell the user:
```bash
# Rebuild and restart
npm run build
pnpm run build
# macOS:
launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist
launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist
+2 -2
View File
@@ -41,7 +41,7 @@ Set `LOG_LEVEL=debug` for verbose output:
```bash
# For development
LOG_LEVEL=debug npm run dev
LOG_LEVEL=debug pnpm run dev
# For launchd service (macOS), add to plist EnvironmentVariables:
<key>LOG_LEVEL</key>
@@ -231,7 +231,7 @@ query({
```bash
# Rebuild main app
npm run build
pnpm run build
# Rebuild container (use --no-cache for clean rebuild)
./container/build.sh
+2 -2
View File
@@ -231,10 +231,10 @@ Ask them to let you know when done.
## Phase 4: Build and restart
```bash
npm run build
pnpm run build
```
If build fails, diagnose and fix. Common issue: `@onecli-sh/sdk` not installed — run `npm install` first.
If build fails, diagnose and fix. Common issue: `@onecli-sh/sdk` not installed — run `pnpm install` first.
Restart the service:
- macOS (launchd): `launchctl kickstart -k gui/$(id -u)/com.nanoclaw`
+3 -3
View File
@@ -43,7 +43,7 @@ Use the channel's `typical-use` and `default-isolation` fields to pick the recom
### Register Command
```bash
npx tsx setup/index.ts --step register -- \
pnpm exec tsx setup/index.ts --step register -- \
--platform-id "<id>" --name "<name>" \
--folder "<folder>" --channel "<type>" \
--session-mode "<shared|agent-shared|per-thread>" \
@@ -58,10 +58,10 @@ For separate agents, also ask for a folder name and optionally a different assis
When adding another group/chat on an already-configured platform (e.g. a second Telegram group):
1. **Telegram:** ask the isolation question first to determine intent (`wire-to:<folder>` for an existing agent, `new-agent:<folder>` for a fresh one). Run `npx tsx setup/index.ts --step pair-telegram -- --intent <intent>`, show the CODE (follow the `REMINDER_TO_ASSISTANT` line in the `PAIR_TELEGRAM_ISSUED` block) and tell the user to post `@<botname> CODE` in the target group (or DM the bot for a private chat). Wait for the `PAIR_TELEGRAM` block. The inbound interceptor has already created the `messaging_groups` row with `unknown_sender_policy = 'strict'` and upserted the paired user — `register` only needs to add the wiring:
1. **Telegram:** ask the isolation question first to determine intent (`wire-to:<folder>` for an existing agent, `new-agent:<folder>` for a fresh one). Run `pnpm exec tsx setup/index.ts --step pair-telegram -- --intent <intent>`, show the CODE (follow the `REMINDER_TO_ASSISTANT` line in the `PAIR_TELEGRAM_ISSUED` block) and tell the user to post `@<botname> CODE` in the target group (or DM the bot for a private chat). Wait for the `PAIR_TELEGRAM` block. The inbound interceptor has already created the `messaging_groups` row with `unknown_sender_policy = 'strict'` and upserted the paired user — `register` only needs to add the wiring:
```bash
npx tsx setup/index.ts --step register -- \
pnpm exec tsx setup/index.ts --step register -- \
--platform-id "<PLATFORM_ID>" --name "<group-name>" \
--folder "<folder>" --channel "telegram" \
--session-mode "<shared|agent-shared|per-thread>" \
@@ -68,7 +68,7 @@ Source: `src/db.ts`
Insert directly into the SQLite database. This requires groups to be registered first (Phase 1). Use the registered group's `folder` and `chat_jid`:
```bash
npx tsx -e "
pnpm exec tsx -e "
const Database = require('better-sqlite3');
const { CronExpressionParser } = require('cron-parser');
const db = new Database('store/messages.db');
@@ -36,7 +36,7 @@ Keep it factual and terse — this is for machine recovery after compaction, not
Run the discovery script to find and summarize the OpenClaw installation:
```bash
npx tsx ${CLAUDE_SKILL_DIR}/scripts/discover-openclaw.ts
pnpm exec tsx ${CLAUDE_SKILL_DIR}/scripts/discover-openclaw.ts
```
If the user specifies a custom path, pass it: `--state-dir <path>`
@@ -106,7 +106,7 @@ The discovery script provides detected groups in the GROUPS field (format: `chan
For each group the user wants to bring over, pre-register it:
```bash
npx tsx setup/index.ts --step register -- --jid "<nanoclaw_jid>" --name "<group_name>" --folder "<channel>_<slug>" --trigger "@<confirmed_name>" --channel <channel> --assistant-name "<confirmed_name>"
pnpm exec tsx setup/index.ts --step register -- --jid "<nanoclaw_jid>" --name "<group_name>" --folder "<channel>_<slug>" --trigger "@<confirmed_name>" --channel <channel> --assistant-name "<confirmed_name>"
```
Only pass `--assistant-name` on the first registration (it updates all CLAUDE.md templates globally).
@@ -115,7 +115,7 @@ Folder naming: `<channel>_<name-slug>` (e.g. `whatsapp_family-chat`, `telegram_d
For the first/primary group, add `--is-main --no-trigger-required`. Other groups default to requiring a trigger prefix.
**Important:** Registration requires the database to exist. If the environment step hasn't been run yet, run it first: `npx tsx setup/index.ts --step environment`. Registration also creates the group folder under `groups/` and copies the CLAUDE.md template.
**Important:** Registration requires the database to exist. If the environment step hasn't been run yet, run it first: `pnpm exec tsx setup/index.ts --step environment`. Registration also creates the group folder under `groups/` and copies the CLAUDE.md template.
Register groups from all channels — including channels NanoClaw doesn't yet support (signal, matrix, etc.). The registration stores the JID and metadata in the database, ready for when that channel is added later. Groups won't receive messages until their channel code is installed, but the registration, group folder, and CLAUDE.md will be ready.
@@ -295,7 +295,7 @@ For each detected plugin, present the name to the user and discuss whether to se
1. **If NanoClaw has a matching skill** — check the available NanoClaw skills list for an equivalent (e.g. `/add-voice-transcription` for whisper). If found, save the API key to `.env` and invoke that skill.
2. **If the OpenClaw plugin was an MCP server** — read its config to find the exact package name and command. Install the same MCP server (e.g. `npx -y <exact-package-from-config>`). Don't search for or guess at MCP packages — only install what was explicitly configured.
2. **If the OpenClaw plugin was an MCP server** — read its config to find the exact package name and command. Install the same MCP server (e.g. `pnpm dlx <exact-package-from-config>`). Don't search for or guess at MCP packages — only install what was explicitly configured.
3. **If the OpenClaw plugin was a CLI tool** — read the config to identify the exact tool. If it's an npm package, add it to the container's Dockerfile. Add a note to the group's CLAUDE.md that the tool is available and how to invoke it.
@@ -324,7 +324,7 @@ Run the credential extraction script with `--write-env .env` so it writes creden
First, run without `--write-env` to preview:
```bash
npx tsx ${CLAUDE_SKILL_DIR}/scripts/extract-channel-credentials.ts --state-dir <STATE_DIR> --channel <name>
pnpm exec tsx ${CLAUDE_SKILL_DIR}/scripts/extract-channel-credentials.ts --state-dir <STATE_DIR> --channel <name>
```
Parse the status block. Key fields: HAS_CREDENTIAL, CREDENTIAL_MASKED, NANOCLAW_ENV_VAR.
@@ -339,7 +339,7 @@ If HAS_CREDENTIAL=true: Show the masked credential (`CREDENTIAL_MASKED`). AskUse
If using the credential:
```bash
npx tsx ${CLAUDE_SKILL_DIR}/scripts/extract-channel-credentials.ts --state-dir <STATE_DIR> --channel <name> --write-env .env
pnpm exec tsx ${CLAUDE_SKILL_DIR}/scripts/extract-channel-credentials.ts --state-dir <STATE_DIR> --channel <name> --write-env .env
```
The script writes the credential directly to `.env` using the correct NanoClaw variable name (e.g. `TELEGRAM_BOT_TOKEN`). Check the status block for `WRITTEN_TO` and `WRITTEN_COUNT` to confirm.
@@ -1,7 +1,7 @@
/**
* Discover an existing OpenClaw installation and emit a structured summary.
*
* Usage: npx tsx .claude/skills/migrate-from-openclaw/scripts/discover-openclaw.ts [--state-dir <path>]
* Usage: pnpm exec tsx .claude/skills/migrate-from-openclaw/scripts/discover-openclaw.ts [--state-dir <path>]
*
* Checks (in order): --state-dir arg, $OPENCLAW_STATE_DIR, ~/.openclaw, ~/.clawdbot
* Parses openclaw.json (JSON5-tolerant), scans workspace for identity/memory files,
@@ -2,7 +2,7 @@
* Extract a channel credential from an OpenClaw configuration and write it
* directly to the NanoClaw .env file.
*
* Usage: npx tsx .claude/skills/migrate-from-openclaw/scripts/extract-channel-credentials.ts \
* Usage: pnpm exec tsx .claude/skills/migrate-from-openclaw/scripts/extract-channel-credentials.ts \
* --channel telegram --state-dir ~/.openclaw --write-env .env
*
* Handles OpenClaw SecretRef formats:
+3 -3
View File
@@ -391,7 +391,7 @@ For behavior customizations (CLAUDE.md files): copy from the main tree. These ar
## 2.6 Validate in worktree
```bash
cd "$WORKTREE" && npm install && npm run build && npm test
cd "$WORKTREE" && pnpm install && pnpm run build && pnpm test
```
If build fails, show the error. Fix only issues caused by the migration. If unclear, ask the user.
@@ -417,7 +417,7 @@ If testing live:
ln -s "$PROJECT_ROOT/.env" "$WORKTREE/.env"
```
3. Start from worktree: `cd "$WORKTREE" && npm run dev`
3. Start from worktree: `cd "$WORKTREE" && pnpm run dev`
4. Ask the user to send a test message from their phone. Wait for them to confirm it works.
@@ -461,7 +461,7 @@ Do NOT use `git checkout -B` to create an intermediate branch — this caused is
## 2.9 Post-upgrade
Run `npm install && npm run build` in the main tree to confirm.
Run `npm install && pnpm run build` in the main tree to confirm.
Restart the service:
```bash
+10 -10
View File
@@ -55,7 +55,7 @@ Run `bash setup.sh` and parse the status block.
## 2. Check Environment
Run `npx tsx setup/index.ts --step environment` and parse the status block.
Run `pnpm exec tsx setup/index.ts --step environment` and parse the status block.
- If HAS_AUTH=true → WhatsApp is already configured, note for step 5
- If HAS_REGISTERED_GROUPS=true → note existing config, offer to skip or reconfigure
@@ -73,9 +73,9 @@ If "Migrate now": invoke `/migrate-from-openclaw`, then return here and continue
## 2a. Timezone
Run `npx tsx setup/index.ts --step timezone` and parse the status block.
Run `pnpm exec tsx setup/index.ts --step timezone` and parse the status block.
- If NEEDS_USER_INPUT=true → The system timezone could not be autodetected (e.g. POSIX-style TZ like `IST-2`). AskUserQuestion: "What is your timezone?" with common options (America/New_York, Europe/London, Asia/Jerusalem, Asia/Tokyo) and an "Other" escape. Then re-run: `npx tsx setup/index.ts --step timezone -- --tz <their-answer>`.
- If NEEDS_USER_INPUT=true → The system timezone could not be autodetected (e.g. POSIX-style TZ like `IST-2`). AskUserQuestion: "What is your timezone?" with common options (America/New_York, Europe/London, Asia/Jerusalem, Asia/Tokyo) and an "Other" escape. Then re-run: `pnpm exec tsx setup/index.ts --step timezone -- --tz <their-answer>`.
- If STATUS=success and RESOLVED_TZ is `UTC` or `Etc/UTC` → confirm with the user: "Your system timezone is UTC — is that correct, or are you on a remote server?" If wrong, ask for their actual timezone and re-run with `--tz`.
- If STATUS=success → Timezone is configured. Note RESOLVED_TZ for reference.
@@ -91,7 +91,7 @@ Run `npx tsx setup/index.ts --step timezone` and parse the status block.
### 3b. Build and test
Run `npx tsx setup/index.ts --step container -- --runtime docker` and parse the status block.
Run `pnpm exec tsx setup/index.ts --step container -- --runtime docker` and parse the status block.
**If BUILD_OK=false:** Read `logs/setup.log` tail for the build error.
- Cache issue (stale layers): `docker builder prune -f`. Retry.
@@ -220,7 +220,7 @@ The skill will:
**After the channel skill completes**, install dependencies and rebuild — channel merges may introduce new packages:
```bash
npm install && npm run build
pnpm install && pnpm run build
```
If the build fails, read the error output and fix it (usually a missing dependency). Then continue to step 5a.
@@ -230,7 +230,7 @@ If the build fails, read the error output and fix it (usually a missing dependen
Set empty mount allowlist (agents only access their own workspace). Users can configure mounts later with `/manage-mounts`.
```bash
npx tsx setup/index.ts --step mounts -- --empty
pnpm exec tsx setup/index.ts --step mounts -- --empty
```
## 7. Start Service
@@ -239,7 +239,7 @@ If service already running: unload first.
- macOS: `launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist`
- Linux: `systemctl --user stop nanoclaw` (or `systemctl stop nanoclaw` if root)
Run `npx tsx setup/index.ts --step service` and parse the status block.
Run `pnpm exec tsx setup/index.ts --step service` and parse the status block.
**If FALLBACK=wsl_no_systemd:** WSL without systemd detected. Tell user they can either enable systemd in WSL (`echo -e "[boot]\nsystemd=true" | sudo tee /etc/wsl.conf` then restart WSL) or use the generated `start-nanoclaw.sh` wrapper.
@@ -287,10 +287,10 @@ If yes: invoke `/add-vercel`.
## 8. Verify
Run `npx tsx setup/index.ts --step verify` and parse the status block.
Run `pnpm exec tsx setup/index.ts --step verify` and parse the status block.
**If STATUS=failed, fix each:**
- SERVICE=stopped → `npm run build`, then restart: `launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `systemctl --user restart nanoclaw` (Linux) or `bash start-nanoclaw.sh` (WSL nohup)
- SERVICE=stopped → `pnpm run build`, then restart: `launchctl kickstart -k gui/$(id -u)/com.nanoclaw` (macOS) or `systemctl --user restart nanoclaw` (Linux) or `bash start-nanoclaw.sh` (WSL nohup)
- SERVICE=not_found → re-run step 7
- CREDENTIALS=missing → re-run step 4 (check `onecli secrets list`)
- CHANNEL_AUTH shows `not_found` for any channel → re-invoke that channel's skill (e.g. `/add-telegram`)
@@ -303,7 +303,7 @@ Tell user to test: send a message in their registered chat. Show: `tail -f logs/
**Container agent fails ("Claude Code process exited with code 1"):** Ensure Docker is running — `open -a Docker` (macOS) or `sudo systemctl start docker` (Linux). Check container logs in `groups/main/logs/container-*.log`.
**No response to messages:** Check trigger pattern. Main channel doesn't need prefix. Check DB: `npx tsx setup/index.ts --step verify`. Check `logs/nanoclaw.log`.
**No response to messages:** Check trigger pattern. Main channel doesn't need prefix. Check DB: `pnpm exec tsx setup/index.ts --step verify`. Check `logs/nanoclaw.log`.
**Channel not connecting:** Verify the channel's credentials are set in `.env`. Channels auto-enable when their credentials are present. For WhatsApp: check `store/auth/creds.json` exists. For token-based channels: check token values in `.env`. Restart the service after any `.env` change.
+5 -5
View File
@@ -30,7 +30,7 @@ Run `/update-nanoclaw` in Claude Code.
**Conflict resolution**: opens only conflicted files, resolves the conflict markers, keeps your local customizations intact.
**Validation**: runs `npm run build` and `npm test`.
**Validation**: runs `pnpm run build` and `pnpm test`.
**Breaking changes check**: after validation, reads CHANGELOG.md for any `[BREAKING]` entries introduced by the update. If found, shows each breaking change and offers to run the recommended skill to migrate.
@@ -109,7 +109,7 @@ Show file-level impact from upstream:
Bucket the upstream changed files:
- **Skills** (`.claude/skills/`): unlikely to conflict unless the user edited an upstream skill
- **Source** (`src/`): may conflict if user modified the same files
- **Build/config** (`package.json`, `package-lock.json`, `tsconfig*.json`, `container/`, `launchd/`): review needed
- **Build/config** (`package.json`, `pnpm-lock.yaml`, `tsconfig*.json`, `container/`, `launchd/`): review needed
- **Other**: docs, tests, misc
**Large drift check:** If the upstream commit count and age suggest the user has a lot of catching up to do, mention that `/migrate-nanoclaw` might be a better fit — it extracts customizations and reapplies them on clean upstream instead of merging. Offer it as an option but don't push.
@@ -175,8 +175,8 @@ If it gets messy (more than 3 rounds of conflicts):
# Step 5: Validation
Run:
- `npm run build`
- `npm test` (do not fail the flow if tests are not configured)
- `pnpm run build`
- `pnpm test` (do not fail the flow if tests are not configured)
If build fails:
- Show the error.
@@ -234,7 +234,7 @@ Tell the user:
- Backup branch also exists: `backup/pre-update-<HASH>-<TIMESTAMP>`
- Restart the service to apply changes:
- If using launchd: `launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist && launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist`
- If running manually: restart `npm run dev`
- If running manually: restart `pnpm run dev`
## Diagnostics
+2 -2
View File
@@ -110,8 +110,8 @@ If a merge fails badly (e.g., cannot resolve conflicts):
# Step 4: Validation
After all selected skills are merged:
- `npm run build`
- `npm test` (do not fail the flow if tests are not configured)
- `pnpm run build`
- `pnpm test` (do not fail the flow if tests are not configured)
If build fails:
- Show the error.
+4 -4
View File
@@ -76,8 +76,8 @@ git remote add whatsapp https://github.com/qwibitai/nanoclaw-whatsapp.git
```bash
git fetch whatsapp skill/local-whisper
git merge whatsapp/skill/local-whisper || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -87,7 +87,7 @@ This modifies `src/transcription.ts` to use the `whisper-cli` binary instead of
### Validate
```bash
npm run build
pnpm run build
```
## Phase 3: Verify
@@ -110,7 +110,7 @@ launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist
### Build and restart
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw
```
@@ -48,8 +48,8 @@ git remote add upstream https://github.com/qwibitai/nanoclaw.git
```bash
git fetch upstream skill/native-credential-proxy
git merge upstream/skill/native-credential-proxy || {
git checkout --theirs package-lock.json
git add package-lock.json
git checkout --theirs pnpm-lock.yaml
git add pnpm-lock.yaml
git merge --continue
}
```
@@ -62,7 +62,7 @@ This merges in:
- Restored platform-aware proxy bind address detection
- Reverted setup skill to `.env`-based credential instructions
If the merge reports conflicts beyond `package-lock.json`, resolve them by reading the conflicted files and understanding the intent of both sides.
If the merge reports conflicts beyond `pnpm-lock.yaml`, resolve them by reading the conflicted files and understanding the intent of both sides.
### Update main group CLAUDE.md
@@ -77,9 +77,9 @@ with:
### Validate code changes
```bash
npm install
npm run build
npx vitest run src/credential-proxy.test.ts src/container-runner.test.ts
pnpm install
pnpm run build
pnpm exec vitest run src/credential-proxy.test.ts src/container-runner.test.ts
```
All tests must pass and build must be clean before proceeding.
@@ -125,7 +125,7 @@ echo 'ANTHROPIC_API_KEY=<key>' >> .env
1. Rebuild and restart:
```bash
npm run build
pnpm run build
```
Then restart the service:
@@ -161,7 +161,7 @@ To revert to OneCLI gateway:
1. Find the merge commit: `git log --oneline --merges -5`
2. Revert it: `git revert <merge-commit> -m 1` (undoes the skill branch merge, keeps your other changes)
3. `npm install` (re-adds `@onecli-sh/sdk`)
4. `npm run build`
3. `pnpm install` (re-adds `@onecli-sh/sdk`)
4. `pnpm run build`
5. Follow `/setup` step 4 to configure OneCLI credentials
6. Remove `ANTHROPIC_API_KEY` / `CLAUDE_CODE_OAUTH_TOKEN` from `.env`
+11 -11
View File
@@ -26,7 +26,7 @@ Before using this skill, ensure:
1. **NanoClaw is installed and running** - WhatsApp connected, service active
2. **Dependencies installed**:
```bash
npm ls playwright dotenv-cli || npm install playwright dotenv-cli
pnpm ls playwright dotenv-cli || pnpm install playwright dotenv-cli
```
3. **CHROME_PATH configured** in `.env` (if Chrome is not at default location):
```bash
@@ -40,7 +40,7 @@ Before using this skill, ensure:
```bash
# 1. Setup authentication (interactive)
npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/setup.ts
pnpm exec dotenv -e .env -- pnpm exec tsx .claude/skills/x-integration/scripts/setup.ts
# Verify: data/x-auth.json should exist after successful login
# 2. Rebuild container to include skill
@@ -48,7 +48,7 @@ npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/setup.ts
# Verify: Output shows "COPY .claude/skills/x-integration/agent.ts"
# 3. Rebuild host and restart service
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
# Verify: launchctl list | grep nanoclaw (macOS) or systemctl --user status nanoclaw (Linux)
@@ -225,7 +225,7 @@ COPY container/agent-runner/package*.json ./
COPY container/agent-runner/ ./
```
Then add COPY line after `COPY container/agent-runner/ ./` and before `RUN npm run build`:
Then add COPY line after `COPY container/agent-runner/ ./` and before `RUN pnpm run build`:
```dockerfile
# Copy skill MCP tools
COPY .claude/skills/x-integration/agent.ts ./src/skills/x-integration/
@@ -247,7 +247,7 @@ echo "Chrome not found - update CHROME_PATH in .env"
### 2. Run Authentication
```bash
npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/setup.ts
pnpm exec dotenv -e .env -- pnpm exec tsx .claude/skills/x-integration/scripts/setup.ts
```
This opens Chrome for manual X login. Session saved to `data/x-browser-profile/`.
@@ -271,7 +271,7 @@ cat data/x-auth.json # Should show {"authenticated": true, ...}
### 4. Restart Service
```bash
npm run build
pnpm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
```
@@ -317,26 +317,26 @@ ls -la data/x-browser-profile/ 2>/dev/null | head -5
### Re-authenticate (if expired)
```bash
npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/setup.ts
pnpm exec dotenv -e .env -- pnpm exec tsx .claude/skills/x-integration/scripts/setup.ts
```
### Test Post (will actually post)
```bash
echo '{"content":"Test tweet - please ignore"}' | npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/post.ts
echo '{"content":"Test tweet - please ignore"}' | pnpm exec dotenv -e .env -- pnpm exec tsx .claude/skills/x-integration/scripts/post.ts
```
### Test Like
```bash
echo '{"tweetUrl":"https://x.com/user/status/123"}' | npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/like.ts
echo '{"tweetUrl":"https://x.com/user/status/123"}' | pnpm exec dotenv -e .env -- pnpm exec tsx .claude/skills/x-integration/scripts/like.ts
```
Or export `CHROME_PATH` manually before running:
```bash
export CHROME_PATH="/path/to/chrome"
echo '{"content":"Test"}' | npx tsx .claude/skills/x-integration/scripts/post.ts
echo '{"content":"Test"}' | pnpm exec tsx .claude/skills/x-integration/scripts/post.ts
```
## Troubleshooting
@@ -344,7 +344,7 @@ echo '{"content":"Test"}' | npx tsx .claude/skills/x-integration/scripts/post.ts
### Authentication Expired
```bash
npx dotenv -e .env -- npx tsx .claude/skills/x-integration/scripts/setup.ts
pnpm exec dotenv -e .env -- pnpm exec tsx .claude/skills/x-integration/scripts/setup.ts
launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
# Linux: systemctl --user restart nanoclaw
```
+1 -1
View File
@@ -22,7 +22,7 @@ async function runScript(script: string, args: object): Promise<SkillResult> {
const scriptPath = path.join(process.cwd(), '.claude', 'skills', 'x-integration', 'scripts', `${script}.ts`);
return new Promise((resolve) => {
const proc = spawn('npx', ['tsx', scriptPath], {
const proc = spawn('pnpm', ['exec', 'tsx', scriptPath], {
cwd: process.cwd(),
env: { ...process.env, NANOCLAW_ROOT: process.cwd() },
stdio: ['pipe', 'pipe', 'pipe']
+2 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env npx tsx
#!/usr/bin/env pnpm exec tsx
/**
* X Integration - Like Tweet
* Usage: echo '{"tweetUrl":"https://x.com/user/status/123"}' | npx tsx like.ts
* Usage: echo '{"tweetUrl":"https://x.com/user/status/123"}' | pnpm exec tsx like.ts
*/
import { getBrowserContext, navigateToTweet, runScript, config, ScriptResult } from '../lib/browser.js';
+2 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env npx tsx
#!/usr/bin/env pnpm exec tsx
/**
* X Integration - Post Tweet
* Usage: echo '{"content":"Hello world"}' | npx tsx post.ts
* Usage: echo '{"content":"Hello world"}' | pnpm exec tsx post.ts
*/
import { getBrowserContext, runScript, validateContent, config, ScriptResult } from '../lib/browser.js';
@@ -1,7 +1,7 @@
#!/usr/bin/env npx tsx
#!/usr/bin/env pnpm exec tsx
/**
* X Integration - Quote Tweet
* Usage: echo '{"tweetUrl":"https://x.com/user/status/123","comment":"My thoughts"}' | npx tsx quote.ts
* Usage: echo '{"tweetUrl":"https://x.com/user/status/123","comment":"My thoughts"}' | pnpm exec tsx quote.ts
*/
import { getBrowserContext, navigateToTweet, runScript, validateContent, config, ScriptResult } from '../lib/browser.js';
@@ -1,7 +1,7 @@
#!/usr/bin/env npx tsx
#!/usr/bin/env pnpm exec tsx
/**
* X Integration - Reply to Tweet
* Usage: echo '{"tweetUrl":"https://x.com/user/status/123","content":"Great post!"}' | npx tsx reply.ts
* Usage: echo '{"tweetUrl":"https://x.com/user/status/123","content":"Great post!"}' | pnpm exec tsx reply.ts
*/
import { getBrowserContext, navigateToTweet, runScript, validateContent, config, ScriptResult } from '../lib/browser.js';
@@ -1,7 +1,7 @@
#!/usr/bin/env npx tsx
#!/usr/bin/env pnpm exec tsx
/**
* X Integration - Retweet
* Usage: echo '{"tweetUrl":"https://x.com/user/status/123"}' | npx tsx retweet.ts
* Usage: echo '{"tweetUrl":"https://x.com/user/status/123"}' | pnpm exec tsx retweet.ts
*/
import { getBrowserContext, navigateToTweet, runScript, config, ScriptResult } from '../lib/browser.js';
@@ -1,7 +1,7 @@
#!/usr/bin/env npx tsx
#!/usr/bin/env pnpm exec tsx
/**
* X Integration - Authentication Setup
* Usage: npx tsx setup.ts
* Usage: pnpm exec tsx setup.ts
*
* Interactive script - opens browser for manual login
*/