Run CLI tools (Claude Code, Kimi, shell commands) from Slack with smart output filtering and full session logging.
Slack CLI Wrapper is a bidirectional bridge between Slack and CLI tools running on your local machine. It lets you:
- π Execute commands from Slack:
run: docker ps,claude: refactor auth.js,kimi: explain this code - π¬ Interact with AI CLIs - Have full conversations with Claude Code or Kimi through Slack threads
- π Run scheduled jobs - Cron jobs that execute commands and report to Slack
- π Access full logs - Complete session output is always logged locally, retrievable on demand
- π§ Smart filtering - AI CLIs use "envelope" markers to decide what gets posted to Slack (no noise!)
[Slack #dev-channel]
Alice: claude: write tests for utils.js
Bot: π Session started (claude code) β logs: session_abc123.log
[Claude reads files, writes tests, runs them β
~200 lines of output goes to log file only]
Bot: β
Refactor complete. All 47 tests pass.
Coverage: 94% on utils.js.
Bot: β
Session complete (exit code 0)
Alice: /logs
Bot: π session_abc123.log (2.1 KB uploaded)
βββββββββββββββ WebSocket βββββββββββββββββββββββββββββββββββββββββββββββ
β Slack βββββββββββββββββββββΆβ Slack CLI Wrapper (Node.js) β
β (Cloud) β (Socket Mode) β β
βββββββββββββββ β βββββββββββββββ βββββββββββββββββββββ β
β β Slack β β CLI Runner β β
β β Listener βββββΆβ (node-pty) β β
β β (Bolt) ββββββ β β
β βββββββββββββββ βββββββββββ¬ββββββββββ β
β β β
β ββββββββββββ΄ββββββββββ β
β βΌ βΌ β
β βββββββββββββββ ββββββββββββ β
β β Envelope β β Full β β
β β Parser β β Output β β
β β (LLM mode) β β Streamer β β
β ββββββββ¬βββββββ ββββββ¬ββββββ β
β β β β
β ββββββββββΌβββββββββ βββββββββΌβββββ β
β β Slack β β Slack β β
β β (enveloped) β β (all out) β β
β βββββββββββββββββββ ββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββ
Two-Track Output Model:
- Track 1: Log β Everything is written to
logs/sessions/<sessionId>.log - Track 2: Slack β AI CLIs use envelope markers; shell commands stream everything
- Node.js 20+
- A Slack workspace where you can create apps
- Bash shell (Windows: Git Bash or WSL)
- (Optional)
claudeCLI orkimiCLI for AI features
git clone https://github.com/yourusername/slack-cli-wrapper.git
cd slack-cli-wrapper
npm install- Go to api.slack.com/apps β Create New App
- Enable Socket Mode (toggle ON)
- Generate an App-Level Token with scope
connections:write - Add Bot Token Scopes:
chat:write,channels:read,users:read - Subscribe to Bot Events:
message.channels - Install to Workspace
cp .env.example .envEdit .env:
SLACK_APP_TOKEN=xapp-... # From step 2
SLACK_BOT_TOKEN=xoxb-... # From step 2
SLACK_LISTEN_CHANNELS=C0123456789 # Channel ID(s) to listen in
ALLOWED_USER_IDS=U0123456789 # Your Slack user IDEdit config/commands.yaml:
commands:
- prefix: "run"
binary: "bash"
args: ["-c"]
mode: one-shot
envelope: false
description: "Run a shell command"
- prefix: "claude"
binary: "claude" # or full path
args: ["--verbose"]
promptFlag: "-p"
sessionIdFlag: "--session-id" # Create new session
resumeFlag: "--resume" # Continue existing session
mode: one-shot
envelope: true
description: "Run Claude Code"npm run dev # Development with hot reload
# or
npm run build # Build for production
npm start # Run production buildrun: docker ps
run: npm test
run: ls -la
Output streams directly to Slack in real-time.
claude: refactor the auth module
kimi: explain this regex
The AI sees a system prompt that teaches it to use envelope markers:
<<<SLACK:progress>>>
Analyzed auth module. Found 3 functions to refactor.
<<<END_SLACK>>>
Only enveloped messages appear in Slack. Full output is in the log.
Reply in the thread to continue the conversation with context preserved:
Alice: claude: my name is Alice
Bot: π Session started β Run Claude Code
β
Session complete (exit code 0)
Alice [in thread]: what is my name?
β Spawns continuation with --resume, Claude remembers "Alice"
How it works:
- Kimi: Uses
-S <session-id>flag (same for create and resume) - Claude: Uses
--session-id <uuid>for first call,--resume <uuid>for follow-ups - Session IDs: Deterministically generated from
slack-<channel>-<thread>so same thread always maps to same session
| Command | Description |
|---|---|
/status |
List active sessions |
/stop <id> |
Kill a session |
/logs |
Upload most recent session log |
/logs <id> |
Upload specific session log |
/logs tail 50 |
Show last 50 lines |
/logs list |
List recent sessions |
/help |
Show available commands |
| Variable | Description |
|---|---|
SLACK_APP_TOKEN |
Socket Mode connection token (xapp-...) |
SLACK_BOT_TOKEN |
Web API token (xoxb-...) |
SLACK_LISTEN_CHANNELS |
Comma-separated channel IDs |
ALLOWED_USER_IDS |
Comma-separated user IDs allowed to run commands |
SESSION_TIMEOUT_MINUTES |
Max session lifetime (default: 30) |
OUTPUT_FLUSH_INTERVAL_MS |
How often to push output (default: 2000) |
ENVELOPE_ACTIVATION_DELAY_MS |
Delay before parsing envelopes (default: 1500) |
rules:
- channels: ["C0123456789"]
users: ["*"] # Any user in ALLOWED_USER_IDS
allowed_prefixes: ["claude", "kimi", "run"]
- channels: ["C9876543210"]
users: ["U0123456789"] # Only specific user
allowed_prefixes: ["run"] # Only shell commandsjobs:
- name: "daily-backup-check"
cron: "0 6 * * *"
command: "bash scripts/backup-check.sh"
channel: "C0123456789"
cwd: "/path/to/project"slack-cli-wrapper/
βββ src/
β βββ cli/ # PTY spawn, session lifecycle
β βββ commands/ # Command parsing & routing
β βββ streaming/ # Envelope parser, streamer, log writer
β βββ scheduler/ # Cron job scheduling
β βββ security/ # Authorization & command filtering
β βββ slack/ # Bolt app, listeners, reporter
β βββ utils/ # Config, logger, formatting
βββ config/
β βββ prompts/ # System prompts for LLMs
β βββ authorization.yaml
β βββ commands.yaml
β βββ jobs.yaml
βββ scripts/debug/ # Manual debugging utilities
βββ test/ # Automated tests
npm run dev # Development mode
npm run build # Compile TypeScript
npm start # Production mode
npm test # Run unit tests
npm run test:lifecycle # Run E2E session lifecycle tests
npm run restart # Kill all node processes and restart# Unit tests for process handle
npm test
# E2E tests for session lifecycle
npm run test:lifecycle
# Integration test
node --import tsx --test test/integration.test.ts- No tokens in code - All secrets in
.env(gitignored) - User allowlist - Only configured Slack users can run commands
- Channel restriction - Bot only listens in configured channels
- Command filtering - Block dangerous patterns (
rm -rf, etc.) - Audit logging - Every command logged with user ID, timestamp, exit code
- Session timeouts - Prevent runaway processes
- Keep
.envfile secure and never commit it - Use specific user IDs in
ALLOWED_USER_IDS, not* - Restrict
allowed_prefixesper channel as needed - Review audit logs regularly:
logs/audit.log - Run with minimal permissions (don't run as root)
Contributions are welcome! Here's how to get started:
# Fork and clone
git clone https://github.com/YOUR_USERNAME/slack-cli-wrapper.git
cd slack-cli-wrapper
# Install dependencies
npm install
# Copy env template
cp .env.example .env
# Edit .env with your test Slack app tokens
# Run in dev mode
npm run dev- Fork the repository
- Create a branch for your feature:
git checkout -b feature/amazing-feature - Make your changes with clear, focused commits
- Add tests if applicable
- Update documentation if needed
- Submit a Pull Request with a clear description
- TypeScript with strict mode enabled
- Use meaningful variable names
- Add JSDoc comments for public APIs
- Keep functions focused and small
- Handle errors gracefully
- Additional CLI integrations
- Better output formatting
- Web dashboard for session logs
- More envelope types
- Plugin system for custom handlers
- Docker support
- Windows/WSL improvements
- Architecture Guide - Detailed system design
- Setup Guide - Step-by-step setup instructions
- Process Management - Handling orphaned processes
# Kill all node processes
npm run clean
# Wait 30 seconds for Slack to release connection
# Then restart
npm run dev- Check that
bash.exeis in your PATH (Windows) - Verify session logs:
logs/sessions/*.log - Run E2E tests:
npm run test:lifecycle
Slack only allows one connection per app token. If you have multiple instances running:
- Kill all node processes:
npm run clean - Wait 30 seconds
- Restart the bot
MIT License - see LICENSE file for details.
- Built with Slack Bolt framework
- Uses node-pty for PTY support
- Inspired by the need for less noisy AI CLI integrations
Made with β€οΈ for cleaner Slack integrations