Run Docker jobs from a CLI or a Slack channel.
Requires Go 1.26+, Docker and a running Redis (included via compose):
git clone https://github.com/parrahex/spool.git
cd spool
go build ./...Start Redis, the worker pool and the Slack bot in one command:
export SLACK_APP_TOKEN=xapp-...
export SLACK_BOT_TOKEN=xoxb-...
make devgo run ./cmd/cli run --image alpine echo hello world
go run ./cmd/cli status 63572007-a8ce-4657-9e5c-0455dfdac509
go run ./cmd/cli cancel 63572007-a8ce-4657-9e5c-0455dfdac509Mention the bot in any channel or DM it. Attach files to run them:
@Spool alpine echo hello world
@Spool python:3.11 python script.py
[script.py attached]
@Spool golang:1.26 go run main.go
[project.zip attached]
The bot replies in a thread with the job id, then posts the exit code and output when the job finishes.
- Parallel workers — a pool of goroutines drains the queue; scale with one env var
- Crash recovery — jobs are leased; a dead worker's jobs requeue automatically on the next startup
- Timeouts & retries — per-job execution limits, configurable retry attempts
- Zombie cleanup — every container is labeled and killed if its worker disappears
- File attachments — zips, folders, single files; all extracted and mounted read-only at
/app - Graceful shutdown — in-flight containers get a context cancel, not a kill
| Variable | Default | Description |
|---|---|---|
REDIS_ADDR |
localhost:6379 |
Redis address |
SPOOL_CONCURRENCY |
1 |
Number of parallel workers |
SLACK_APP_TOKEN |
— | App-level token for Socket Mode |
SLACK_BOT_TOKEN |
— | Bot user OAuth token |
Create the app from slack-app-manifest.yml at api.slack.com/apps → Create New App → From a manifest. Then install it to your workspace and copy the two tokens.



