Documentation
C0D loads module files from bot/modules/. Each
.cod file lists commands, optional slash options, and
either a reply string or an action chain.
Install & run
You need Node.js 18+ and a Discord application (bot token + client
ID). The bot code lives in the bot/ folder.
1. Get the project
Clone the repo or copy the bot/ directory to your
machine.
2. Install dependencies
cd bot
npm install
3. Configure environment
Copy .env.example to .env and fill in
values from the
Discord Developer Portal.
DISCORD_TOKEN=your_bot_token
DISCORD_CLIENT_ID=your_application_id
# Optional for instant guild command updates while developing:
# DISCORD_GUILD_ID=your_server_id
Under Bot → Privileged Gateway Intents, enable Server Members Intent for moderation features. Enable Message Content Intent only if you add code that reads message text.
4. Start the bot
npm start
.cod file format
A minimal module with a plain text reply (no action chain) looks like this:
{
"meta": { "name": "ping", "version": "1.0.0" },
"commands": [
{
"name": "ping",
"description": "Health check",
"response": "Pong!",
"ephemeral": false
}
]
}
Simple replies
If a command has response and no actions
array (or an empty one), the bot sends that text once. Use
ephemeral: true for replies only visible to the user who
ran the command.
Action chains
If actions is a non-empty array, the bot
defers the reply, runs each action in order, then
sends one combined message (truncated to Discord limits). Mix
moderation and channel actions with reply steps as
needed.
"actions": [
{ "type": "purge_messages", "count_option": "amount" },
{ "type": "reply", "text": "Cleanup finished." }
]
Action types
reply-text(orcontent)-
purge_messages-countfixed number, orcount_optionfor a slash integer option name -
create_channel-nameorname_option; optionalname_templatewith{user},{userid},{random};ticket_style: truehides the channel from @everyone and grants access to the user who invoked the action -
delete_channel-channel_option(slash channel option name) -
ban_member-user_option,delete_message_days, optionalreason_option -
kick_member-user_option, optionalreason_option -
timeout_member-user_option,minutesorminutes_option -
lock_channel/unlock_channel- optionalchannel_option(defaults to current channel) -
slowmode-secondsorseconds_option, optionalchannel_option -
send_message-channel_option(slash channel) orchannel_id;contentorcontent_optionfor slash string -
send_embed- same channel targeting;embedobject (title, description, color, fields, footer); optionalcomponentsarray (see below) -
JSON data - generic
data_*actions (read / write / increment / lists / leaderboard); paths and filenames are yours (see Data files).
Data files (bot/data/)
Each module gets a folder data/<module-name>/ where
<module-name> is sanitized meta.name from the
.cod file (or the filename). Inside it you can use any
<basename>.json you reference from actions (data_file).
Shapes are not fixed: use whatever JSON fits your game (e.g.
users.<id>.coins, root array entries, etc.).
*.json under data/ is gitignored.
data-store.js exposes readModuleJson /
writeModuleJson. The data_* actions below call those for you.
Path templates
Dotted paths support placeholders: {userid} (invoker),
{select_value} (menus), {option_user:OPTION_NAME} (slash
USER option), {option_string:OPTION_NAME}. Messages also support
{mention}, {user}, {random}.
Data action types
-
data_get-data_file,path, optionaldefault,message({value}). Optionalderiveobject for extra fields from the read number, e.g."derive": { "level": { "op": "div_floor_add", "by": 100, "add": 1 } }adds{level}. -
data_set-data_file,path, andvalueorvalue_integer_option/value_string_option/value_boolean_option. Optionalsuccess_message. -
data_increment-data_file,path,deltaand/ordelta_option, optionaldefault_if_missing,clamp_min,clamp_max,message({value},{delta}). Optionaltarget_user_optionfor{target}in the message (slash). -
data_append/data_append_unique-data_file,pathto an array,itemtemplate (default{userid}),max_length, optional messages. -
data_daily_claim-data_file,stamp_path,counter_path,reward,compare_modeutc_date,already_message,success_message({value}= new counter). -
data_transfer- slash only:from_path,to_path,amount_option,target_user_option(for{target}),data_file, optionalmessage. -
data_rank-object_pathto an object of records,score_keynested numeric field,orderdesc|asc,limit,header,score_label,empty_message, optionalinclude_zero.
Examples: bot/modules/economy.cod (wallet + transfer + rank),
leveling.cod, giveaway.cod. Web templates
economy-demo, leveling-demo, giveaway,
gamble (chips).
Module Builder (data blocks)
The web Module Builder includes green
data blocks for data_get, data_set,
data_increment, list append (data_append /
data_append_unique via one block), data_daily_claim,
data_transfer, and data_rank. Import a
.cod file to edit those fields visually. Slash options are merged
automatically from path placeholders ({option_user:…},
{option_string:…}), from data_transfer’s
amount_option / target_user_option, from
data_increment’s delta_option and optional
target_user_option, and from data_set value option
fields when filled.
Buttons, dropdowns & ticket panels
A root interactions object maps
custom_id strings to action lists. When someone
clicks a button or uses a string select menu, those actions run
(slash options are not available - use placeholders like
{select_value} in reply text).
Inside send_embed, components is an array
of rows. Each row has "type": "ACTION_ROW" and
components: buttons with
type: "BUTTON", custom_id,
label, style (PRIMARY,
SECONDARY, SUCCESS, DANGER), or
type: "STRING_SELECT" with options array
(label, value, optional
description).
Slash options
Declare options on each command with an options array.
Option type values: STRING,
INTEGER, BOOLEAN, USER,
CHANNEL, ROLE. Use
required: false for optional inputs.
Default permissions
Set default_member_permissions to one of:
Administrator, BanMembers,
KickMembers, ModerateMembers,
ManageChannels, ManageMessages - so only
members with that permission see the command in the picker.
Discord Developer Portal
Enable Server Members Intent and
Message Content Intent (if you extend the bot to
read message bodies) under Bot → Privileged Gateway Intents. The
bot uses Guilds, GuildMembers,
GuildModeration, and GuildMessages.
Invite the bot with scopes bot and
applications.commands, and grant permissions for the
actions you use (Manage Channels, Moderate Members, Ban Members,
Manage Messages, etc.).
How loading works
On startup, index.js parses every *.cod in
modules/, merges slash commands, and registers them.
Each command and interaction handler gets a moduleName derived from
meta.name (for data paths and debugging). Duplicate slash names are
overwritten - watch the console.
Set DISCORD_GUILD_ID in .env for instant
guild command updates while developing. Omit it for global commands
(propagation can take up to an hour).