Discord

Set up the Gitterm Discord bot, host it yourself, manage its saved settings, and use it in a thread.

View as markdown

The Discord bot (@gitterm/discord-bot) puts an OpenCode agent on your repository. Mention it in a channel and it opens a thread. The agent works on the request in a Gitterm workspace, asks back with buttons when it needs a decision, and replies in the thread. Read this page to set the bot up, run it, and configure it.

You host one small process yourself: on your laptop, a VPS, Railway, or in a container. It connects to Discord's gateway, so it needs no public URL. The agent runs in an OpenCode workspace; the bots don't support T3 Code.

Before you start

  • A Gitterm account with a model credential under Models. See Agents.
  • GitHub access to the repository: a GitHub connection, or your own GitHub token. See Connections.
  • A Discord server where you can add bots.
  • Docker, or Node 22.12 or later, on the machine that will run the bot.

Set it up

All steps are required.

  1. Create the bot in Gitterm. In the dashboard, open Bots and click New bot. Fill in Model and Repository, and choose Discord under Platform. Compute, Tools and Behavior (channels, people, instructions, setup command) are optional. Under Deploy, name the bot and click Create bot.

    You should see a .env under Save this as .env, with the bot's GITTERM_API_TOKEN. The token is shown only once, so copy the file now. New token replaces a lost one.

  2. Create the Discord application. In the Discord developer portal, create an application and open its Bot page. Click Reset Token and copy the token. Turn on Message Content Intent, so the bot can read thread messages for context and typed answers.

  3. Add the Discord token to the .env:

    Shell
    GITTERM_API_TOKEN=gt_...
    DISCORD_BOT_TOKEN=...
  4. Start the bot in the folder that holds the .env:

    Shell
    npx @gitterm/discord-bot

    To run it in Docker instead, see Host it with Docker. Before it connects, the bot checks the token, model credential, GitHub access, tools and compute. You should see a โœ“ line for each, an Invite the bot: link, and GitTerm Discord bot is running for <repository>. Missing GitHub access or a missing model credential prints a ! warning, and the bot still starts. Any other problem prints what to fix and exits.

  5. Invite it. Open the Invite the bot: link and pick your server. The bot asks only for what it uses: view channels, send messages, create and post in threads, read message history, add reactions, and embed links.

  6. Mention it in a channel:

    Text
    @Acme Agent why does the login page flash on load?

    You should see a ๐Ÿ‘€ reaction on your message and a new thread with the reply.

Use it in a thread

  • Mention to start. A mention in a channel opens a thread for the conversation. Mention the bot, or reply to it, in the thread to continue with full context. Anyone in the thread can follow up, and messages posted between mentions are passed along. In a thread you started yourself, a mention works too, with the thread so far as context.
  • One session per thread. Threads run side by side. Messages in one thread wait their turn.
  • It asks back. Questions show a button per option, a menu for multiple choice or long lists, or a dialog for a written answer. Tool approvals show Allow once, Always allow (only if enabled) and Deny. The person who asked can also reply with an option number, yes, or no.
  • Images reach the agent. PNG, JPEG, GIF and WebP files up to 5 MB, posted with the mention or earlier in the thread, are attached. Other files are only named.
  • Pick a repository. If the bot has more than one repository, name one in the first message: @Acme Agent in acme/api, why is login slow?. The thread stays on that repository.
  • Progress. The request gets a ๐Ÿ‘€ reaction when picked up, then โœ… or โŒ.

Pull requests the agent opens start with Requested by <name> in Discord, without a link to the conversation. Direct messages aren't supported; talk to the bot in server channels.

Commands

Mention the bot with one word:

CommandWhat it does
stopCancel the work in this thread
statusShow the repository, workspace state, model, tools, and who may use the bot
resetTerminate the workspace. The next message creates a fresh one
helpExplain how to use the bot

How workspaces are used

  • Each repository gets one workspace per channel. It pauses when idle and wakes with the next message, so the checkout, installed dependencies and branches stay where the agent left them.
  • Different servers never share a workspace. Set GITTERM_BOT_SHARE_CHANNELS=true to let equally trusted channels share one.
  • The workspace name uses only the repository name: acme/api becomes discord-bot-api. Open it from the dashboard to see every thread's session. See Connect to a workspace.
  • A bot workspace gets only the chosen model's credential. It gets none of your saved environment variables or agent config.

Saved settings

The bot loads its saved settings from Gitterm, using its API token, each time it starts. Change them on the bot's page under Bots. A running bot applies saved changes to new requests without a restart.

Settings reach a workspace when it is created. After you change instructions, tools, the model's provider, or workspace settings, the bot asks for a reset: mention it with reset in each channel.

Environment variables and code options can narrow the saved settings (fewer channels or people) but never widen them. A repository, model or connection that isn't in the saved settings stops the bot with an error.

Host it with Docker

One image runs the Slack or the Discord bot; it picks the platform from the tokens in the .env. Run it in the folder that holds the .env:

Shell
docker run -d --name gitterm-discord-bot --restart unless-stopped \
  -v "$PWD/.env:/data/.env:ro" -v gitterm-discord-bot:/data \
  ghcr.io/opeoginni/gitterm-bot

