--- name: setup description: Run initial NanoClaw setup. Use when user wants to install dependencies, authenticate WhatsApp/Gmail, register their main channel, or start the background services. Triggers on "setup", "install", "configure nanoclaw", or first-time setup requests. --- # NanoClaw Setup Run all commands automatically. Only pause when user action is required (scanning QR codes). ## 1. Install Dependencies ```bash npm install ``` ## 2. Install Apple Container Check if Apple Container is installed: ```bash which container && container --version || echo "Not installed" ``` If not installed, tell the user: > Apple Container is required for running agents in isolated environments. > > 1. Download the latest `.pkg` from https://github.com/apple/container/releases > 2. Double-click to install > 3. Run `container system start` to start the service > > Let me know when you've completed these steps. Wait for user confirmation, then verify: ```bash container system start container --version ``` **Note:** NanoClaw automatically starts the Apple Container system when it launches, so you don't need to start it manually after reboots. ## 3. Configure Claude Authentication Ask the user: > Do you want to use your **Claude subscription** (Pro/Max) or an **Anthropic API key**? ### Option 1: Claude Subscription (Recommended) Ask the user: > Want me to grab the OAuth token from your current Claude session? If yes: ```bash TOKEN=$(cat ~/.claude/.credentials.json 2>/dev/null | jq -r '.claudeAiOauth.accessToken // empty') if [ -n "$TOKEN" ]; then echo "CLAUDE_CODE_OAUTH_TOKEN=$TOKEN" > .env echo "Token configured: ${TOKEN:0:20}...${TOKEN: -4}" else echo "No token found - are you logged in to Claude Code?" fi ``` If the token wasn't found, tell the user: > Run `claude` in another terminal and log in first, then come back here. ### Option 2: API Key Ask if they have an existing key to copy or need to create one. **Copy existing:** ```bash grep "^ANTHROPIC_API_KEY=" /path/to/source/.env > .env ``` **Create new:** ```bash echo 'ANTHROPIC_API_KEY=' > .env ``` Tell the user to add their key from https://console.anthropic.com/ **Verify:** ```bash KEY=$(grep "^ANTHROPIC_API_KEY=" .env | cut -d= -f2) [ -n "$KEY" ] && echo "API key configured: ${KEY:0:10}...${KEY: -4}" || echo "Missing" ``` ## 4. Build Container Image Build the NanoClaw agent container: ```bash ./container/build.sh ``` This creates the `nanoclaw-agent:latest` image with Node.js, Chromium, Claude Code CLI, and agent-browser. Verify the build succeeded (the `container images` command may not work due to a plugin issue, so we verify by running a simple test): ```bash echo '{}' | container run -i --entrypoint /bin/echo nanoclaw-agent:latest "Container OK" || echo "Container build failed" ``` ## 5. WhatsApp Authentication **USER ACTION REQUIRED** Run the authentication script: ```bash npm run auth ``` Tell the user: > A QR code will appear. On your phone: > 1. Open WhatsApp > 2. Tap **Settings → Linked Devices → Link a Device** > 3. Scan the QR code Wait for the script to output "Successfully authenticated" then continue. If it says "Already authenticated", skip to the next step. ## 6. Configure Assistant Name Ask the user: > What trigger word do you want to use? (default: `Andy`) > > Messages starting with `@TriggerWord` will be sent to Claude. If they choose something other than `Andy`, update it in these places: 1. `groups/CLAUDE.md` - Change "# Andy" and "You are Andy" to the new name 2. `groups/main/CLAUDE.md` - Same changes at the top 3. `data/registered_groups.json` - Use `@NewName` as the trigger when registering groups Store their choice - you'll use it when creating the registered_groups.json and when telling them how to test. ## 7. Register Main Channel Ask the user: > Do you want to use your **personal chat** (message yourself) or a **WhatsApp group** as your main control channel? For personal chat: > Send any message to yourself in WhatsApp (the "Message Yourself" chat). Tell me when done. For group: > Send any message in the WhatsApp group you want to use as your main channel. Tell me when done. After user confirms, start the app briefly to capture the message: ```bash timeout 10 npm run dev || true ``` Then find the JID from the database: ```bash # For personal chat (ends with @s.whatsapp.net) sqlite3 store/messages.db "SELECT DISTINCT chat_jid FROM messages WHERE chat_jid LIKE '%@s.whatsapp.net' ORDER BY timestamp DESC LIMIT 5" # For group (ends with @g.us) sqlite3 store/messages.db "SELECT DISTINCT chat_jid FROM messages WHERE chat_jid LIKE '%@g.us' ORDER BY timestamp DESC LIMIT 5" ``` Create/update `data/registered_groups.json` using the JID from above and the assistant name from step 5: ```json { "JID_HERE": { "name": "main", "folder": "main", "trigger": "@ASSISTANT_NAME", "added_at": "CURRENT_ISO_TIMESTAMP" } } ``` Ensure the groups folder exists: ```bash mkdir -p groups/main/logs ``` ## 8. Gmail Authentication (Optional) Ask the user: > Do you want to enable Gmail integration for reading/sending emails? > > **Note:** This requires setting up Google Cloud Platform OAuth credentials, which involves: > 1. Creating a GCP project > 2. Enabling the Gmail API > 3. Creating OAuth 2.0 credentials > 4. Downloading a credentials file > > This takes about 5-10 minutes. Skip if you don't need email integration. If yes, guide them through the prerequisites: 1. Go to https://console.cloud.google.com 2. Create a new project (or use an existing one) 3. Enable the Gmail API (APIs & Services → Enable APIs → search "Gmail API") 4. Create OAuth 2.0 credentials (APIs & Services → Credentials → Create Credentials → OAuth client ID → Desktop app) 5. Download the JSON file and save to `~/.gmail-mcp/gcp-oauth.keys.json` Then run: ```bash npx -y @gongrzhe/server-gmail-autoauth-mcp ``` This will open a browser for OAuth consent. After authorization, credentials are cached. ## 9. Configure launchd Service Get the actual paths: ```bash which node pwd ``` Create the plist file at `~/Library/LaunchAgents/com.nanoclaw.plist`: ```xml Label com.nanoclaw ProgramArguments NODE_PATH_HERE PROJECT_PATH_HERE/dist/index.js WorkingDirectory PROJECT_PATH_HERE RunAtLoad KeepAlive EnvironmentVariables PATH /usr/local/bin:/usr/bin:/bin:HOME_PATH_HERE/.local/bin HOME HOME_PATH_HERE StandardOutPath PROJECT_PATH_HERE/logs/nanoclaw.log StandardErrorPath PROJECT_PATH_HERE/logs/nanoclaw.error.log ``` Replace the placeholders with actual paths from the commands above. Build and start the service: ```bash npm run build mkdir -p logs launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist ``` Verify it's running: ```bash launchctl list | grep nanoclaw ``` ## 10. Test Tell the user (using the assistant name they configured): > Send `@ASSISTANT_NAME hello` in your registered chat. Check the logs: ```bash tail -f logs/nanoclaw.log ``` The user should receive a response in WhatsApp. ## Troubleshooting **Service not starting**: Check `logs/nanoclaw.error.log` **Container agent fails with "Claude Code process exited with code 1"**: - Ensure Apple Container is running: `container system start` - Check container logs: `cat groups/main/logs/container-*.log | tail -50` **No response to messages**: - Verify the trigger pattern matches (e.g., `@AssistantName` at start of message) - Check that the chat JID is in `data/registered_groups.json` - Check `logs/nanoclaw.log` for errors **WhatsApp disconnected**: - The service will show a macOS notification - Run `npm run auth` to re-authenticate - Restart the service: `launchctl kickstart -k gui/$(id -u)/com.nanoclaw` **Unload service**: ```bash launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist ```