pi-slack-bot

May 13, 2026 · View on GitHub

A Slack bot that exposes pi as a conversational coding agent. Chat with pi in Slack DMs — it streams responses, runs tools, manages sessions per thread, and lets you switch models, thinking levels, and working directories on the fly.

Features

  • Threaded sessions — each Slack thread gets its own pi agent session with full conversation history
  • Streaming responses — real-time updates with tool execution indicators, auto-split for long messages
  • Project picker — fuzzy-matches project names or shows buttons to pick a working directory
  • Interactive file picker — browse and select files via Slack buttons when the agent needs user input
  • Commands!model, !thinking, !cwd, !cancel, !new, !sessions, and more
  • Prompt templates — run file-based prompt templates via !prompt with a picker UI
  • Attach server — external processes can connect via WebSocket and stream to Slack threads
  • Session management — configurable limits, idle timeout, automatic cleanup

Prerequisites

  • Node.js >= 20
  • A Slack app with Socket Mode enabled (see Slack App Setup)
  • pi installed and configured
  • An LLM provider (Anthropic, AWS Bedrock, etc.) with credentials configured

Installation

git clone https://github.com/samfoy/pi-slack-bot.git
cd pi-slack-bot
npm install

Configuration

Copy the example env file and fill in your values:

cp .env.example .env

Environment Variables

VariableRequiredDefaultDescription
SLACK_BOT_TOKENBot token (xoxb-...)
SLACK_APP_TOKENApp-level token (xapp-...) for Socket Mode
SLACK_USER_IDYour Slack user ID (bot only responds to you)
PROVIDERanthropicLLM provider name
MODELclaude-sonnet-4-5Model ID
THINKING_LEVELoffThinking level: off, minimal, low, medium, high, xhigh
MAX_SESSIONS10Max concurrent sessions
SESSION_IDLE_TIMEOUT3600Idle session timeout in seconds
SESSION_DIR~/.pi-slack-bot/sessionsSession persistence directory
STREAM_THROTTLE_MS3000Min interval between Slack message updates
SLACK_MSG_LIMIT3900Max chars per Slack message before splitting
WORKSPACE_DIRS~/projectsComma-separated dirs to scan for projects
ATTACH_PORT3001WebSocket port for the attach server

Project Discovery

The bot discovers projects by scanning WORKSPACE_DIRS one level deep. For finer control, create ~/.pi-slack-bot/projects.json:

{
  "scanDirs": ["~/projects", "~/work"],
  "pin": ["~/dotfiles"],
  "exclude": ["node_modules", "CR-*"],
  "labels": {
    "my-app": "🚀 My App",
    "dotfiles": "⚙️ Dotfiles"
  }
}

Usage

npm start

Then DM your bot in Slack. The first message starts a session:

  • With a path: ~/projects/my-app fix the login bug → starts in that directory
  • With a fuzzy name: my-app fix the login bug → matches against known projects
  • Plain message: hello → shows a project picker with buttons

Commands

CommandDescription
!helpShow available commands
!newStart a fresh session (same thread)
!cancelCancel the current stream
!statusShow session info (model, cwd, message count)
!model <name>Switch model
!thinking <level>Set thinking level
!sessionsList all active sessions
!cwd <path>Change working directory (creates a new session)
!reloadReload extensions and prompt templates
!plan <idea>Start a PDD planning session
!prompt [name]Run a prompt template

Any unrecognized !command is forwarded to pi as /command (for extensions and prompt templates).

Slack App Setup

  1. Go to api.slack.com/apps and create a new app
  2. Enable Socket Mode under Settings → Socket Mode and generate an app-level token (xapp-...)
  3. Under OAuth & Permissions, add these bot token scopes:
    • chat:write
    • im:history
    • im:read
    • im:write
    • reactions:read
    • reactions:write
  4. Under Event Subscriptions, enable events and subscribe to:
    • message.im
  5. Install the app to your workspace and copy the bot token (xoxb-...)
  6. Find your Slack user ID (click your profile → "..." → "Copy member ID")

Deployment (Linux / systemd)

Use run.sh as the process entry point — it handles NODE_PATH resolution for pi packages and auto-restarts on exit code 75 (issued by !restart).

./run.sh
# or in tmux:
tmux new -d -s bot './run.sh'

Heap sizing under cgroup memory limits. Node 22 auto-sizes --max-old-space-size to roughly half the cgroup MemoryMax. Under a 1 GB systemd limit this gives V8 only ~380 MB of old-gen — not enough for several active sessions. run.sh applies a safe default (NODE_OPTIONS=--max-old-space-size=768) unless you've already set it.

If you run under systemd, add MemoryHigh generously above the heap ceiling so the kernel doesn't OOM-kill before V8 can GC:

[Service]
ExecStart=/path/to/pi-slack-bot/run.sh
Restart=on-failure
RestartSec=10
StartLimitBurst=5
StartLimitIntervalSec=300
Environment=NODE_OPTIONS=--max-old-space-size=768
MemoryHigh=1200M
MemoryMax=1500M

Adjust --max-old-space-size based on how many concurrent sessions you expect (MAX_SESSIONS × ~100–150 MB/session is a reasonable estimate).

Development

# Run tests
npm test

# Type check
npm run typecheck

# Test coverage
npm run coverage

# Check code duplication
npm run duplication

Architecture

src/
├── index.ts              # Entry point — boots Slack app + attach server
├── config.ts             # Environment variable parsing
├── slack.ts              # Slack Bolt app, event routing, project picker
├── session-manager.ts    # Session lifecycle, limits, idle reaping
├── thread-session.ts     # Per-thread pi AgentSession wrapper
├── streaming-updater.ts  # Streams agent output to Slack with throttling
├── formatter.ts          # Markdown → Slack mrkdwn conversion, splitting
├── parser.ts             # Message parsing, project discovery, fuzzy match
├── commands.ts           # !command dispatch
├── command-picker.ts     # Prompt template button picker
├── file-picker.ts        # Interactive file browser via Slack buttons
└── attach-server.ts      # WebSocket server for external session attachment

License

MIT