Files
EJClaw/CLAUDE.md

4.4 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 (owner, reviewer, arbiter) in one process. Agent types behind each role remain configurable via OWNER_AGENT_TYPE, REVIEWER_AGENT_TYPE, and ARBITER_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_OWNER_BOT_TOKEN (owner), DISCORD_REVIEWER_BOT_TOKEN (reviewer), DISCORD_ARBITER_BOT_TOKEN (arbiter)
  • Old service-based token names are no longer accepted; migrate them to the canonical role-based keys above before starting the service
  • Paired review: owner (OWNER_AGENT_TYPE, default: codex) ↔ reviewer (REVIEWER_AGENT_TYPE, default: claude-code)
  • Provider fallback is internal routing only — visible Discord bots stay owner/reviewer/arbiter fixed
  • Shared dirs: store/, groups/, data/
  • SQLite WAL mode + busy_timeout=5000 for 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 persistence
  • thread.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 via config.toml
  • CODEX_HOME set to per-group session dir, reads AGENTS.md from there + CWD

Voice Transcription

Audio attachments in Discord are transcribed via Groq Whisper (primary) or OpenAI Whisper (fallback):

  • GROQ_API_KEY — Groq whisper-large-v3-turbo, ~200x real-time, free tier (console.groq.com)
  • OPENAI_API_KEY — OpenAI whisper-1, fallback if Groq key not set
  • Shared file cache (cache/transcriptions/) deduplicates across both services
  • .pending file coordination prevents duplicate API calls