Remove 9 inherited skills (Qodo, update-ejclaw, add-* addons, update-skills) and restart-ejclaw-stack.sh that came from the nanoclaw fork and are no longer used.
4.3 KiB
EJClaw
Dual-agent AI assistant (Claude Code + Codex) over Discord. Originally derived from qwibitai/nanoclaw.
Quick Context
Single unified service (ejclaw) manages three Discord bots (Claude, Codex-main, Codex-review) in one process. Owner/reviewer agent types are configurable via OWNER_AGENT_TYPE and REVIEWER_AGENT_TYPE in .env. Claude Code uses the Agent SDK; Codex uses the Codex SDK (codex exec). 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 |
runners/agent-runner/ |
Claude Code runner (Agent SDK) |
runners/codex-runner/ |
Codex runner (SDK, codex exec wrapper) |
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 |
Development
Run commands directly—don't tell the user to run them.
bun run build # Build main project
bun run build:runners # Install + build both runners
bun run build:container # Rebuild reviewer Docker image
bun run dev # Dev mode with hot reload
Service management (Linux):
systemctl --user restart ejclaw # Restart unified service
systemctl --user status ejclaw # Check status
journalctl --user -u ejclaw -f # Follow logs
Deploy:
bun run deploy
Service Stack Architecture
Single unified service manages all three Discord bots in one process:
ejclaw.service— Single unified process- Discord bots:
DISCORD_BOT_TOKEN(Claude),DISCORD_CODEX_BOT_TOKEN(Codex-main),DISCORD_REVIEW_BOT_TOKEN(Codex-review) - Paired review: owner (
OWNER_AGENT_TYPE, default: codex) ↔ reviewer (REVIEWER_AGENT_TYPE, default: claude-code) - Reviewer fallback: Claude 429/한도초과 시 codex-review로 자동 핸드오프
- Shared dirs:
store/,groups/,data/ - SQLite WAL mode +
busy_timeout=5000for concurrent access
Debugging Paths
Unified DB + directories (both services share store/, groups/, data/):
| 항목 | 경로 |
|---|---|
| DB | store/messages.db (공유, WAL 모드) |
| 서비스 로그 | journalctl --user -u ejclaw -f 또는 logs/ejclaw.log |
| 그룹별 로그 | groups/{name}/logs/ (공유 채널은 양쪽 봇 로그가 같은 폴더) |
| Claude 세션 | data/sessions/{name}/.claude/ |
| Codex 세션 | data/sessions/{name}/.codex/ |
| Claude 플랫폼 규칙 | prompts/claude-platform.md |
| Codex 플랫폼 규칙 | prompts/codex-platform.md |
| Claude 글로벌 메모리 | groups/global/CLAUDE.md |
Codex SDK
Codex runner uses @openai/codex-sdk (wraps codex exec):
codex.startThread()/codex.resumeThread()for session persistencethread.run(input)for single-shot turn execution (completes all work before returning)approvalPolicy: "never"+sandboxMode: "danger-full-access"for bypass- Per-group: model (
CODEX_MODEL), effort (CODEX_EFFORT), MCP servers viaconfig.toml CODEX_HOMEset to per-group session dir, readsAGENTS.mdfrom there + CWD
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