Rebrand NanoClaw to EJClaw

This commit is contained in:
Eyejoker
2026-03-19 03:31:41 +09:00
parent 29b78fc286
commit f2ad1331a9
44 changed files with 564 additions and 535 deletions

View File

@@ -1,4 +1,4 @@
# NanoClaw Debug Checklist
# EJClaw Debug Checklist
## Known Issues (2026-02-08)
@@ -16,7 +16,7 @@ Both timers fire at the same time, so containers always exit via hard SIGKILL (c
```bash
# 1. Is the service running?
launchctl list | grep nanoclaw
# Expected: PID 0 com.nanoclaw (PID = running, "-" = not running, non-zero exit = crashed)
# Expected: PID 0 com.ejclaw (PID = running, "-" = not running, non-zero exit = crashed)
# 2. Any running containers?
container ls --format '{{.Names}} {{.Status}}' 2>/dev/null | grep nanoclaw
@@ -25,13 +25,13 @@ container ls --format '{{.Names}} {{.Status}}' 2>/dev/null | grep nanoclaw
container ls -a --format '{{.Names}} {{.Status}}' 2>/dev/null | grep nanoclaw
# 4. Recent errors in service log?
grep -E 'ERROR|WARN' logs/nanoclaw.log | tail -20
grep -E 'ERROR|WARN' logs/ejclaw.log | tail -20
# 5. Is WhatsApp connected? (look for last connection event)
grep -E 'Connected to WhatsApp|Connection closed|connection.*close' logs/nanoclaw.log | tail -5
grep -E 'Connected to WhatsApp|Connection closed|connection.*close' logs/ejclaw.log | tail -5
# 6. Are groups loaded?
grep 'groupCount' logs/nanoclaw.log | tail -3
grep 'groupCount' logs/ejclaw.log | tail -3
```
## Session Transcript Branching
@@ -62,7 +62,7 @@ for i, line in enumerate(lines):
```bash
# Check for recent timeouts
grep -E 'Container timeout|timed out' logs/nanoclaw.log | tail -10
grep -E 'Container timeout|timed out' logs/ejclaw.log | tail -10
# Check container log files for the timed-out container
ls -lt groups/*/logs/container-*.log | head -10
@@ -71,23 +71,23 @@ ls -lt groups/*/logs/container-*.log | head -10
cat groups/<group>/logs/container-<timestamp>.log
# Check if retries were scheduled and what happened
grep -E 'Scheduling retry|retry|Max retries' logs/nanoclaw.log | tail -10
grep -E 'Scheduling retry|retry|Max retries' logs/ejclaw.log | tail -10
```
## Agent Not Responding
```bash
# Check if messages are being received from WhatsApp
grep 'New messages' logs/nanoclaw.log | tail -10
grep 'New messages' logs/ejclaw.log | tail -10
# Check if messages are being processed (container spawned)
grep -E 'Processing messages|Spawning container' logs/nanoclaw.log | tail -10
grep -E 'Processing messages|Spawning container' logs/ejclaw.log | tail -10
# Check if messages are being piped to active container
grep -E 'Piped messages|sendMessage' logs/nanoclaw.log | tail -10
grep -E 'Piped messages|sendMessage' logs/ejclaw.log | tail -10
# Check the queue state — any active containers?
grep -E 'Starting container|Container active|concurrency limit' logs/nanoclaw.log | tail -10
grep -E 'Starting container|Container active|concurrency limit' logs/ejclaw.log | tail -10
# Check lastAgentTimestamp vs latest message timestamp
sqlite3 store/messages.db "SELECT chat_jid, MAX(timestamp) as latest FROM messages GROUP BY chat_jid ORDER BY latest DESC LIMIT 5;"
@@ -97,10 +97,10 @@ sqlite3 store/messages.db "SELECT chat_jid, MAX(timestamp) as latest FROM messag
```bash
# Check mount validation logs (shows on container spawn)
grep -E 'Mount validated|Mount.*REJECTED|mount' logs/nanoclaw.log | tail -10
grep -E 'Mount validated|Mount.*REJECTED|mount' logs/ejclaw.log | tail -10
# Verify the mount allowlist is readable
cat ~/.config/nanoclaw/mount-allowlist.json
cat ~/.config/ejclaw/mount-allowlist.json
# Check group's container_config in DB
sqlite3 store/messages.db "SELECT name, container_config FROM registered_groups;"
@@ -114,7 +114,7 @@ container run -i --rm --entrypoint ls nanoclaw-agent:latest /workspace/extra/
```bash
# Check if QR code was requested (means auth expired)
grep 'QR\|authentication required\|qr' logs/nanoclaw.log | tail -5
grep 'QR\|authentication required\|qr' logs/ejclaw.log | tail -5
# Check auth files exist
ls -la store/auth/
@@ -127,17 +127,17 @@ npm run auth
```bash
# Restart the service
launchctl kickstart -k gui/$(id -u)/com.nanoclaw
launchctl kickstart -k gui/$(id -u)/com.ejclaw
# View live logs
tail -f logs/nanoclaw.log
tail -f logs/ejclaw.log
# Stop the service (careful — running containers are detached, not killed)
launchctl bootout gui/$(id -u)/com.nanoclaw
launchctl bootout gui/$(id -u)/com.ejclaw
# Start the service
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.nanoclaw.plist
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.ejclaw.plist
# Rebuild after code changes
npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw
npm run build && launchctl kickstart -k gui/$(id -u)/com.ejclaw
```

View File

@@ -1,4 +1,4 @@
# NanoClaw Requirements
# EJClaw Requirements
Original requirements and design decisions from the project creator.
@@ -8,7 +8,7 @@ Original requirements and design decisions from the project creator.
This is a lightweight, secure alternative to OpenClaw (formerly ClawBot). That project became a monstrosity - 4-5 different processes running different gateways, endless configuration files, endless integrations. It's a security nightmare where agents don't run in isolated processes; there's all kinds of leaky workarounds trying to prevent them from accessing parts of the system they shouldn't. It's impossible for anyone to realistically understand the whole codebase. When you run it you're kind of just yoloing it.
NanoClaw gives you the core functionality without that mess.
EJClaw gives you the core functionality without that mess.
---
@@ -193,4 +193,4 @@ These are the creator's settings, stored here for reference:
## Project Name
**NanoClaw** - A reference to Clawdbot (now OpenClaw).
**EJClaw** - A reference to Clawdbot (now OpenClaw).

View File

@@ -1,4 +1,4 @@
# NanoClaw Security Model
# EJClaw Security Model
## Trust Model
@@ -23,7 +23,7 @@ This is the primary security boundary. Rather than relying on application-level
### 2. Mount Security
**External Allowlist** - Mount permissions stored at `~/.config/nanoclaw/mount-allowlist.json`, which is:
**External Allowlist** - Mount permissions stored at `~/.config/ejclaw/mount-allowlist.json`, which is:
- Outside project root
- Never mounted into containers
- Cannot be modified by agents

View File

@@ -1,4 +1,4 @@
# NanoClaw Specification
# EJClaw Specification
A personal Claude assistant with multi-channel support, persistent memory per conversation, scheduled tasks, and container-isolated agent execution.
@@ -314,12 +314,12 @@ nanoclaw/
│ └── ipc/ # Container IPC (messages/, tasks/)
├── logs/ # Runtime logs (gitignored)
│ ├── nanoclaw.log # Host stdout
│ └── nanoclaw.error.log # Host stderr
│ ├── ejclaw.log # Host stdout
│ └── ejclaw.error.log # Host stderr
│ # Note: Per-container logs are in groups/{folder}/logs/container-*.log
└── launchd/
└── com.nanoclaw.plist # macOS service configuration
└── com.ejclaw.plist # macOS service configuration
```
---
@@ -422,7 +422,7 @@ Files with `{{PLACEHOLDER}}` values need to be configured:
## Memory System
NanoClaw uses a hierarchical memory system based on CLAUDE.md files.
EJClaw uses a hierarchical memory system based on CLAUDE.md files.
### Memory Hierarchy
@@ -555,7 +555,7 @@ This allows the agent to understand the conversation context even if it wasn't m
## Scheduled Tasks
NanoClaw has a built-in scheduler that runs tasks as full agents in their group's context.
EJClaw has a built-in scheduler that runs tasks as full agents in their group's context.
### How Scheduling Works
@@ -616,7 +616,7 @@ From main channel:
## MCP Servers
### NanoClaw MCP (built-in)
### EJClaw MCP (built-in)
The `nanoclaw` MCP server is created dynamically per agent call with the current group's context.
@@ -636,12 +636,12 @@ The `nanoclaw` MCP server is created dynamically per agent call with the current
## Deployment
NanoClaw runs as a single macOS launchd service.
EJClaw runs as a single macOS launchd service.
### Startup Sequence
When NanoClaw starts, it:
1. **Ensures container runtime is running** - Automatically starts it if needed; kills orphaned NanoClaw containers from previous runs
When EJClaw starts, it:
1. **Ensures container runtime is running** - Automatically starts it if needed; kills orphaned EJClaw containers from previous runs
2. Initializes the SQLite database (migrates from JSON files if they exist)
3. Loads state from SQLite (registered groups, sessions, router state)
4. **Connects channels** — loops through registered channels, instantiates those with credentials, calls `connect()` on each
@@ -652,16 +652,16 @@ When NanoClaw starts, it:
- Recovers any unprocessed messages from before shutdown
- Starts the message polling loop
### Service: com.nanoclaw
### Service: com.ejclaw
**launchd/com.nanoclaw.plist:**
**launchd/com.ejclaw.plist:**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "...">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.nanoclaw</string>
<string>com.ejclaw</string>
<key>ProgramArguments</key>
<array>
<string>{{NODE_PATH}}</string>
@@ -683,9 +683,9 @@ When NanoClaw starts, it:
<string>Andy</string>
</dict>
<key>StandardOutPath</key>
<string>{{PROJECT_ROOT}}/logs/nanoclaw.log</string>
<string>{{PROJECT_ROOT}}/logs/ejclaw.log</string>
<key>StandardErrorPath</key>
<string>{{PROJECT_ROOT}}/logs/nanoclaw.error.log</string>
<string>{{PROJECT_ROOT}}/logs/ejclaw.error.log</string>
</dict>
</plist>
```
@@ -694,19 +694,19 @@ When NanoClaw starts, it:
```bash
# Install service
cp launchd/com.nanoclaw.plist ~/Library/LaunchAgents/
cp launchd/com.ejclaw.plist ~/Library/LaunchAgents/
# Start service
launchctl load ~/Library/LaunchAgents/com.nanoclaw.plist
launchctl load ~/Library/LaunchAgents/com.ejclaw.plist
# Stop service
launchctl unload ~/Library/LaunchAgents/com.nanoclaw.plist
launchctl unload ~/Library/LaunchAgents/com.ejclaw.plist
# Check status
launchctl list | grep nanoclaw
# View logs
tail -f logs/nanoclaw.log
tail -f logs/ejclaw.log
```
---
@@ -763,7 +763,7 @@ chmod 700 groups/
| Issue | Cause | Solution |
|-------|-------|----------|
| No response to messages | Service not running | Check `launchctl list | grep nanoclaw` |
| "Claude Code process exited with code 1" | Container runtime failed to start | Check logs; NanoClaw auto-starts container runtime but may fail |
| "Claude Code process exited with code 1" | Container runtime failed to start | Check logs; EJClaw auto-starts container runtime but may fail |
| "Claude Code process exited with code 1" | Session mount path wrong | Ensure mount is to `/home/node/.claude/` not `/root/.claude/` |
| Session not continuing | Session ID not saved | Check SQLite: `sqlite3 store/messages.db "SELECT * FROM sessions"` |
| Session not continuing | Mount path mismatch | Container user is `node` with HOME=/home/node; sessions must be at `/home/node/.claude/` |
@@ -772,8 +772,8 @@ chmod 700 groups/
### Log Location
- `logs/nanoclaw.log` - stdout
- `logs/nanoclaw.error.log` - stderr
- `logs/ejclaw.log` - stdout
- `logs/ejclaw.error.log` - stderr
### Debug Mode

View File

@@ -1,4 +1,4 @@
# NanoClaw Skills Architecture
# EJClaw Skills Architecture
## Core Principle
@@ -123,7 +123,7 @@ skills/
- Git's three-way merge uses context matching, so it works even if the user has moved code around — unlike line-number-based diffs that break immediately
- Auditable: `diff .nanoclaw/base/src/server.ts skills/add-whatsapp/modify/src/server.ts` shows exactly what the skill changes
- Deterministic: same three inputs always produce the same merge result
- Size is negligible since NanoClaw's core files are small
- Size is negligible since EJClaw's core files are small
### Intent Files
@@ -382,11 +382,11 @@ If tests fail and Level 2 can't resolve, restore from `.nanoclaw/backup/` and re
### The Problem
`git rerere` is local by default. But NanoClaw has thousands of users applying the same skill combinations. Every user hitting the same conflict and waiting for Claude Code to resolve it is wasteful.
`git rerere` is local by default. But EJClaw has thousands of users applying the same skill combinations. Every user hitting the same conflict and waiting for Claude Code to resolve it is wasteful.
### The Solution
NanoClaw maintains a verified resolution cache in `.nanoclaw/resolutions/` that ships with the project. This is the shared artifact — **not** `.git/rr-cache/`, which stays local.
EJClaw maintains a verified resolution cache in `.nanoclaw/resolutions/` that ships with the project. This is the shared artifact — **not** `.git/rr-cache/`, which stays local.
```
.nanoclaw/
@@ -588,7 +588,7 @@ There is no unrecoverable state.
## 10. Core Updates
Core updates must be as programmatic as possible. The NanoClaw team is responsible for ensuring updates apply cleanly to common skill combinations.
Core updates must be as programmatic as possible. The EJClaw team is responsible for ensuring updates apply cleanly to common skill combinations.
### Patches and Migrations
@@ -977,7 +977,7 @@ Each passing combination generates a verified resolution entry for the shared ca
### `.gitattributes`
Ship with NanoClaw to reduce noisy merge conflicts:
Ship with EJClaw to reduce noisy merge conflicts:
```
* text=auto

View File

@@ -1,8 +1,8 @@
# NanoClaw Skills Architecture
# EJClaw Skills Architecture
## What Skills Are For
NanoClaw's core is intentionally minimal. Skills are how users extend it: adding channels, integrations, cross-platform support, or replacing internals entirely. Examples: add Telegram alongside WhatsApp, switch from Apple Container to Docker, add Gmail integration, add voice message transcription. Each skill modifies the actual codebase, adding channel handlers, updating the message router, changing container configuration, and adding dependencies, rather than working through a plugin API or runtime hooks.
EJClaw's core is intentionally minimal. Skills are how users extend it: adding channels, integrations, cross-platform support, or replacing internals entirely. Examples: add Telegram alongside WhatsApp, switch from Apple Container to Docker, add Gmail integration, add voice message transcription. Each skill modifies the actual codebase, adding channel handlers, updating the message router, changing container configuration, and adding dependencies, rather than working through a plugin API or runtime hooks.
## Why This Architecture