# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Telegram bot built with TypeScript and [Telegraf](https://telegraf.js.org/). Uses Markov chains with trigrams to generate sentences from learned messages. Each chat has its own isolated Markov chain, creating unique "personalities" per group. ## Commands ```bash npm run dev # Development with hot-reload (tsx watch) npm run build # Compile TypeScript to dist/ npm start # Run production build docker compose up -d --build # Docker deployment ``` ## Architecture ``` src/ ├── index.ts # Bot entry point, commands, message handling ├── markov.ts # Markov chain with trigram support └── database.ts # SQLite persistence layer ``` **Data flow:** 1. Message received → `chain.learn(text)` → SQLite 2. Trigger check (reply/mention/random) 3. If triggered → `chain.generate()` → reply **Per-chat isolation:** - Each chat has separate Markov chain data - Each chat has its own response probability setting - In-memory cache (`chains` Map) loaded lazily from DB ## Key Implementation Details ### Markov Chain (markov.ts) - Uses **trigrams** (order=2): "word1 word2" → "word3" - Better grammatical coherence than bigrams - Weighted random selection based on frequency - Generates sentences up to 20 words ### Database (database.ts) - SQLite with `better-sqlite3` (synchronous API) - Three tables: `chat_settings`, `markov_transitions`, `markov_starts` - Transactions for atomic updates - Automatic cleanup every 24h ### Cleanup Mechanism ```typescript const MAX_TRANSITIONS_PER_CHAT = 10000; // Upper limit const MIN_TRANSITION_COUNT = 2; // Remove rare entries const MIN_TRANSITIONS_TO_CLEANUP = 100; // Protect new chats ``` ### Response Triggers 1. Reply to bot's message → always respond 2. @username mention → always respond 3. Random probability (default 10%) in groups 4. Always respond in private chats ## Environment - `BOT_TOKEN` - Telegram bot token (required) - Database: `data/ulfbot.db` (auto-created) ## Docker - Uses `node:20-slim` for better-sqlite3 compatibility - Volume `ulfbot-data` mounts to `/app/data` - Build locally: `npm run build` then `docker compose up -d --build` ## Common Modifications **Change response probability default:** ```typescript // database.ts return { probability: (row?.probability ?? 10) }; // Change default ``` **Change cleanup interval:** ```typescript // index.ts const CLEANUP_INTERVAL_MS = 24 * 60 * 60 * 1000; // Currently 24h ``` **Change Markov order (affects grammar quality):** ```typescript // markov.ts constructor(order: number = 2) // Higher = better grammar, needs more data ```