Discord
Set up the Gitterm Discord bot, host it yourself, manage its saved settings, and use it in a thread.
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.
-
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
.envunder Save this as .env, with the bot'sGITTERM_API_TOKEN. The token is shown only once, so copy the file now. New token replaces a lost one. -
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.
-
Add the Discord token to the
.env:Shell GITTERM_API_TOKEN=gt_... DISCORD_BOT_TOKEN=... -
Start the bot in the folder that holds the
.env:Shell npx @gitterm/discord-botTo 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, anInvite the bot:link, andGitTerm 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. -
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. -
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, orno. - 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:
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=trueto let equally trusted channels share one. - The workspace name uses only the repository name:
acme/apibecomesdiscord-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:
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-botMount 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.
Without a model, no saved model credential reaches the workspace.
Run it from code
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
permissionrules inworkspace.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.