tanmay11k 453389f55c feat: add pluggable multi-CLI backend system
Implement BackendAdapter interface with four CLI backends:
- ClaudeCodeBackend (extracted from AgentRuntime)
- CodexBackend (OpenAI Codex CLI)
- GeminiBackend (Google Gemini CLI)
- OpenCodeBackend (OpenCode CLI)

Add BackendRegistry for resolution/creation via AGENT_BACKEND env var.
Refactor AgentRuntime to delegate to BackendAdapter instead of
hardcoding Claude CLI. Update GatewayConfig with new env vars
(AGENT_BACKEND, BACKEND_CLI_PATH, BACKEND_MODEL, BACKEND_MAX_TURNS).

Includes 10 property-based test files and unit tests for edge cases.
2026-02-22 23:41:30 -05:00

Aetheel — Discord-Claude Gateway

An event-driven AI agent runtime that connects Discord to Claude Code CLI. Inspired by OpenClaw's architecture — a gateway in front of an agent runtime with markdown-based personality, memory, scheduled behaviors, and proactive messaging.

How It Works

Discord Users ──► Discord Bot ──► Event Queue ──► Agent Runtime ──► Claude Code CLI
                                      ▲                                    │
                  Heartbeats ──────────┤                                    │
                  Cron Jobs ───────────┤              ┌─────────────────────┘
                  Hooks ───────────────┘              ▼
                  IPC Watcher ─────────────    Markdown Config Files
                                            (CLAUDE.md, memory.md, etc.)

All inputs — Discord messages, heartbeat timers, cron jobs, lifecycle hooks — enter a unified event queue. The agent runtime reads your markdown config files fresh on each event, assembles a dynamic system prompt, and calls the Claude Code CLI. The agent can write back to memory.md to persist facts across sessions, and send proactive messages via the IPC system.

Uses your existing Claude Code subscription — no API key needed.

Prerequisites

  • Node.js 18+
  • Claude Code CLI installed and signed in (npm install -g @anthropic-ai/claude-code && claude)
  • A Discord bot token (create one here) with Message Content Intent enabled

Quick Start

git clone <your-repo-url>
cd aetheel-2
npm install
cp .env.example .env   # Edit with your Discord bot token
mkdir -p config
# Create config/CLAUDE.md with your persona (see Setup section)
npm run dev

Or run the interactive setup:

bash scripts/setup.sh

Configuration

Environment Variables

Create a .env file in the project root (auto-loaded via dotenv):

Variable Required Default Description
DISCORD_BOT_TOKEN Yes Discord bot token
OUTPUT_CHANNEL_ID No Discord channel for heartbeat/cron/hook output
CLAUDE_CLI_PATH No claude Path to the Claude Code CLI binary
CONFIG_DIR No ./config Path to markdown config directory
ALLOWED_TOOLS No Read,Write,Edit,Glob,Grep,WebSearch,WebFetch Comma-separated tools the agent can use
PERMISSION_MODE No bypassPermissions Claude Code permission mode
QUERY_TIMEOUT_MS No 120000 Max time per query (ms)
MAX_CONCURRENT_QUERIES No 5 Max simultaneous queries
MAX_QUEUE_DEPTH No 100 Max events in the queue
IDLE_SESSION_TIMEOUT_MS No 1800000 Session idle timeout (30 min)
LOG_LEVEL No info Log level: debug, info, warn, error

Markdown Config Files

Place these in CONFIG_DIR (default: ./config/):

File Purpose Required
CLAUDE.md Persona: identity, personality, user context, tools Yes
agents.md Operating rules, cron jobs, hooks (parsed at startup) No
memory.md Long-term memory (agent-writable) No (auto-created)
heartbeat.md Proactive check definitions (parsed at startup) No

The gateway reads CLAUDE.md and memory.md fresh on every event — edit them anytime. agents.md and heartbeat.md are parsed at startup for timers, so restart after editing those.

Skills

Drop skill files into config/skills/{name}/SKILL.md and they're automatically loaded into the system prompt:

config/skills/
├── web-research/
│   └── SKILL.md    → "When asked to research, use WebSearch..."
└── code-review/
    └── SKILL.md    → "When reviewing code, focus on..."

Features

Discord Integration

  • Mention the bot (@Aetheel hi) or use /claude slash command
  • /claude-reset to start a fresh conversation
  • Responses auto-split at 2000 chars with code block preservation
  • Typing indicators while processing

