Skip to main content
Freesona’s cog-based architecture makes it straightforward to add new commands. All logic lives in focused modules under cogs/. Shared utilities live in utils/. A single registry file (utils/modules.py) controls what is available at runtime. Add a file, register it, and enable it from Discord — no restart required.

How Modules Work

  • Each feature lives in cogs/<category>/<name>.py as a discord.py Cog class.
  • Core modules (help, ping, status, admin) always load on startup and cannot be toggled.
  • Optional modules are registered in OPTIONAL_MODULES in utils/modules.py. They can be toggled via /module enable and /module disable at runtime.
  • Enabled/disabled state persists in config.json under enabled_modules. Your configuration survives restarts.
  • Slash commands are automatically re-synced when you enable or disable a module.

Creating a New Module

1

Create the cog file

Create cogs/<category>/<name>.py. At minimum, define a Cog subclass and a setup coroutine:
cogs/tools/mycommand.py
Place it under an existing category (ai, media, moderation, system, tools, fun) or create a new subfolder.
2

Register it in utils/modules.py

Add an entry to OPTIONAL_MODULES using a short lowercase key and the full dotted module path:
utils/modules.py
Once registered, the key appears in /module list and supports autocomplete.
3

Enable it from Discord

Run the enable command in your server:
The bot loads the cog immediately and re-syncs slash commands.
4

Verify with /module list

Run /module list. Your new module should appear as enabled with its load status confirmed.

Accessing Bot Utilities

Import from utils/ for functionality shared across cogs:
Keep cogs focused. Each file should handle one feature area. Cogs should not import directly from each other. If one cog needs functionality from another (for example, mvsep.py uses ytdlp.py), access it via bot.get_cog("CogClassName") at call time rather than a top-level import.

Adding Slash Command Support

discord.py supports exposing a single command as both a prefix and a slash command via @commands.hybrid_command. Use this by default — one decorator, one callback:
Only fall back to defining separate @app_commands.command and @commands.command callbacks when the slash version needs interaction-only features that @commands.command cannot provide. For example, modals (interaction.response.send_modal(...)) require a raw discord.Interaction. After adding new slash commands, run /sync (Bot Owner) to register them globally with Discord. The /module enable and /module disable commands also trigger an automatic re-sync.
Run python scripts/check_project.py before deploying to verify syntax and config. On Windows PowerShell you can use .\\scripts\\check.ps1 instead. Both run the same checks and exit non-zero on any failure.