mainplane-chat

command module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: MIT Imports: 31 Imported by: 0

README

mainplane-chat

Talk to your Mainplane agents from Discord and Slack. Every session is a thread. You see the agent work live, stop it with a button, send it files, and get files back. Long tasks keep going past the context limit on their own.

Mainplane is an open-source agent harness. It runs agents on any model and lets them control your computers. You message the agents through connectors, such as its terminal app and CLI. mainplane-chat adds Discord and Slack as connectors. It is a small Go service that runs next to your Mainplane server and talks to its API.

 Discord server ─┐                                   ┌─ worker: server
                 ├─ mainplane-chat ─ Mainplane server ┼─ worker: laptop
 Slack DMs ──────┘                                   └─ worker: ...

mainplane-chat is a community project. It is not made by or affiliated with the Mainplane team.

Features

  • A thread per session. A message in a channel (Discord) or a DM (Slack) starts a session in a new thread. Replies in the thread continue it.
  • Live status. One message shows the running turn: its time, its last tool calls and a Stop button. When the turn ends, it shrinks to one line: 14 calls · 2m31s · 38% context.
  • Files in both directions. Send images and text files with a message. The agent sends a file back with a line attach: /path/to/file in its reply.
  • Every connector, one conversation. Sessions started in the terminal app or CLI get a thread in #sessions. Messages sent from elsewhere show in the thread with their source.
  • Recovery. A failed step comes with a Retry button and a model picker. When a provider's quota runs out, continue on another model in one click.
  • No context limit. When a session fills its context, the bot continues it in a new session and passes on the last message. The thread follows.
  • Catches up. What happens while the bot is down is picked up when it starts again.
  • Slack agent sessions. In Slack, a thread is a native agent session, with its title, working state and Stop button.

The demos are re-creations of real sessions, with the worker names changed.

Setup

You need a running Mainplane server and Go 1.27 or later. Run mainplane-chat on the same machine as the server. Use Discord, Slack or both.

  1. Make a harness key for the bot:

    mainplane-server key new chat
    
  2. For Discord, make a bot in the Developer Portal. Turn on the Message Content intent. Invite it to a private server with permission to read and send messages, manage threads, add reactions and attach files. Make a text channel named sessions for sessions started outside Discord.

  3. For Slack, make an app from the manifest in slack-manifest.yaml and install it to your workspace. Make an app-level token with connections:write for Socket Mode.

  4. Install and run:

    go install github.com/0x7067/mainplane-chat@latest
    mainplane-chat
    

    To keep it running, use a systemd user service or similar, with the environment below in an env file.

Variable
MAINPLANE_KEY the harness key from step 1
MAINPLANE_URL the harness URL; default http://127.0.0.1:8080
DISCORD_TOKEN the Discord bot token; leave it unset to run Slack only
SLACK_BOT_TOKEN the xoxb- token of the Slack app; leave it unset to run Discord only
SLACK_APP_TOKEN the xapp- app-level token, with Slack
MAINPLANE_SLACK_USERS with Slack: comma-separated Slack user ids the bot takes messages from
MAINPLANE_DISCORD_TESTER optional: the user id of a tester bot whose messages the bot takes as a person's, for end-to-end tests. Other bots stay ignored

The bot keeps its state in $XDG_STATE_HOME/mainplane-chat/state.json (~/.local/state by default).

Security: anyone who can post in the Discord server, or any Slack user in MAINPLANE_SLACK_USERS, controls your agents and every worker they reach. Use a private Discord server.

Commands

Type these in a thread. In Discord, / and ! both work. In Slack, use !, as Slack takes / for its own commands.

Command
/model show a picker of the connected models
/model <id> [message] continue in a new session on that model, with the same workers
/continue [message] continue in a new session with the same config
/retry step a failed session again
/stop stop the running step
/info show the status, model, workers and context

Details

Discord
  • A message in any channel starts a session in a new thread named <session id> <first words>. Its model is picked as the Mainplane terminal app picks it: the newest session's, else the catalog's default, if its provider is connected. Its workers are every connected worker.
  • A session made outside Discord (terminal app, CLI, another agent) gets its own thread in #sessions, from when mirroring began. The bot finds the channel by name.
  • Messages sent from elsewhere show quoted with their source (> **cli:** …), and a background job's report shows as one line (-# job on admin exited 0 after 40s).
  • A thread whose session is deleted is archived and locked. When a session gets a name, its thread is renamed <id> <name>.
  • The final reply is a Discord reply to the message it answers. It notifies you when the turn took over two minutes.
  • Each message sent to a session gets a reaction: 👀 while the agent works, then ✅ or ❌. The start messages in a channel show how each session's last turn went.
  • The bot reads an attach: file on its own machine, up to 20 MiB, and uploads it in place of the line.
  • Files sent with a message go to the session: images as images (up to 5 MiB), text files inline (up to 200 KiB). Others are listed as not sent.
  • A thread follows a continuation made anywhere: /model or /continue in the terminal app moves the thread to the new session too. Mainplane has no event for new sessions, so the bot checks the newest ones every 3 seconds, as the terminal app does.
Slack
  • A top-level DM to the app starts a session in its thread, which is a Slack agent session. Slack shows its title (the first words, then the session's name), its working state and a Stop button. A title changed in Slack names the session.
  • Only users in MAINPLANE_SLACK_USERS are heard. A reply also sent to the DM counts.
  • Status, quotes, job lines, files, attach:, Retry, the model picker, auto-continue and following continuations work as in Discord. Remote files (shared from outside Slack) are not fetched.
  • The finished status line carries the session id, as the Slack title does not. Messages get ✅ or ❌ when their turn ends. A failed step marks the agent session suspended.
  • Sessions made in Slack stay in Slack: #sessions mirrors only sessions made outside the chats.

License

MIT. Built on Mainplane, which is MIT too.

Documentation

Overview

mainplane-chat drives Mainplane agents from Discord and Slack, the way the mainplane terminal app does. A message in a channel or DM starts a session in a new thread; messages in that thread continue it, and the agent's replies come back there. A thread takes the terminal app's /model, /continue and /stop, and the CLI's /retry and /info (in Slack, as !model and so on). What happens while the bot is down is picked up when it comes back.

This file is the core: the harness client, following sessions, commands, continuations and the state. Each chat app is an adapter (discord.go, slack.go) that turns its events into calls of the core and shows what the core says.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL