fix: remaining npm→pnpm gaps + dockerignore for pnpm symlinks

- container/.dockerignore (new): exclude agent-runner/node_modules and
  agent-runner/dist so COPY agent-runner/ ./ doesn't clobber the
  pnpm-installed node_modules with host directories. Under npm's flat
  layout this was forgiving; under pnpm's symlink layout it's a hard
  conflict (overlay2 cannot copy onto a symlink target).
- setup/{groups,service}.ts: execSync('pnpm run build') not npm.
- setup/index.ts: usage string.
- scripts/*.ts: usage comments + seed-discord final log.
- .claude/settings.json: permission allowlist entries.
- .claude/skills/{add-whatsapp-v2,add-dashboard}/SKILL.md: docs.
- container/skills/{frontend-engineer,vercel-cli,self-customize}/SKILL.md:
  agent-facing docs still told the container agent to run npm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gavrielc
2026-04-17 09:53:00 +03:00
parent 504e5296c9
commit 22498ae69c
16 changed files with 40 additions and 38 deletions
+11 -11
View File
@@ -6,17 +6,17 @@
"allow": [
"Bash(bash setup.sh*)",
"Bash(git remote *)",
"Bash(npx tsx setup/index.ts*)",
"Bash(npx tsx scripts/init-first-agent.ts*)",
"Bash(npm install @chat-adapter/*)",
"Bash(npm install chat-adapter-imessage*)",
"Bash(npm install @bitbasti/chat-adapter-webex*)",
"Bash(npm install @resend/chat-sdk-adapter*)",
"Bash(npm install @whiskeysockets/baileys*)",
"Bash(npm install @beeper/chat-adapter-matrix*)",
"Bash(npm install @nanoco/nanoclaw-dashboard*)",
"Bash(npm ci*)",
"Bash(npm run build*)",
"Bash(pnpm exec tsx setup/index.ts*)",
"Bash(pnpm exec tsx scripts/init-first-agent.ts*)",
"Bash(pnpm install @chat-adapter/*)",
"Bash(pnpm install chat-adapter-imessage*)",
"Bash(pnpm install @bitbasti/chat-adapter-webex*)",
"Bash(pnpm install @resend/chat-sdk-adapter*)",
"Bash(pnpm install @whiskeysockets/baileys*)",
"Bash(pnpm install @beeper/chat-adapter-matrix*)",
"Bash(pnpm install @nanoco/nanoclaw-dashboard*)",
"Bash(pnpm install --frozen-lockfile*)",
"Bash(pnpm run build*)",
"Bash(curl -fsSL onecli.sh*)",
"Bash(onecli *)",
"Bash(grep -q *)",
+4 -4
View File
@@ -25,7 +25,7 @@ NanoClaw (pusher) Dashboard (npm package)
### 1. Install the npm package
```bash
npm install @nanoco/nanoclaw-dashboard
pnpm install @nanoco/nanoclaw-dashboard
```
### 2. Copy the pusher module
@@ -94,7 +94,7 @@ Generate the secret: `node -e "console.log('nc-' + require('crypto').randomBytes
### 6. Build and restart
```bash
npm run build
pnpm run build
systemctl --user restart nanoclaw # Linux
# or: launchctl kickstart -k gui/$(id -u)/com.nanoclaw # macOS
```
@@ -130,9 +130,9 @@ Open `http://localhost:3100/dashboard` in a browser.
## Removal
```bash
npm uninstall @nanoco/nanoclaw-dashboard
pnpm uninstall @nanoco/nanoclaw-dashboard
rm src/dashboard-pusher.ts
# Remove the dashboard block from src/index.ts
# Remove DASHBOARD_SECRET and DASHBOARD_PORT from .env
npm run build
pnpm run build
```
+8 -8
View File
@@ -16,7 +16,7 @@ Check if `src/channels/whatsapp.ts` exists and the import is uncommented in `src
### Install the adapter packages
```bash
npm install @whiskeysockets/baileys@^6.7.21 pino@^9.6.0 qrcode@^1.5.4 @types/qrcode@^1.5.6
pnpm install @whiskeysockets/baileys@^6.7.21 pino@^9.6.0 qrcode@^1.5.4 @types/qrcode@^1.5.6
```
### Enable the channel
@@ -39,7 +39,7 @@ import './whatsapp.js';
### Build
```bash
npm run build
pnpm run build
```
## Credentials
@@ -90,7 +90,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)
@@ -106,7 +106,7 @@ 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
```
(Bash timeout: 150000ms)
@@ -123,7 +123,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):
@@ -199,7 +199,7 @@ Not supported (WhatsApp linked device limitation): edit messages, delete message
QR codes expire after ~60 seconds. Re-run the auth command:
```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
```
### Pairing code not working
@@ -207,7 +207,7 @@ rm -rf store/auth/ && npx tsx setup/index.ts --step whatsapp-auth -- --method qr
Codes expire in ~60 seconds. Delete auth and retry:
```bash
rm -rf store/auth/ && npx tsx setup/index.ts --step whatsapp-auth -- --method pairing-code --phone <phone>
rm -rf store/auth/ && pnpm exec tsx setup/index.ts --step whatsapp-auth -- --method pairing-code --phone <phone>
```
Ensure: digits only (no `+`), phone has internet, WhatsApp is updated.
@@ -215,7 +215,7 @@ Ensure: digits only (no `+`), phone has internet, WhatsApp is updated.
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
```
### "waiting for this message" on reactions
+2
View File
@@ -0,0 +1,2 @@
agent-runner/node_modules
agent-runner/dist
+2 -2
View File
@@ -66,7 +66,7 @@ Every frontend task follows this sequence. Do not skip steps.
Run the build and fix ALL errors:
```bash
npm run build 2>&1
pnpm run build 2>&1
```
If it fails, **fix it**. Do not deploy broken builds. Do not disable ESLint rules or TypeScript checks to make it pass.
@@ -76,7 +76,7 @@ If it fails, **fix it**. Do not deploy broken builds. Do not disable ESLint rule
Start the dev server and test in a real browser:
```bash
npm run dev &
pnpm run dev &
DEV_PID=$!
sleep 3
```
+1 -1
View File
@@ -87,4 +87,4 @@ User: "Can you transcribe audio?"
- **The change is for a one-off task** — just do it in your workspace, don't modify the container
- **The request is ambiguous** — ask the user what they actually need before spinning up builders or requesting installs
- **You don't know if it will work** — prototype in your workspace first (`npm install` in `/workspace/agent/`), then promote to container-level install if it proves useful
- **You don't know if it will work** — prototype in your workspace first (`pnpm install` in `/workspace/agent/`), then promote to container-level install if it proves useful
+1 -1
View File
@@ -117,7 +117,7 @@ After sending, tell the user you've handed it off and will share the result when
## Best Practices
- Run `npm run build` locally before deploying to catch build errors early
- Run `pnpm run build` locally before deploying to catch build errors early
- Use `--cwd` instead of `cd` to keep your working directory stable
- For Next.js projects, `vercel deploy` auto-detects the framework — no extra config needed
- Use `vercel.json` only when you need custom build settings, rewrites, or headers
+1 -1
View File
@@ -10,7 +10,7 @@
* channel adapters, so there's no Gateway conflict.
*
* Usage:
* npx tsx scripts/init-first-agent.ts \
* pnpm exec tsx scripts/init-first-agent.ts \
* --channel discord \
* --user-id discord:1470183333427675709 \
* --platform-id discord:@me:1491573333382523708 \
+1 -1
View File
@@ -22,7 +22,7 @@
*
* Idempotent — safe to re-run.
*
* Usage: npx tsx scripts/migrate-group-claude-md.ts
* Usage: pnpm exec tsx scripts/migrate-group-claude-md.ts
*/
import fs from 'fs';
import path from 'path';
+2 -2
View File
@@ -1,7 +1,7 @@
/**
* Seed the v2 central DB with a Discord agent group + messaging group.
*
* Usage: npx tsx scripts/seed-discord.ts
* Usage: pnpm exec tsx scripts/seed-discord.ts
*/
import path from 'path';
@@ -73,4 +73,4 @@ try {
}
}
console.log('Done! Run: npm run build && node dist/index.js');
console.log('Done! Run: pnpm run build && node dist/index.js');
+1 -1
View File
@@ -2,7 +2,7 @@
* Quick integration test: create a session DB, insert a message,
* run the v2 poll loop with the Claude provider, verify output.
*
* Usage: npx tsx scripts/test-v2-agent.ts
* Usage: pnpm exec tsx scripts/test-v2-agent.ts
*/
import Database from 'better-sqlite3';
import fs from 'fs';
+1 -1
View File
@@ -4,7 +4,7 @@
* Mock adapter → onInbound → router → session DB → Docker container →
* agent-runner → Claude → messages_out → delivery → mock adapter.deliver()
*
* Usage: npx tsx scripts/test-v2-channel-e2e.ts
* Usage: pnpm exec tsx scripts/test-v2-channel-e2e.ts
*/
import Database from 'better-sqlite3';
import fs from 'fs';
+1 -1
View File
@@ -6,7 +6,7 @@
* 3. Container runs v2 agent-runner, polls inbound.db, queries Claude, writes outbound.db
* 4. Poll outbound.db for messages_out response
*
* Usage: npx tsx scripts/test-v2-host.ts
* Usage: pnpm exec tsx scripts/test-v2-host.ts
*/
import Database from 'better-sqlite3';
import fs from 'fs';
+1 -1
View File
@@ -87,7 +87,7 @@ async function syncGroups(projectRoot: string): Promise<void> {
log.info('Building TypeScript');
let buildOk = false;
try {
execSync('npm run build', {
execSync('pnpm run build', {
cwd: projectRoot,
stdio: ['ignore', 'pipe', 'pipe'],
});
+2 -2
View File
@@ -1,6 +1,6 @@
/**
* Setup CLI entry point.
* Usage: npx tsx setup/index.ts --step <name> [args...]
* Usage: pnpm exec tsx setup/index.ts --step <name> [args...]
*/
import { log } from '../src/log.js';
import { emitStatus } from './status.js';
@@ -27,7 +27,7 @@ async function main(): Promise<void> {
if (stepIdx === -1 || !args[stepIdx + 1]) {
console.error(
`Usage: npx tsx setup/index.ts --step <${Object.keys(STEPS).join('|')}> [args...]`,
`Usage: pnpm exec tsx setup/index.ts --step <${Object.keys(STEPS).join('|')}> [args...]`,
);
process.exit(1);
}
+1 -1
View File
@@ -31,7 +31,7 @@ export async function run(_args: string[]): Promise<void> {
// Build first
log.info('Building TypeScript');
try {
execSync('npm run build', {
execSync('pnpm run build', {
cwd: projectRoot,
stdio: ['ignore', 'pipe', 'pipe'],
});