Discord-Claude Gateway

An event-driven agent runtime that connects Discord to Claude via the Claude Agent SDK. Inspired by OpenClaw's architecture — a gateway in front of an agent runtime with markdown-based personality, memory, and scheduled behaviors.

How It Works

Discord Users ──► Discord Bot ──► Event Queue ──► Agent Runtime ──► Claude Agent SDK
                                      ▲                                    │
                  Heartbeats ──────────┤                                    │
                  Cron Jobs ───────────┤              ┌─────────────────────┘
                  Hooks ───────────────┘              ▼
                                              Markdown Config Files
                                         (soul, identity, memory, 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 Agent SDK. The agent can write back to memory.md to persist facts across sessions.

Prerequisites

  • Node.js 18+
  • Claude Code CLIInstall Claude Code and sign in with your subscription
  • Discord Bot TokenCreate a bot with Message Content Intent enabled

Quick Start

# Install dependencies
npm install

# Make sure Claude Code CLI is installed and you're signed in
claude --version

# Set required environment variables
export DISCORD_BOT_TOKEN=your-discord-bot-token

# Create config directory with persona files
mkdir config

Create at minimum config/soul.md and config/identity.md:

# config/identity.md
echo "# Identity

- **Name:** Aetheel
- **Vibe:** Helpful, sharp, slightly witty
- **Emoji:** ⚡" > config/identity.md

# config/soul.md
echo "# Soul

Be genuinely helpful. Have opinions. Be resourceful before asking.
Earn trust through competence." > config/soul.md
# Start the gateway
npm run dev

Configuration

All settings are via environment variables:

Variable Required Default Description
DISCORD_BOT_TOKEN Yes Discord bot token
CLAUDE_CLI_PATH No claude Path to the Claude Code CLI binary
ALLOWED_TOOLS No Read,Write,Edit,Glob,Grep,WebSearch,WebFetch Comma-separated Claude Code tools
PERMISSION_MODE No bypassPermissions Claude Code permission mode
QUERY_TIMEOUT_MS No 120000 Query timeout in milliseconds
MAX_CONCURRENT_QUERIES No 5 Max simultaneous Claude queries
CONFIG_DIR No ./config Path to markdown config directory
MAX_QUEUE_DEPTH No 100 Max events in the queue
OUTPUT_CHANNEL_ID No Discord channel for heartbeat/cron output

Markdown Config Files

Place these in your CONFIG_DIR (default: ./config/). The gateway reads them fresh on every event — edit them anytime, no restart needed (except agents.md and heartbeat.md which are parsed at startup for cron/heartbeat timers).

File Purpose Required
CLAUDE.md Persona: identity, personality, user context, tools — all in one Yes
agents.md Operating rules, cron jobs, hooks (parsed by gateway) No
memory.md Long-term memory (agent can write to this) No (auto-created)
heartbeat.md Proactive check definitions (parsed by gateway) No

Missing optional files are created with default headers on first run.

Heartbeat Config (heartbeat.md)

Define proactive checks the agent runs on a timer:

## check-email
Interval: 1800
Instruction: Check my inbox for anything urgent. If nothing, reply HEARTBEAT_OK.

## check-calendar
Interval: 3600
Instruction: Review upcoming calendar events in the next 24 hours.

Interval is in seconds (minimum 60).

Cron Jobs (in agents.md)

Define scheduled tasks with cron expressions:

## Cron Jobs

### morning-briefing
Cron: 0 9 * * *
Instruction: Good morning! Check email, review today's calendar, and give me a brief summary.

### weekly-review
Cron: 0 15 * * 1
Instruction: Review the week's calendar and flag any conflicts.

Hooks (in agents.md)

Define lifecycle hook instructions:

## Hooks

### startup
Instruction: Read memory.md and greet the user.

### shutdown
Instruction: Save any important context to memory.md before shutting down.

Discord Commands

Command Description
@bot <message> Send a prompt by mentioning the bot
/claude <prompt> Send a prompt via slash command
/claude-reset Reset the conversation session in the current channel

Architecture

The system has 5 input types (inspired by OpenClaw):

  1. Messages — Discord mentions and slash commands
  2. Heartbeats — Timer-based proactive checks
  3. Cron Jobs — Scheduled events with cron expressions
  4. Hooks — Internal lifecycle triggers (startup, shutdown, agent_begin, agent_stop)
  5. Webhooks — External system events (planned)

All inputs enter a unified FIFO event queue → processed sequentially by the agent runtime → state persists to markdown files → loop continues.

Project Structure

src/
├── index.ts                  # Entry point
├── gateway-core.ts           # Main orchestrator
├── config.ts                 # Environment variable loader
├── discord-bot.ts            # Discord.js wrapper
├── event-queue.ts            # Unified FIFO event queue
├── agent-runtime.ts          # Core processing engine
├── markdown-config-loader.ts # Reads config files from disk
├── system-prompt-assembler.ts# Assembles system prompt from configs
├── session-manager.ts        # Channel-to-session bindings
├── channel-queue.ts          # Per-channel sequential processing
├── response-formatter.ts     # Message splitting for Discord's 2000 char limit
├── error-formatter.ts        # Safe error formatting
├── heartbeat-scheduler.ts    # Recurring timer events
├── cron-scheduler.ts         # Cron-expression scheduled events
├── hook-manager.ts           # Lifecycle hook events
├── bootstrap-manager.ts      # First-run file validation/creation
└── shutdown-handler.ts       # Graceful SIGTERM/SIGINT handling

Development

# Run tests
npm test

# Run in dev mode
npm run dev

# Build
npm run build

# Start production
npm start

Claude Code CLI vs API Key

This gateway uses the Claude Code CLI (claude -p) instead of the Anthropic API directly. This means:

  • You use your existing Claude Code subscription — no separate API key needed
  • Just sign in with claude in your terminal and you're good to go
  • The gateway shells out to claude -p "prompt" --output-format json for each query
  • Set CLAUDE_CLI_PATH if claude isn't in your PATH

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%