Delete token-refresh.ts and credentials.json sync. Auth is now via CLAUDE_CODE_OAUTH_TOKEN in .env (1-year setup-token). No more auto-refresh loop or credentials.json dependency.
3.6 KiB
3.6 KiB
NanoClaw
Dual-agent AI assistant (Claude Code + Codex) over Discord. Based on qwibitai/nanoclaw.
Quick Context
Two systemd services (nanoclaw, nanoclaw-codex) share the same codebase but run with separate stores, data, and groups. Agents run as direct host processes (no containers). Claude Code uses the Agent SDK; Codex uses codex app-server via JSON-RPC. Auth via CLAUDE_CODE_OAUTH_TOKEN in .env (1-year token from claude setup-token).
Key Files
| File | Purpose |
|---|---|
src/index.ts |
Orchestrator: state, message loop, agent invocation |
src/agent-runner.ts |
Spawns agent processes, manages env/sessions/skills |
src/channels/discord.ts |
Discord channel (8s typing refresh, Groq/OpenAI Whisper transcription) |
src/ipc.ts |
IPC watcher and task processing |
src/router.ts |
Message formatting and outbound routing |
src/config.ts |
Trigger pattern, paths, intervals |
src/task-scheduler.ts |
Runs scheduled tasks |
src/db.ts |
SQLite operations |
container/agent-runner/ |
Claude Code runner (Agent SDK) |
container/codex-runner/ |
Codex runner (app-server JSON-RPC, streaming, turn/steer) |
groups/{name}/CLAUDE.md |
Per-group memory (isolated) |
Skills
| Skill | When to Use |
|---|---|
/setup |
First-time installation, authentication, service configuration |
/customize |
Adding channels, integrations, changing behavior |
/debug |
Agent issues, logs, troubleshooting |
/update-nanoclaw |
Bring upstream NanoClaw updates into a customized install |
/qodo-pr-resolver |
Fetch and fix Qodo PR review issues interactively or in batch |
/get-qodo-rules |
Load org- and repo-level coding rules from Qodo before code tasks |
Development
Run commands directly—don't tell the user to run them.
npm run build # Build main project
npm run build:runners # Install + build both runners
npm run dev # Dev mode with hot reload
Service management (Linux):
systemctl --user restart nanoclaw nanoclaw-codex # Restart both
systemctl --user status nanoclaw # Check status
journalctl --user -u nanoclaw -f # Follow logs
Deploy to server: scp dist/*.js clone-ej@100.64.185.108:~/nanoclaw/dist/
Dual-Service Architecture
nanoclaw.service— Claude Code bot (@claude), usesstore/,data/,groups/nanoclaw-codex.service— Codex bot (@codex), usesstore-codex/,data-codex/,groups-codex/- Both share the same codebase (
dist/index.js), differentiated by env vars (NANOCLAW_STORE_DIR, etc.) - Channel registration is per-service DB (
registered_groupstable)
Codex App-Server
Codex runner uses codex app-server JSON-RPC (not codex exec):
thread/start/thread/resumefor session persistence (threadId-based)turn/startfor streaming responses (item/agentMessage/delta)turn/steerfor mid-execution message injection (IPC polling during turn)approvalPolicy: "never"+sandbox: "danger-full-access"for bypass- Per-group: model (
CODEX_MODEL), effort (CODEX_EFFORT), MCP servers viaconfig.toml
Voice Transcription
Audio attachments in Discord are transcribed via Groq Whisper (primary) or OpenAI Whisper (fallback):
GROQ_API_KEY— Groqwhisper-large-v3-turbo, ~200x real-time, free tier (console.groq.com)OPENAI_API_KEY— OpenAIwhisper-1, fallback if Groq key not set- Shared file cache (
cache/transcriptions/) deduplicates across both services .pendingfile coordination prevents duplicate API calls