Loading repository data…
Loading repository data…
nielsbosma / repository
A flexible Slack bot framework that bridges Slack and local CLI scripts through a JSON protocol. Create bots in any language!
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
A flexible Slack bot framework that allows you to create multiple bots powered by local CLI scripts (PowerShell, C#, Python, etc.). Bots communicate with Slack through a simple JSON protocol, enabling rich interactions without requiring scripts to implement the Slack API directly.
SlackServer acts as a bridge between Slack and your local scripts. Instead of writing complex Slack bot logic, you write simple scripts that output JSON commands, and SlackServer handles all the Slack API interactions.
🚀 NEW HERE? Start with the Quick Start Guide (15 minutes) to get your @mention bot running!
This guide will walk you through creating a Slack bot that responds when @mentioned in a channel.
Socket Mode allows your bot to receive events without needing a public URL.
xapp-) - Save this! ⚠️Go to "OAuth & Permissions" in the left sidebar
Scroll to "Scopes" → "Bot Token Scopes"
Click "Add an OAuth Scope" and add these scopes:
Required Scopes:
app_mentions:read - Read messages that @mention your botchat:write - Send messageschannels:history - Read messages in channelsim:history - Read messages in DMsusers:read - Get user informationOptional Scopes:
reactions:write - Add/remove emoji reactionsfiles:write - Upload filesGo to "Event Subscriptions" in the left sidebar
Toggle "Enable Events" to ON
Expand "Subscribe to bot events"
Click "Add Bot User Event" and add:
app_mention - When someone @mentions your botmessage.channels - Messages in channels (if you want to respond without @mention)message.im - Direct messages to your botClick "Save Changes"
xoxb-) - Save this! ⚠️/invite @MyBot (replace with your bot's name)You'll need the channel ID for configuration:
C, e.g., C01234ABCDE)Copy config.example.yaml to config.yaml:
cp config.example.yaml config.yaml
Edit config.yaml with your tokens and channel:
slack:
appToken: "xapp-1-YOUR-APP-LEVEL-TOKEN" # From Step 2
botToken: "xoxb-YOUR-BOT-USER-TOKEN" # From Step 5
logLevel: "Information"
bots:
# Bot that responds to @mentions
- name: "Question Bot"
description: "Answers questions when @mentioned"
type: channel
channelId: "C01234ABCDE" # Your channel ID from Step 7
messagePattern: "<@\\w+>\\s+.*" # Matches "@bot_name question"
script: "pwsh ./scripts/question-bot.ps1"
timeout: 30
Pattern Explanation:
<@\\w+> - Matches the @mention (Slack sends it as <@U01234>)\\s+ - Matches whitespace.* - Matches the rest of the message (the question)Create scripts/question-bot.ps1:
#!/usr/bin/env pwsh
# Question bot - responds to @mentions
param(
[string]$Message = $env:TRIGGER_MESSAGE,
[string]$Channel = $env:TRIGGER_CHANNEL,
[string]$Timestamp = $env:TRIGGER_TS,
[string]$User = $env:TRIGGER_USER
)
function Send-SlackAction {
param([hashtable]$Action)
$json = $Action | ConvertTo-Json -Compress -Depth 10
Write-Output $json
}
# Extract the question (remove the @mention part)
$question = $Message -replace '<@\w+>\s*', ''
# Post a thinking message
Send-SlackAction @{
action = "post_message"
channel = $Channel
thread_ts = $Timestamp
text = "🤔 Let me think about that..."
store_as = "thinking_msg"
}
Start-Sleep -Milliseconds 500
# Process the question (call your CLI tool here)
# Example: calling a simple echo, but you could call any CLI
$answer = "You asked: '$question'"
$answer += "`n`nThis is where you would call your CLI tool!"
$answer += "`nExample: `python ./my-cli-tool.py `"$question`"`"
# Update with the answer
Send-SlackAction @{
action = "update_message"
channel = $Channel
message_ref = "thinking_msg"
text = "✅ *Answer:*`n$answer"
}
# You could also post a rich formatted response
Send-SlackAction @{
action = "post_blocks"
channel = $Channel
thread_ts = $Timestamp
text = "Response details"
blocks = @(
@{
type = "section"
text = @{
type = "mrkdwn"
text = "*Your Question:*`n> $question"
}
}
@{
type = "divider"
}
@{
type = "section"
text = @{
type = "mrkdwn"
text = "*Answer:*`n$answer"
}
}
)
}
exit 0
Make script executable (Linux/Mac):
chmod +x scripts/question-bot.ps1
# Build the C# test bot (optional, but good to verify)
cd TestBotCli
dotnet build -c Release
cd ..
# Run SlackServer
dotnet run
You should see:
info: SlackServer.Services.SlackListenerService[0]
Loaded 1 bot(s) from config.yaml
info: SlackServer.Services.SlackListenerService[0]
- Question Bot: channel | <@\w+>\s+.* | pwsh ./scripts/question-bot.ps1
info: SlackServer.Services.SlackListenerService[0]
Connecting to Slack via Socket Mode...
info: SlackServer.Services.SlackListenerService[0]
✅ Connected to Slack! Ready to process bot commands.
@MyBot what is the weather?Your bot should:
bots:
- name: "Auto Responder"
type: channel
channelId: "C01234ABCDE"
messagePattern: ".*help.*" # Matches any message containing "help"
script: "pwsh ./scripts/help-bot.ps1"
timeout: 15
bots:
- name: "DM Bot"
type: bot_dm # Only responds to DMs
messagePattern: ".*" # Matches any DM
script: "python ./bots/dm-handler.py"
timeout: 30
bots:
- name: "Help Bot"
type: channel
channelId: "C01234ABCDE"
messagePattern: "^help"
script: "pwsh ./scripts/help.ps1"
timeout: 10
- name: "Deploy Bot"
type: channel
channelId: "C01234ABCDE"
messagePattern: "^deploy (staging|production)"
script: "pwsh ./scripts/deploy.ps1"
timeout: 120
- name: "Question Bot"
type: channel
channelId: "C01234ABCDE"
messagePattern: "<@\\w+>\\s+.*"
script: "pwsh ./scripts/question-bot.ps1"
timeout: 30
# Example: Call Python CLI tool
$question = $Message -replace '<@\w+>\s*', ''
$result = python ./my-tool.py $question | Out-String
Send-SlackAction @{
action = "post_message"
channel = $Channel
thread_ts = $Timestamp
text = $result
}
# Example: Call C# CLI tool
$answer = dotnet run --project ./MyCliTool -- $question | Out-String
Send-SlackAction @{
action = "post_message"
channel = $Channel
thread_ts = $Timestamp
text = "✅ Result:`n``````$answer``````"
}
Bots communicate by outputting line-delimited JSON (one JSON object per line) to stdout.
TRIGGER_MESSAGE # The full message text (includes @mention)
TRIGGER_CHANNEL # Channel ID (e.g., C01234ABCDE)
TRIGGER_TS # Message timestamp (unique ID)
TRIGGER_USER # User ID who sent the message (e.g., U01234ABCDE)
TRIGGER_USER_NAME # Username (display name)
BOT_NAME # Name of the bot from config
{"action": "post_message", "channel": "$TRIGGER_CHANNEL", "text": "Hello!"}
{"action": "post_message", "channel": "$TRIGGER_CHANNEL", "thread_ts": "$TRIGGER_TS", "text": "Reply"}
{"action": "post_message", "channel": "$CHANNEL", "text": "Processing...", "store_as": "msg1"}
{"action": "update_message", "channel": "$CHANNEL", "message_ref": "msg1", "text": "Done!"}
{
"action": "post_blocks",
"channel": "$TRIGGER_CHANNEL",
"thread_ts": "$TRIGGER_TS",
"text": "Fallback text",
"blocks": [
{
"type": "header",
"text": {"type": "plain_text", "text": "📊 Report"}
},
{
"type": "section",
"text": {"type": "mrkdwn", "text": "*Status:* ✅ Success"}
}
]
}
{"action": "delete_message", "channel": "$CHANNEL", "message_ref": "msg1"}
See DESIGN.md for complete protocol documentation.
Location: scripts/test-bot.ps1
Demonstrates all response types:
Trigger: Send test ps in configured channel
Location: TestBotCli/
Demonstrates:
Trigger: Send test cs in configured channel
# Publish the app
dotnet publish -c Release -o C:\SlackServer
# Copy config.yaml to publish directory
copy config.yaml C:\SlackServer\
# Create Windows service
sc.exe create SlackServer binPath="C:\SlackServer\SlackServer.exe" start=auto
sc.exe start SlackServer
# Publish
dotnet publish -c Release -o /opt/slackserver
# Copy config
cp config.yaml /opt/slackserver/
# Create service file: /etc/systemd/system/slackserver.service
[Unit]
Description=SlackServer Bot Framework
After=network.target
[Service]
Type=notify
WorkingDirectory=/opt/slackserver
ExecStart=/usr/bin/dotnet /opt/slackserver/SlackServe