Session Management

  • Per-channel conversation sessions with Claude Code CLI --resume
  • Sessions persist to config/sessions.json (survive restarts)
  • Auto-cleanup of idle sessions after 30 minutes (configurable)

Heartbeats (Timer Events)

Define in config/heartbeat.md:

## check-email
Interval: 1800
Instruction: Check my inbox for anything urgent.

Cron Jobs (Scheduled Events)

Define in config/agents.md:

## Cron Jobs

### morning-briefing
Cron: 0 8 * * *
Instruction: Good morning! Search for the latest AI news and post a summary.

Lifecycle Hooks

Define in config/agents.md:

## Hooks

### startup
Instruction: Say hello, you just came online.

### shutdown
Instruction: Save important context to memory.md.

Proactive Messaging (IPC)

The agent can send messages to any Discord channel by writing JSON files to config/ipc/outbound/:

{"channelId": "123456789", "text": "Hey, found something interesting!"}

The gateway polls every 2 seconds and delivers the message.

Message History

All inbound/outbound messages stored per channel in config/messages/{channelId}.json. Max 100 messages per channel, auto-trimmed.

Conversation Archiving

Every exchange saved as readable markdown in config/conversations/{channelId}/{YYYY-MM-DD}.md.

Retry with Backoff

Claude CLI calls retry 3 times with exponential backoff (5s, 10s, 20s) on transient errors. Session corruption errors fail immediately.

Structured Logging

Pino-based structured JSON logging. Set LOG_LEVEL=debug for verbose output. Pretty-printed in dev, JSON in production (NODE_ENV=production).

Deployment

sudo bash scripts/setup.sh  # Creates .env, config/, and systemd service

Or manually:

sudo cp scripts/aetheel.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable aetheel
sudo systemctl start aetheel

# View logs
sudo journalctl -u aetheel -f

PM2

npm run build
pm2 start dist/index.js --name aetheel
pm2 save

Dev mode

npm run dev

Project Structure

src/
├── index.ts                   # Entry point (loads .env)
├── gateway-core.ts            # Main orchestrator
├── config.ts                  # Environment variable loader
├── logger.ts                  # Pino structured logger
├── discord-bot.ts             # Discord.js wrapper
├── event-queue.ts             # Unified FIFO event queue
├── agent-runtime.ts           # Core engine: reads configs, spawns CLI, streams output
├── markdown-config-loader.ts  # Reads CLAUDE.md, agents.md, memory.md
├── system-prompt-assembler.ts # Assembles system prompt with sections
├── skills-loader.ts           # Loads skills from config/skills/*/SKILL.md
├── session-manager.ts         # Channel → session ID (persisted, idle cleanup)
├── message-history.ts         # Per-channel message storage
├── conversation-archiver.ts   # Markdown conversation logs
├── ipc-watcher.ts             # Polls ipc/outbound/ for proactive messages
├── response-formatter.ts      # Splits long text for Discord's 2000 char limit
├── error-formatter.ts         # Sanitizes errors (strips keys, paths, stacks)
├── heartbeat-scheduler.ts     # Recurring timer events
├── cron-scheduler.ts          # node-cron scheduled events
├── hook-manager.ts            # Lifecycle hooks
├── bootstrap-manager.ts       # First-run file validation/creation
├── channel-queue.ts           # Per-channel sequential processing
└── shutdown-handler.ts        # Graceful SIGTERM/SIGINT handling

config/                        # Agent workspace (gitignored)
├── CLAUDE.md                  # Persona
├── agents.md                  # Rules, cron, hooks
├── memory.md                  # Long-term memory (agent-writable)
├── heartbeat.md               # Heartbeat checks
├── sessions.json              # Session persistence (auto)
├── messages/                  # Message history (auto)
├── conversations/             # Conversation archives (auto)
├── ipc/outbound/              # Proactive message queue (auto)
├── skills/                    # Skill definitions
└── news/                      # Example: agent-created content

Development

npm test          # Run tests (85 passing)
npm run dev       # Dev mode with tsx
npm run build     # Compile TypeScript
npm start         # Run compiled JS

License

MIT

Description
No description provided
Readme 870 KiB
Languages
TypeScript 70.9%
JavaScript 13.8%
CSS 12.1%
HTML 1.7%
Shell 1.5%