Files
comfy-discord-web/CLAUDE.md
Khoa (Revenovich) Tran Gia 1ed3c9ec4b Initial commit — ComfyUI Discord bot + web UI
Full source for the-third-rev: Discord bot (discord.py), FastAPI web UI
(React/TS/Vite/Tailwind), ComfyUI integration, generation history DB,
preset manager, workflow inspector, and all supporting modules.

Excluded from tracking: .env, invite_tokens.json, *.db (SQLite),
current-workflow-changes.json, user_settings/, presets/, logs/,
web-static/ (build output), frontend/node_modules/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 09:55:48 +07:00

9.0 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is a Discord bot that integrates with ComfyUI to generate AI images and videos. Users interact via Discord commands, which queue generation requests that execute on a ComfyUI server.

Architecture

File Structure

The codebase is organized into focused modules for maintainability:

the-third-rev/
├── config.py              # Configuration and constants
├── job_queue.py               # Job queue system (SerialJobQueue)
├── workflow_manager.py    # Workflow manipulation logic
├── workflow_state.py      # Runtime workflow state management
├── discord_utils.py       # Discord helpers and decorators
├── commands/              # Command handlers (organized by functionality)
│   ├── __init__.py        # Command registration
│   ├── generation.py      # generate, workflow-gen commands
│   ├── workflow.py        # workflow-load command
│   ├── upload.py          # upload command
│   ├── history.py         # history, get-history commands
│   └── workflow_changes.py # get/set workflow changes commands
├── bot.py                 # Main bot entry point (~150 lines)
└── comfy_client.py       # ComfyUI API client (~650 lines)

Core Components

  • bot.py: Minimal Discord bot entry point. Loads configuration, creates dependencies, and registers commands. No command logic here.
  • comfy_client.py: Async client wrapping ComfyUI's REST and WebSocket APIs. Dependencies (WorkflowManager, WorkflowStateManager) are injected via constructor.
  • config.py: Centralized configuration with BotConfig.from_env() for loading environment variables and constants.
  • job_queue.py: SerialJobQueue ensuring generation requests execute sequentially, preventing ComfyUI server overload.
  • workflow_manager.py: WorkflowManager class handling workflow template storage and node manipulation (finding/replacing prompts, seeds, etc).
  • workflow_state.py: WorkflowStateManager class managing runtime workflow changes (prompt, negative_prompt, input_image) in memory with optional file persistence.
  • discord_utils.py: Reusable Discord utilities including @require_comfy_client decorator, argument parsing, and the UploadView component.
  • commands/: Command handlers organized by functionality. Each module exports a setup_*_commands(bot, config) function.

Key Architectural Patterns

  1. Dependency Injection: ComfyClient receives WorkflowManager and WorkflowStateManager as constructor parameters, eliminating tight coupling to file-based state.

  2. Job Queue System: All generation requests are queued through SerialJobQueue in job_queue.py. Jobs execute serially with a worker loop that catches and logs exceptions without crashing the bot.

  3. Workflow System: The bot uses two modes:

    • Prompt mode: Simple prompt + negative_prompt (requires workflow template with KSampler node)
    • Workflow mode: Full workflow JSON with dynamic modifications from WorkflowStateManager
  4. Workflow Modification Flow:

    • Load workflow template via bot.comfy.set_workflow() or bot.comfy.load_workflow_from_file()
    • Runtime changes (prompt, negative_prompt, input_image) stored in WorkflowStateManager
    • At generation time, WorkflowManager methods locate nodes by class_type and title metadata, then inject values
    • Seeds are randomized automatically via workflow_manager.find_and_replace_seed()
  5. Command Registration: Commands are registered via commands.register_all_commands(bot, config) which calls individual setup_*_commands() functions from each command module.

  6. Configuration Management: All configuration loaded via BotConfig.from_env() in config.py. Constants (command prefixes, error messages, limits) centralized in config.py.

  7. History Management: ComfyClient maintains a bounded deque of recent generations (configurable via history_limit) for retrieval via ttr!get-history.

Environment Variables

Required in .env:

  • DISCORD_BOT_TOKEN: Discord bot authentication token
  • COMFY_SERVER: ComfyUI server address (e.g., localhost:8188 or example.com:8188)

