Fix container execution and add debug tooling
Container fixes:
- Run as non-root 'node' user (required for --dangerously-skip-permissions)
- Add allowDangerouslySkipPermissions: true to SDK options
- Mount .env file to work around Apple Container -i env var bug
- Use --mount for readonly, -v for read-write (Apple Container quirk)
- Bump SDK to 0.2.29, zod to v4
- Install Claude Code CLI globally in container
Logging improvements:
- Write per-run logs to groups/{folder}/logs/container-*.log
- Add debug-level logging for mounts and container args
Documentation:
- Add /debug skill with comprehensive troubleshooting guide
- Update /setup skill with API key configuration step
- Update SPEC.md with container details, mount syntax, security notes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
36
SPEC.md
36
SPEC.md
@@ -54,7 +54,7 @@ A personal Claude assistant accessible via WhatsApp, with persistent memory per
|
||||
│ │ Volume mounts: │ │
|
||||
│ │ • groups/{name}/ → /workspace/group │ │
|
||||
│ │ • groups/CLAUDE.md → /workspace/global/CLAUDE.md │ │
|
||||
│ │ • ~/.claude/ → /root/.claude/ (sessions) │ │
|
||||
│ │ • ~/.claude/ → /home/node/.claude/ (sessions) │ │
|
||||
│ │ • Additional dirs → /workspace/extra/* │ │
|
||||
│ │ │ │
|
||||
│ │ Tools (all groups): │ │
|
||||
@@ -76,7 +76,7 @@ A personal Claude assistant accessible via WhatsApp, with persistent memory per
|
||||
| WhatsApp Connection | Node.js (@whiskeysockets/baileys) | Connect to WhatsApp, send/receive messages |
|
||||
| Message Storage | SQLite (better-sqlite3) | Store messages for polling |
|
||||
| Container Runtime | Apple Container | Isolated Linux VMs for agent execution |
|
||||
| Agent | @anthropic-ai/claude-agent-sdk | Run Claude with tools and MCP servers |
|
||||
| Agent | @anthropic-ai/claude-agent-sdk (0.2.29) | Run Claude with tools and MCP servers |
|
||||
| Browser Automation | agent-browser + Chromium | Web interaction and screenshots |
|
||||
| Runtime | Node.js 22+ | Host process for routing and scheduling |
|
||||
|
||||
@@ -104,7 +104,7 @@ nanoclaw/
|
||||
│ └── container-runner.ts # Spawns agents in Apple Containers
|
||||
│
|
||||
├── container/
|
||||
│ ├── Dockerfile # Container image definition
|
||||
│ ├── Dockerfile # Container image (runs as 'node' user, includes Claude Code CLI)
|
||||
│ ├── build.sh # Build script for container image
|
||||
│ ├── agent-runner/ # Code that runs inside the container
|
||||
│ │ ├── package.json
|
||||
@@ -121,8 +121,10 @@ nanoclaw/
|
||||
│ └── skills/
|
||||
│ ├── setup/
|
||||
│ │ └── SKILL.md # /setup skill
|
||||
│ └── customize/
|
||||
│ └── SKILL.md # /customize skill
|
||||
│ ├── customize/
|
||||
│ │ └── SKILL.md # /customize skill
|
||||
│ └── debug/
|
||||
│ └── SKILL.md # /debug skill (container debugging)
|
||||
│
|
||||
├── groups/
|
||||
│ ├── CLAUDE.md # Global memory (all groups read this)
|
||||
@@ -142,11 +144,14 @@ nanoclaw/
|
||||
│ ├── sessions.json # Active session IDs per group
|
||||
│ ├── archived_sessions.json # Old sessions after /clear
|
||||
│ ├── registered_groups.json # Group JID → folder mapping
|
||||
│ └── router_state.json # Last processed timestamp + last agent timestamps
|
||||
│ ├── router_state.json # Last processed timestamp + last agent timestamps
|
||||
│ ├── env/env # Copy of .env for container mounting
|
||||
│ └── ipc/ # Container IPC (messages/, tasks/)
|
||||
│
|
||||
├── logs/ # Runtime logs (gitignored)
|
||||
│ ├── nanoclaw.log # stdout
|
||||
│ └── nanoclaw.error.log # stderr
|
||||
│ ├── nanoclaw.log # Host stdout
|
||||
│ └── nanoclaw.error.log # Host stderr
|
||||
│ # Note: Per-container logs are in groups/{folder}/logs/container-*.log
|
||||
│
|
||||
└── launchd/
|
||||
└── com.nanoclaw.plist # macOS service configuration
|
||||
@@ -202,6 +207,18 @@ Groups can have additional directories mounted via `containerConfig` in `data/re
|
||||
|
||||
Additional mounts appear at `/workspace/extra/{containerPath}` inside the container.
|
||||
|
||||
**Apple Container mount syntax note:** Read-write mounts use `-v host:container`, but readonly mounts require `--mount "type=bind,source=...,target=...,readonly"` (the `:ro` suffix doesn't work).
|
||||
|
||||
### API Key Configuration
|
||||
|
||||
The Anthropic API key must be in a `.env` file in the project root:
|
||||
|
||||
```bash
|
||||
ANTHROPIC_API_KEY=sk-ant-...
|
||||
```
|
||||
|
||||
This file is automatically mounted into the container at `/workspace/env-dir/env` and sourced by the entrypoint script. This workaround is needed because Apple Container loses `-e` environment variables when using `-i` (interactive mode with piped stdin).
|
||||
|
||||
### Changing the Assistant Name
|
||||
|
||||
Set the `ASSISTANT_NAME` environment variable:
|
||||
@@ -540,6 +557,7 @@ All agents run inside Apple Container (lightweight Linux VMs), providing:
|
||||
- **Safe Bash access**: Commands run inside the container, not on your Mac
|
||||
- **Network isolation**: Can be configured per-container if needed
|
||||
- **Process isolation**: Container processes can't affect the host
|
||||
- **Non-root user**: Container runs as unprivileged `node` user (uid 1000)
|
||||
|
||||
### Prompt Injection Risk
|
||||
|
||||
@@ -563,7 +581,7 @@ WhatsApp messages could contain malicious instructions attempting to manipulate
|
||||
|
||||
| Credential | Storage Location | Notes |
|
||||
|------------|------------------|-------|
|
||||
| Claude CLI Auth | ~/.claude/ | Managed by Claude Code CLI |
|
||||
| Claude CLI Auth | ~/.claude/ | Mounted to /home/node/.claude/ in container |
|
||||
| WhatsApp Session | store/auth/ | Auto-created, persists ~20 days |
|
||||
| Gmail OAuth Tokens | ~/.gmail-mcp/ | Created during setup (optional) |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user