REPLbot is a bot for Slack and Discord that allows you to control a REPL or shell from a chat. It comes with a few REPLs (Go
I thought it might be a fun way to collaboratively dabble with a REPL in a team. Yes, I could have gone for a terminal in a browser, but there's nothing like having it right there in Slack. Mainly I did it because it was fun though.
How it works
tmux and the
tmux capture-pane command to run most of the show. It's simple, but effective. In the first iteration I tried using a pseudo terminal (pty) directly, but with all the escape sequences and commands, it was getting kinda tiresome, and I was spending time with stuff that I didn't want to spend time with (though I learned a lot!). And
tmux does its job so well.
The actual REPLs are just simple scripts (see script.d folder), so they could be anything you like. I highly recommend using Docker to provide somewhat of an isolation, though you'll probably still need to trust the people using the bot if you give them an entire REPL.
Screenshots & Videos
|Scala, split mode (Discord)||Ubuntu running `htop` (Discord)||C++, channel mode (Discord)|
|Blinking cursors, choo choo
||Custom shells, multiple sessions (Slack)|
After installing REPLbot, you may use it by tagging
@replbot in Slack/Discord. For the most part it should be pretty self-explanatory:
To start a session with the default settings, simply say
@replbot java to start a Java REPL. There are a few advanced arguments you can use when starting a session.
REPLbot can run more or less arbitrary scripts and interact with them -- they don't really have to be REPLs. Any interactive script is perfectly fine, whether it's a REPL or a Shell or even a game. By default, REPLbot ships with a few REPLs. To extend the REPLs you can run, simple add more scripts in the
script-dir folder (see config.yml).
Here's a super simple example script:
#!/bin/sh # Scripts are executed as "./script run <id>" to start the REPL, and as "./script kill <id>" # to stop it. Not all scripts need the "kill" behavior, if they exit properly on SIGTERM. case "$1" in run) while true; do echo -n "Enter name: " read name echo "Hello $name!" done ;; *) ;; esac
In all likelihood, you'll want more isolation by running REPLs as Docker containers. Here's the PHP REPL script that REPLbot ships with (not shortened):
#!/bin/sh # REPLbot script to run a PHP REPL. # # Scripts are executed as "./script run <id>" to start the REPL, # and as "./script kill <id>" to stop it. DIR="$(cd -- "$(dirname "$0")" >/dev/null 2>&1 && pwd -P)" case "$1" in run) docker run --rm --name "$2" -it php ;; kill) "$DIR"/helpers/docker-kill "$2" ;; *) echo "Syntax: $0 (run|kill) ID"; exit 1 ;; esac
You can specify if you want the session to be started in the main channel (
channel), in a thread (
thread), or in split mode (
split) using both channel and thread. Split mode is the default because it is the cleanest to use: it'll use a thread for command input and the main channel to display the terminal.
You can set the terminal window size when you start a session by using the keywords
medium (100x30), and
large (120x38). The default is
small. You may also resize the terminal while the session is running using the
When starting a session, you can choose whether to trim empty space from the terminal session (
trim), or whether to show the entire terminal window as it would appear in a terminal emulator (
full). The default is
trim mode can get awkward when the terminal is expanded and the collapsed again.
You can share your local terminal window in Slack or Discord using the
share feature. It's quite cool, although it's really got nothing to do with REPLs
share-host option, since it needs direct communication between the client and REPLbot.
When a session is started, you can get a list of available commands by typing
!h). To exit a session at any point in time, type
First, create a Slack or Discord app and authorize it. After that, you can install REPLbot via packages or binaries.
Creating a REPLbot Slack app:
REPLbot requires a Slack "Classic App (bot)", because of its use of the real time messaging (RTM) API. To create a classic app and acquire a Slack bot token, follow these steps:
- Create a classic Slack app
- In the "App Home" section, add a "Legacy bot user"
- In the "OAuth & Permissions" section, click "Install to Workspace" (this may require workspace admin approval)
- Copy the "Bot User OAuth Token" starting with "xoxb-..."
Creating a REPLbot Discord app:
- Create a Discord app
- In the "Bot" section, click "Add Bot" and disable "Public Bot"
- In the "OAuth2" section, click "Add Redirect" and type a URL (even https://google.com is fine), select the scopes "bot" and "messages.read", and the permissions "public threads", "private thread", "send messages", "manage messages", "manage threads". Click "Save changes".
- Copy the OAuth2 URL and navigate to it in the browser and authorize the app.
- In the "Bot" section, copy the token and paste it here
- Make sure
tmuxand probably also
dockerare installed. Then install REPLbot using any of the methods below.
- Then edit
/etc/replbot/config.ymlto add Slack or Discord bot token. REPLbot will figure out which one is which based on the format.
- Review the scripts in
/etc/replbot/script.d, and make sure that you have Docker installed if you'd like to use them.
- If you're running REPLbot as non-root user (such as when you install the deb/rpm), be sure to add the
replbotuser to the
sudo usermod -G docker -a replbot.
- Then just run it with
systemctl start replbotwhen using the deb/rpm).
Binaries and packages
Debian/Ubuntu (from a repository):
curl -sSL https://archive.heckel.io/apt/pubkey.txt | sudo apt-key add - sudo apt install apt-transport-https sudo sh -c "echo 'deb [arch=amd64] https://archive.heckel.io/apt debian main' > /etc/apt/sources.list.d/archive.heckel.io.list" sudo apt update sudo apt install replbot
Debian/Ubuntu (manual install):
sudo apt install tmux wget https://github.com/binwiederhier/replbot/releases/download/v0.4.5/replbot_0.4.5_amd64.deb dpkg -i replbot_0.4.5_amd64.deb
# Make sure that "tmux" is installed rpm -ivh https://github.com/binwiederhier/replbot/releases/download/v0.4.5/replbot_0.4.5_amd64.rpm
You can configure the Docker image by mounting a config directory (containing config.yml) to
/etc/replbot. To be able to use most of the pre-packaged script.d REPLs (to be mounted to
/etc/replbot/script.d), you'll need to give the REPLbot image access to the Docker socket file. This allows the container to spin up other containers on the host. This is a security risk and considered bad practice, but it's the only way.
docker run --rm -it \ -v /etc/replbot:/etc/replbot \ -v /var/run/docker.sock:/var/run/docker.sock \ binwiederhier/replbot
# Be sure "tmux" is installed go get -u heckel.io/replbot
Manual install (any x86_64-based Linux):
# Make sure that "tmux" is installed wget https://github.com/binwiederhier/replbot/releases/download/v0.4.5/replbot_0.4.5_linux_x86_64.tar.gz sudo tar -C /usr/bin -zxf replbot_0.4.5_linux_x86_64.tar.gz replbot
Building replbot is simple. Here's how you do it:
make build-simple # Builds to dist/replbot_linux_amd64/replbot
To build releases, I use GoReleaser. If you have that installed, you can run
make build or
I welcome any and all contributions. Just create a PR or an issue, or talk to me on Slack.
Third party libraries:
- github.com/urfave/cli/v2 (MIT) is used to drive the CLI
- discord-go (BSD-3) is used for the Discord communication, specifically these two these two pull requests for thread support
- slack-go (BSD-2) is used for the Slack communication
- gliderlabs/ssh (BSD-3) is used for remote port forwarding for terminal sharing
Code and posts that helped: