Discord AI Bot Development (Slimy.ai)
Development assistant for working with Slimy.ai, a feature-rich Discord bot built with Discord.js v14 that provides AI-powered chat, memory management, personality modes, and game-specific features (Super Snail stats analysis via GPT-4 Vision).
Project Architecture
Core Structure
**Entry Point**: `index.js`
Singleton lock mechanism (`.slimy-singleton.lock`) prevents duplicate instancesInitializes database connection via `lib/database.js`Auto-loads slash commands from `commands/` directoryAttaches event handlers from `handlers/` directoryMaintains global bot statistics in `global.botStats`**Command System**
Commands auto-loaded from `commands/` directoryEach command exports `{ data: SlashCommandBuilder, execute: async function }`Stored in `client.commands` CollectionDispatcher in `index.js` handles `InteractionCreate` events**Handler System**
`handlers/mention.js`: Processes @bot mentions and routes to chat`handlers/snail-auto-detect.js`: Auto-detects Super Snail screenshots in messagesHandlers loaded gracefully (bot continues if handlers fail)Data Layer
**Dual Storage System**
1. **JSON File Storage** (`lib/memory.js`)
- Uses `data_store.json` with file locking via `proper-lockfile`
- Stores: consent preferences, memos, channel mode configurations
- Atomic writes with temp file + rename pattern
- UUID-based IDs with race condition prevention
2. **MySQL Database** (`lib/database.js`)
- Connection pooling via `mysql2/promise`
- Optional (bot works without DB configured)
- Stores: users, guilds, memories, snail stats, image generation logs, personality metrics
- Auto-creates tables on initialization
- Check `database.isConfigured()` before using DB features
AI Integration
**OpenAI Client** (`lib/openai.js`)
Shared OpenAI instance for chat, vision, and image generation**Personality Engine** (`lib/personality-engine.js`)
Parses `bot-personality.md` configuration fileBuilds dynamic system prompts based on mode/rating/user historySupports traits, catchphrases, tone guidelines, context behaviorsTracks usage metrics and adaptation signals**Persona System** (`lib/persona.js`)
Predefined personas: mentor, partner, mirror, operator, personality, no_personalityAuto-detection based on user message contentCan be overridden by channel mode configuration**Mode System** (`lib/modes.js`)
Channel/category/thread-level mode configurationModes: admin, chat, personality, no_personality, super_snail, rating_pg13, rating_unratedHierarchical resolution: thread → channel → categoryOperations: view, merge, remove, replace**Vision & Image Features**
`lib/vision.js`: General-purpose GPT-4 Vision API wrapper`lib/snail-vision.js`: Super Snail specific stat extraction`lib/auto-image.js`: DALL-E image generation with intent detection`lib/image-intent.js`: Detects image generation intent in user messages**Google Sheets Integration**
`lib/sheets.js`, `lib/sheets-creator.js`, `lib/sheets-drive-create.js`Per-user Google Sheets for Super Snail stat trackingService account authentication via `google-service-account.json`Auto-creates sheets on first use with proper permissionsDevelopment Workflow
Running the Bot
```bash
Start the bot
npm start
or
node index.js
```
Command Deployment
```bash
Deploy slash commands to Discord
npm run deploy
or
node deploy-commands.js
```
**Deployment Strategy:**
Set `DISCORD_GUILD_ID` for guild-specific deployment (instant updates for testing)Leave `DISCORD_GUILD_ID` blank for global deployment (~1 hour to propagate)Testing
```bash
Run memory persistence tests
npm run test:memory
or
node tests/memory-simple.test.js
```
**Test Coverage:**
Consent managementMemo CRUD operationsConcurrent access patternsData persistence verificationAdding a New Command
1. Create `commands/yourcommand.js` with this structure:
```javascript
const { SlashCommandBuilder } = require('discord.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('yourcommand')
.setDescription('Description'),
async execute(interaction) {
// Command logic
},
};
```
2. Deploy commands:
```bash
npm run deploy
```
3. Restart the bot:
```bash
npm start
```
Modifying Personality
1. Edit `bot-personality.md` (markdown format)
2. Reload without restart:
```
/personality-config reload
```
3. Test in channel with personality mode enabled
Database Schema Changes
1. Modify `createTables()` in `lib/database.js`
2. Drop/recreate tables or run manual migration
3. Update query methods as needed
4. Test with `database.testConnection()`
Key Commands Reference
**Memory Commands:**
`/remember <note>` - Store a memory (requires consent)`/recall [limit]` - List stored memories`/forget <id>` - Delete a specific memory`/forget all` - Delete all memories in current context`/consent set <allow>` - Enable/disable memory storage`/consent status` - Check current consent status**Chat Commands:**
`/chat <message> [reset]` - Chat with AI (maintains conversation history)@mention the bot - Alternative chat interface (same backend)**Mode Configuration:**
`/mode view` - Show current channel modes`/mode set <modes>` - Configure channel behavior`/mode clear` - Remove all mode configurations**Super Snail Features:**
`/snail <image>` - Analyze stats from screenshot (GPT-4 Vision)Auto-detection of snail screenshots in channels**Utility Commands:**
`/diag` - Bot diagnostics (uptime, errors, memory usage)`/export memories` - Export memories to JSON file`/personality-config reload` - Reload bot personality configuration`/dream <prompt>` - Generate images via DALL-ECritical Patterns
Error Handling
All async operations must use try/catch with fallbacksCheck `database.isConfigured()` before database operationsDefer interactions for long-running operationsLog errors to `global.botStats.errors`Consent Management
Memory operations require user consent per guildGlobal consent stored in database (`users.global_consent`)Sheets consent stored separately (`user_guilds.sheets_consent`)Always check consent before storing user dataFile Locking
Use `proper-lockfile` for concurrent access to `data_store.json`Atomic writes: write to `.tmp` file, then renameStale lock detection (10 second timeout)Conversation History
In-memory history per (channelId, userId) keyLimited to MAX_TURNS * 2 messages (16 total)No persistence - resets on bot restartEnvironment Variables
**Required:**
`DISCORD_TOKEN` - Bot token`DISCORD_CLIENT_ID` - Application ID**Optional:**
`DISCORD_GUILD_ID` - For guild-specific command deployment`OPENAI_API_KEY` - For AI features`VISION_MODEL` - GPT-4 Vision model (default: gpt-4o)`OPENAI_MODEL` - Chat model (default: gpt-4o)`DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASSWORD`, `DB_NAME` - MySQL config`GOOGLE_APPLICATION_CREDENTIALS` - Path to service account JSON`GOOGLE_SERVICE_ACCOUNT_JSON` - Inline service account JSON`SHEETS_PARENT_FOLDER_ID` - Google Drive folder for sheetsRecent Bug Fixes (as of 2025-10-09)
1. Memory persistence race conditions fixed with file locking
2. UUID-based memo IDs (replaced timestamp-based approach)
3. Proper async/await usage in save operations
4. Duplicate command loading prevention
5. Channel mode filter bug (DM notes appearing in guild queries)
Instructions for Claude Code
When working with this codebase:
1. **Before modifying commands:** Always check if the command already exists in `commands/` directory
2. **Database operations:** Always check `database.isConfigured()` before attempting DB operations
3. **Memory operations:** Verify consent before storing user data
4. **File operations:** Use proper-lockfile for concurrent access to JSON files
5. **Error handling:** Wrap all async operations in try/catch blocks
6. **Testing:** Run memory tests after modifying storage logic
7. **Deployment:** Use guild-specific deployment for testing, global for production
8. **Personality changes:** Use `/personality-config reload` instead of restarting bot
9. **Code style:** Follow existing patterns in commands and handlers
10. **Security:** Never commit API keys or service account credentials
When adding new features:
Check if database is required or if JSON storage sufficesConsider consent requirements for user data storageAdd appropriate error handling and loggingTest in isolated guild before global deploymentUpdate this CLAUDE.md file if adding new architectural patterns