Optional:

  • WORKFLOW_FILE: Path to JSON workflow file to load at startup
  • COMFY_HISTORY_LIMIT: Number of generations to keep in history (default: 10)
  • COMFY_OUTPUT_PATH: Path to ComfyUI output directory (default: C:\Users\ktrangia\Documents\ComfyUI\output)

Running the Bot

python bot.py

The bot will:

  1. Load configuration from environment variables via BotConfig.from_env()
  2. Create WorkflowStateManager and WorkflowManager instances
  3. Initialize ComfyClient with injected dependencies
  4. Load workflow from WORKFLOW_FILE if specified
  5. Register all commands via commands.register_all_commands()
  6. Start Discord bot and job queue
  7. Listen for commands with prefix ttr!

Development Commands

No build/test/lint commands exist. This is a standalone Python application.

To run: python bot.py

Key Implementation Details

ComfyUI Workflow Node Injection

When generating with workflows, WorkflowManager searches for specific node patterns:

  • Prompt: Finds CLIPTextEncode nodes with _meta.title containing "Positive Prompt"
  • Negative Prompt: Finds CLIPTextEncode nodes with _meta.title containing "Negative Prompt"
  • Input Image: Finds LoadImage nodes and replaces the image input
  • Seeds: Finds any node with inputs.seed or inputs.noise_seed and randomizes

This pattern-matching approach means workflows must follow naming conventions in their node titles for dynamic updates to work.

Discord Command Pattern

Commands use a labelled parameter syntax: ttr!generate prompt:<text> negative_prompt:<text>

Parsing is handled by helpers in discord_utils.py (e.g., parse_labeled_args()). The bot splits on keyword markers (prompt:, negative_prompt:, type:, etc.) rather than traditional argparse. Case is preserved for prompts.

Job Queue Mechanics

Jobs are dataclasses with run: Callable[[], Awaitable[None]] and a label for logging. The queue returns position on submit. Jobs capture their context (ctx, prompts) via lambda closures when submitted.

Image/Video Output Handling

The _general_generate method in ComfyClient returns both images and videos. Videos are identified by file extension (mp4, webm, avi) in the history response. For videos, the bot reads the file from disk at the path specified by COMFY_OUTPUT_PATH rather than downloading via the API.

Command Validation

The @require_comfy_client decorator (from discord_utils.py) validates that bot.comfy exists before executing commands. This eliminates repetitive validation code in every command handler.

State Management

WorkflowStateManager maintains runtime workflow changes in memory with optional persistence to current-workflow-changes.json. The file is loaded on initialization if it exists, and saved automatically when changes are made.

Configuration System

Configuration is managed via the BotConfig dataclass in config.py:

from config import BotConfig

# Load from environment
config = BotConfig.from_env()

# Access configuration
server = config.comfy_server
history_limit = config.comfy_history_limit
output_path = config.comfy_output_path

All constants (command prefixes, error messages, defaults) are defined in config.py and imported where needed.

Adding New Commands

To add a new command:

  1. Create a new module in commands/ (e.g., commands/my_feature.py)
  2. Define a setup_my_feature_commands(bot, config=None) function
  3. Use @bot.command(name="...") decorators to define commands
  4. Use @require_comfy_client decorator if command needs ComfyClient
  5. Import and call your setup function in commands/__init__.py's register_all_commands()

Example:

# commands/my_feature.py
from discord.ext import commands
from discord_utils import require_comfy_client

def setup_my_feature_commands(bot):
    @bot.command(name="my-command")
    @require_comfy_client
    async def my_command(ctx: commands.Context):
        await ctx.reply("Hello from my command!")

Dependencies

From imports:

  • discord.py
  • aiohttp
  • websockets
  • python-dotenv (optional, for .env loading)

No requirements.txt exists. Install manually: pip install discord.py aiohttp websockets python-dotenv

Code Organization Principles

The refactored codebase follows these principles:

  1. Single Responsibility: Each module has one clear purpose
  2. Dependency Injection: Dependencies passed via constructor, not created internally
  3. Configuration Centralization: All configuration in config.py
  4. Command Separation: Commands grouped by functionality in separate modules
  5. No Magic Strings: Constants defined once in config.py
  6. Type Safety: Modern Python type hints throughout (dict[str, Any] instead of Dict)
  7. Logging: Using logger methods instead of print() statements