Required environmental variables
June 14, 2026 ยท View on GitHub
| Variable | Type of Value |
|---|---|
| DISCORD_AUTH | Discord Bot Authentication Token |
| BOT_OWNER_DISCORD_ID | Discord User ID for Bot Owner |
| BOT_NAME | Name the bot will use as username, nickname, and prefix for data files |
| (NB: Avoid using non-ascii characters to prevent unexpected behavior) | |
| NODE_ENV | Node Environment: "production" or "development" |
Optional environmental variables
| Variable | Type of Value |
|---|---|
| DATA_DIR | Optional absolute or project-relative override for the bot data directory (defaults to ./data). |
| AMBIENT_BOT_NAME_TRIGGER | Toggle ambient name-based replies in non-DM channels (true/1 by default, set false/0 to disable). |
| TOPIC_MEMORY_SALT | Salt used to anonymize user IDs in temporal topic memory; if unset, topic memory is disabled (fail-closed). |
| TRACE_SURPRISE | Enable debug traces for surprise-based next/previous token selection in response generation (true/1). |
| HARNESS_PROXY_ENABLED | Enable local harness HTTP proxy endpoints (true/1 to enable). |
| HARNESS_PROXY_TOKEN | Bearer token required by harness proxy when enabled. |
| HARNESS_PROXY_ALLOW_PROD | Allow harness proxy in production (false by default). |
| HARNESS_PROXY_ALLOW_REMOTE | Allow non-localhost access to harness proxy (false by default). |
| HARNESS_PROXY_IP_ALLOWLIST | Optional comma-separated source IP allowlist for harness proxy when remote access is enabled. |
| HARNESS_PROXY_MAX_BODY_BYTES | Maximum request payload size accepted by harness proxy (default 1048576). |
| HARNESS_PROXY_RATE_LIMIT_MAX_REQUESTS | Maximum requests per source IP per rate-limit window (default 120). |
| HARNESS_PROXY_RATE_LIMIT_WINDOW_MS | Rate-limit window size in milliseconds (default 60000). |
| HARNESS_PROXY_TRUST_CALLER_ROLES | Trust caller-provided isAdmin/isBotOwner flags in harness payloads (default false). |
Bot settings
Default bot settings are stored in the resources/default-settings.json file. These should be copied to resources/{bot name}-settings.json.
The following are the required values for the bot settings:
| Value | Acceptable Range | Default Value | Description |
|---|---|---|---|
| outburstThreshold | 0.0 - 1.0 | 0.005 | Chance that the bot will respond without being explicitly triggered |
| angerLevel | 0.01 - 10.0 | 0.5 | Chance that the bot will yell. Values above 1.0 will cause the bot to always yell |
| surprise | 0.0 - 1.0 | 0.25 | Randomness factor for weighted next/previous token selection |
| angerIncrease | 0.01 - 10.0 | 1.75 | Value that the angerLevel will be multiplied by if the bot witnesses yelling (all capitalized input) |
| angerDecrease | 0.01 - 10.0 | 0.8 | Value that the AngerLevel will be multipled by if the bot does not witness yelling |
| recursion | 1 - 5 | 1 | Number of response-generation passes before the final output is chosen |
| topicMemoryTtlMinutes | 1 - 1440 | 20 | Minutes a remembered topic stays active for a user+channel |
| topicMemoryMaxInteractions | 1 - 1000 | 8 | Maximum number of personality-response generations before topic memory expires |
| topicMemoryBiasStrength | 0.0 - 1.0 | 0.8 | Multiplier applied to remembered topic weights when they are overlaid onto response generation |
| topicMemoryKeywordCount | 1 - 5 | 3 | Number of ranked keywords extracted from user input when refreshing topic memory |
| learnFromBots | true / false | false | Whether the bot will learn from other bots, or ignore them |
Validation
npm run buildcompiles TypeScript intodist/.npm run devbuilds and starts the bot locally.npm run startstarts from an existingdist/build.
Note: this branch does not currently define npm test, test:*, or lint scripts.
Steps to deploy initially (no pretrained brain) without git
- Copy the following files and directories:
./resources/*./src/*./tools/*(NOTE: you should also runchmod +x ./tools/*for the scripts to properly execute)./Dockerfile./docker-compose.yml./package.json./tsconfig.json./README.md./.gitattributes./.dockerignore
- Create the following files and directories:
./.env(See Required environment variables)./data/- (Optional)
./resources/{bot-name}-settings.json(See Bot settings) - (Optional)
./resources/{bot-name}-trainer.{txt|json}(See Example trainer schema- You can also create a default trainer by running the following commands:
cd ./tools/./generate-trainer.sh
- This will create the file
./resources/default-trainer.txtbased off of data from the ConvAI2 competition - WARNING: This requires the
curlandjqprograms to be installed
- You can also create a default trainer by running the following commands:
- Install dependencies via
npm:npm install
- Build a distribution version of the source:
npm run builddocker-compose build
- Run
docker-composeas a daemon:docker-compose up -d
Steps to install when using git
- Create a directory for the project to exist in:
mkdir -p ~/charliescd ~/charlies
- Clone the project:
git clone https://github.com/mureni/charlies2.git ~/charlies - Create the following files and directories:
./.env(See Required environment variables)./data/- (Optional)
./resources/{bot-name}-settings.json(See Bot settings) - (Optional)
./resources/{bot-name}-trainer.{txt|json}(See Example trainer schema- You can also create a default trainer by running the following commands:
cd ./tools/./generate-trainer.sh
- This will create the file
./resources/default-trainer.txtbased off of data from the ConvAI2 competition - WARNING: This requires the
curlandjqprograms to be installed
- You can also create a default trainer by running the following commands:
- Install dependencies via
npm:npm install
- Build a distribution version of the source:
npm run builddocker-compose build
- Run
docker-composeas a daemon:docker-compose up -d
Steps to update when using git
- Run the
updatescript:./tools/update.sh- Optional:
./tools/update.sh origin private-devto target a specific remote/branch
The update script, if not present, can be made as follows:
#!/bin/sh
set -eu
if [ -n "${1:-}" ] && [ -n "${2:-}" ]; then
REMOTE="\$1"
BRANCH="\$2"
elif [ -n "${1:-}" ]; then
case "\$1" in
*/*)
REMOTE="${1%%/*}"
BRANCH="${1#*/}"
;;
*)
REMOTE="origin"
BRANCH="\$1"
;;
esac
else
UPSTREAM=$(git rev-parse --abbrev-ref --symbolic-full-name "@{u}" 2>/dev/null || true)
if [ -n "$UPSTREAM" ] && [ "$UPSTREAM" != "@{u}" ]; then
REMOTE="${UPSTREAM%%/*}"
BRANCH="${UPSTREAM#*/}"
else
REMOTE="origin"
BRANCH=$(git rev-parse --abbrev-ref HEAD)
fi
fi
echo "Stopping docker container for charlies..."
docker-compose down
echo "Retrieving most recent code from remote '$REMOTE', branch '$BRANCH'..."
git pull "$REMOTE" "$BRANCH"
echo "Rebuilding charlies docker image as needed..."
docker-compose build
echo "Starting docker container based off of charlies docker image..."
docker-compose up -d
This will pull the most recent code from the remote git repo