Mount the .env as shown; --env-file doesn't read dotenv quoting. Thread state is kept in the /data volume. Follow the logs, including the invite link, with docker logs -f gitterm-discord-bot.

Without Docker, keep the .gitterm-bot/ folder on persistent storage so a restart picks up runs in progress.

Run one process per Discord application. A second process for the same saved bot waits for the first to stop: up to 90 seconds after a crash.

Configuration

Set environment variables (a .env in the working directory is loaded) or the matching code option. For a bot created under Bots, only the tokens are required; saved settings fill in the rest. To copy channel and user ids, turn on Developer Mode in Discord.

VariableOptionRequiredDefaultWhat it does
DISCORD_BOT_TOKENtokenYesNoneBot token
GITTERM_API_TOKENgittermYes, for a saved botThe gitterm login tokenThe bot's Gitterm token
GITTERM_SERVER_URLgittermOnly if self-hostedhttps://api.gitterm.devGitterm API URL
GITTERM_BOT_REPO, --reporepoOnly without saved settingsSaved settingsRepository for every channel. <url>#<branch> picks a branch
GITTERM_BOT_CHANNELSchannelsNoNonePer-channel repositories: 1234=https://github.com/acme/api,โ€ฆ
GITTERM_BOT_REPOSreposNoNoneMore repositories people can name in a thread
GITTERM_BOT_MODEL, --modelmodelNoSaved settingsprovider/model for every run. Only that provider's credential reaches the workspace
GITTERM_BOT_MODEL_CREDENTIALmodel.credentialNoThe provider's defaultSaved credential label. Needs GITTERM_BOT_MODEL
GITTERM_BOT_MODEL_API_KEYmodel.apiKeyNoNoneA model key for this bot only, never saved. Needs GITTERM_BOT_MODEL
GITTERM_BOT_CONNECTIONSconnectionsNoNoneTools besides GitHub, by name, key or id: Linear,Sentry
GITTERM_BOT_GITHUB_TOKENworkspace.repositoryCredentialsNoA Gitterm GitHub connectionYour own GitHub token instead of a connection
GITTERM_BOT_INSTRUCTIONS, GITTERM_BOT_INSTRUCTIONS_FILE, --instructions-fileinstructionsNoNoneExtra instructions for the agent
GITTERM_BOT_SETUPsetupNoNoneCommand run in the checkout before the agent starts, such as pnpm install
GITTERM_BOT_SANDBOX_ENV_FILEenvNoNoneA dotenv file of variables for new workspaces
GITTERM_BOT_PROVIDERworkspace.providerNoYour default providerCompute provider for new workspaces, such as e2b
GITTERM_BOT_ALLOWED_USERSallowedUsersNoAnyone who can post in the channelOnly these user ids may use the bot
GITTERM_BOT_ALLOWED_CHANNELSallowedChannelsNoEvery channel the bot can seeOnly these channel ids
GITTERM_BOT_APPROVERSapproversNoThe requesterWho may approve tool requests
GITTERM_BOT_ALLOW_ALWAYS=trueallowAlwaysNoOffShow Always allow on tool approvals
GITTERM_BOT_SHARE_CHANNELS=trueshareChannelsNoOffLet channels share one workspace
GITTERM_BOT_MAX_PENDING, GITTERM_BOT_MAX_PENDING_PER_USERmaxPendingRequests, maxPendingPerUserNo20 total, 3 per userQueue limits
GITTERM_BOT_STATE_FILEstateFileNo.gitterm-bot/discord.jsonWhere thread sessions are kept
GITTERM_BOT_RUN_TIMEOUT_MINUTESrunTimeoutMsNo60 minutesGive up on a request after this long, including time waiting for answers
inputTimeoutMsNo30 minutesHow long a question waits for an answer
GITTERM_BOT_IDbotIdNoSaved bots use their own idNames the workspaces of a bot without saved settings

Without a model, no saved model credential reaches the workspace.

Run it from code

TypeScript
import { createDiscordBot, withSavedConfig } from "@gitterm/discord-bot";

const bot = createDiscordBot(
  await withSavedConfig({
    workspace: { setup: { beforeAgent: ["pnpm install"] } },
  }),
);
await bot.start();

const shutdown = () => void bot.stop().finally(() => process.exit(0));
process.once("SIGINT", shutdown);
process.once("SIGTERM", shutdown);

withSavedConfig() loads the settings saved for the token. A saved bot must call it before start(). To add the agent to a discord.js client you already run, pass it as client. The client needs the Guilds, GuildMessages and MessageContent intents, and none of your own handlers should answer mentions of the bot.

Security

  • Who can use it: anyone who can post in a channel the bot can see, unless you set allowed users. Then only those people can make requests and approve tool requests. Use Discord channel permissions for the rest.
  • What the agent can reach: whatever the attached connections allow. Scope the GitHub connection and MCP credentials to match. To deny commands, set OpenCode permission rules in workspace.opencode.config.
  • What the bot stores: Gitterm workspace and run ids, in a file with mode 0600. No tokens.
  • Replies never ping anyone.
  • A question left unanswered past the workspace's idle timeout lets the workspace pause, which cancels the run.