ASSISTANT_NAME was interpolated directly into a regex without escaping.
If the name contained regex metacharacters (e.g., @A.*), the trigger
would match unintended patterns. This adds escapeRegex() to properly
escape special characters before building the TRIGGER_PATTERN.
https://claude.ai/code/session_01Lvuxq73qa9S4rtmGpX1WsP
Co-authored-by: Claude <noreply@anthropic.com>
updateChatName() was inserting new groups with last_message_time set to
Unix epoch (1970-01-01), causing newly discovered groups to appear at
the bottom of activity-ordered listings. Changed to use current time
for new groups while preserving existing timestamps for known groups.
https://claude.ai/code/session_018rcZvALfF3ND2jfcvBaFo2
Co-authored-by: Claude <noreply@anthropic.com>
- Remove unused claude-agent-sdk from host deps (only used in container)
- Remove dead scheduler MCP config (built into IPC)
- Remove unused eslint script
- Add clear error message when Apple Container fails to start
- Auto-generate launchd plist with real paths in setup skill
- Standardize Node.js version to 20+ everywhere
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add secure mount allowlist validation
Addresses arbitrary host mount vulnerability by validating additional
mounts against an external allowlist stored at ~/.config/nanoclaw/.
This location is never mounted into containers, making it tamper-proof.
Security measures:
- Allowlist cached in memory (edits require process restart)
- Real path resolution (blocks symlink and .. traversal attacks)
- Blocked patterns for sensitive paths (.ssh, .gnupg, .aws, etc.)
- Non-main groups forced to read-only when nonMainReadOnly is true
- Container path validation prevents /workspace/extra escape
https://claude.ai/code/session_01BPqdNy4EAHHJcdtZ27TXkh
* Add mount allowlist setup to /setup skill
Interactive walkthrough that asks users:
- Whether they want agents to access external directories
- Which directories to allow (with paths)
- Read-write vs read-only for each
- Whether non-main groups should be restricted to read-only
Creates ~/.config/nanoclaw/mount-allowlist.json based on answers.
https://claude.ai/code/session_01BPqdNy4EAHHJcdtZ27TXkh
---------
Co-authored-by: Claude <noreply@anthropic.com>
52+ modules, 8 config files, 45+ deps, 15 channel providers.
Security is application-level (allowlists) vs actual container isolation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Sync group names from WhatsApp via groupFetchAllParticipating()
- Store group names in chats table (jid -> name mapping)
- Daily sync with 24h cache, on-demand refresh via IPC
- Write available_groups.json snapshot for agent (main group only)
- Agent can request refresh_groups via IPC if group not found
- Update documentation in main CLAUDE.md and debug skill
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- PR #10: Add sentinel markers for robust JSON parsing between container
and host. Fallback to last-line parsing for backwards compatibility.
- PR #5: Look up target JID from registeredGroups instead of trusting
IPC payload, fixing cross-group scheduled tasks getting wrong chat_jid.
- PR #8: Add lightweight schedule validation in container MCP that
returns errors to agents (cron syntax, positive interval, valid ISO
timestamp). Also defensive validation on host side.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Keep only comments that explain non-obvious behavior or add context
not apparent from reading the code.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add authorization checks to IPC task operations (pause/resume/cancel)
to prevent cross-group task manipulation
- Only store message content for registered groups; unregistered chats
only get metadata stored for group discovery
- Container logs now only include full input/output in debug mode;
default logging omits sensitive message content
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add PreCompact hook in agent-runner that archives conversations before
compaction, using session summary from sessions-index.json for filename
- Remove /clear command (programmatic compaction not supported by SDK)
- Add /add-clear to RFS for future implementation
- Update CLAUDE.md templates with memory system instructions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove dash-as-em-dash patterns throughout
- Add FAQ about what changes are accepted (security, bugs, clear fixes)
- Clarify that enhancements should be skills, not PRs
- Fix "Leverage" → "Use" in REQUIREMENTS.md
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Main gets /workspace/project with full project access
- Main can query SQLite database and edit configs
- Updated main CLAUDE.md with container paths
- Added docs for configuring additional mounts per group
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Agents run in isolated Linux VMs via Apple Container
- All groups get Bash access (safe - sandboxed in container)
- Browser automation via agent-browser + Chromium
- Per-group configurable additional directory mounts
- File-based IPC for messages and scheduled tasks
- Container image with Node.js 22, Chromium, agent-browser
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Custom nanoclaw MCP server with scheduling tools (schedule_task,
list_tasks, get_task, update_task, pause/resume/cancel_task, send_message)
- Tasks run as full agents in their group's context
- Support for cron, interval, and one-time schedules
- Task run logging with duration and results
- Main channel has Bash access for admin tasks (query DB, manage groups)
- Other groups restricted to file operations only
- Updated docs and requirements
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Format: [Jan 31 2:35 PM] instead of [14:35:00]
Date provides important context for ongoing conversations.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use pushName from baileys to get the sender's display name instead
of just the phone number. Falls back to phone number if no name.
Includes migration to add sender_name column to existing databases.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Include the full message with @trigger so agent sees exactly
what was written. Current message is already in missedMessages
query so no need to add separately.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a triggered message comes in, fetch all messages in that chat
since the last agent interaction and include them in the prompt.
Each message is formatted with timestamp and sender.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove context building (group name, chat JID, permissions)
- Agent runs in group folder which determines its permissions
- Caller handles response prefixing and where to send reply
- Session provides continuity, no need for metadata in each message
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- src/db.ts: initDatabase, closeDatabase, storeMessage, getNewMessages
- Removes SQL from index.ts
- Database initialization happens once at startup
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Explain Gmail/GCP prerequisites upfront before asking
- Replace hardcoded "Andy" with ASSISTANT_NAME placeholder
- Replace hardcoded timestamp with CURRENT_ISO_TIMESTAMP
- Add step 3 to ask user for their preferred trigger word
- Renumber sections accordingly
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add src/auth.ts for interactive QR code authentication
- Add `npm run auth` script
- Update setup skill for current Node.js architecture
- Daemon (src/index.ts) now only uses stored credentials
Auth is run during setup; daemon assumes credentials exist and
shows macOS notification if re-auth is needed.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The daemon should never show interactive QR codes. If auth is needed,
send a macOS notification alerting the user to run /setup, then exit.
Also removes unused qrcode-terminal dependency.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
If WhatsApp authentication is required but the process is running
non-interactively (as a launchd daemon), exit with an error instead
of showing a QR code that nobody will see.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
A minimal Node.js application that connects Claude Agent SDK to WhatsApp
using baileys. Features per-group memory via CLAUDE.md files, session
continuity, scheduled tasks, and Gmail integration via MCP.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>