Slack

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

View as markdown

The Slack bot (@gitterm/slack-bot) puts an OpenCode agent on your repository. Mention it in a channel and 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 Slack over Socket Mode, 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.
  • Permission to install apps in your Slack workspace.
  • Docker, or Node 22.12 or later, on the machine that will run the bot.

Set it up

All steps are required unless marked optional.

  1. Create the bot in Gitterm. In the dashboard, open Bots and click New bot. Fill in Model and Repository, and choose Slack 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 Slack app. On the bot's page, click Create the Slack app. Slack opens with the app already configured. Click Install to Workspace.

    If Slack doesn't fill in the manifest, choose Create New App โ†’ From a manifest, pick your workspace, and paste the manifest shown on the bot's page.

  3. Add the Slack tokens to the .env. Copy the Bot User OAuth Token into SLACK_BOT_TOKEN. Under Basic Information โ†’ App-Level Tokens, create a token with the connections:write scope and put it in SLACK_APP_TOKEN.

    Shell
    GITTERM_API_TOKEN=gt_...
    SLACK_BOT_TOKEN=xoxb-...
    SLACK_APP_TOKEN=xapp-...
  4. Start the bot in the folder that holds the .env:

    Shell
    npx @gitterm/slack-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, then GitTerm Slack 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 to a channel and mention it:

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

    You should see a ๐Ÿ‘€ reaction on your message, then the reply in the thread.

To build the Slack app by hand, print the manifest and paste it at api.slack.com/apps under From a manifest:

Shell
npx @gitterm/slack-bot manifest "Acme Agent"

Use it in a thread

  • Mention to start. A mention in a channel starts a session. Mention the bot again in the thread to continue with full context. Anyone in the thread can follow up, and messages posted between mentions are passed along.
  • 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, checkboxes for multiple choice, 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.
  • Direct messages. Message the bot directly; no mention needed. Each DM gets its own workspace, which is terminated seven days after it is created.
  • Progress. Slack shows that the bot is working under the thread. The request gets a ๐Ÿ‘€ reaction when picked up, then โœ… or โŒ.

Pull requests the agent opens start with Requested by <name> in Slack, without a link to the conversation.

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.
  • By default channels never share a workspace, so a private channel's work stays out of public ones. Set GITTERM_BOT_SHARE_CHANNELS=true to make every channel share one workspace per repository. Use it only when all the channels are equally trusted.
  • The workspace name uses only the repository name: acme/api becomes slack-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-slack-bot --restart unless-stopped \
  -v "$PWD/.env:/data/.env:ro" -v gitterm-slack-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 with docker logs -f gitterm-slack-bot.

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

Run one process per Slack app. 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.

VariableOptionRequiredDefaultWhat it does
SLACK_BOT_TOKENbotTokenYesNoneBot token (xoxb-โ€ฆ)
SLACK_APP_TOKENappTokenYesNoneApp-level token with connections:write (xapp-โ€ฆ)
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: C0123=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_USERSallowedUsersNoEvery full member in the channelOnly these user ids may use the bot
GITTERM_BOT_ALLOWED_CHANNELSallowedChannelsNoEvery channel the bot is inOnly these channel ids
GITTERM_BOT_ALLOW_GUESTS=trueallowGuestsNoOffLet guests and people from other organizations use the bot
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/slack.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 { createSlackBot, withSavedConfig } from "@gitterm/slack-bot";

const bot = createSlackBot(
  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 Bolt app you already run, pass it as app. Your app needs the scopes and events from the manifest, and none of your own listeners should answer app_mention.

Security

  • Who can use it: full members of the Slack workspace, in channels the bot was invited to, or only the users you allow. Guests and people from other organizations are refused unless you allow guests.
  • 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 mention @channel or @here.
  • A question left unanswered past the workspace's idle timeout lets the workspace pause, which cancels the run.