Skip to content

Slack Bot (Headless Builds)

The mx-workflow Slack bot turns a Mac mini into an AI-powered build assistant you chat with in Slack. Discuss ideas naturally, and when you’re ready, tell it to build. It runs the /mx:build pipeline phase-by-phase, letting you review and steer at each step — or go fully autonomous with --auto.

ModeTriggerBehavior
Conversational (default)Any message without --autoChat naturally, build when ready, review phases interactively with questions and feedback
AutoAdd --auto to your messageFire-and-forget — runs the full pipeline autonomously, streams output, posts final result
You (Slack #builds) → Slack Bot → Claude Code (per phase or full pipeline) → GitHub PR → Slack thread
ComponentRole
Slack bot (slack-bot/index.js)Listens to #builds channel and @mentions, routes thread replies to active sessions
Session manager (slack-bot/session.js)Tracks build state, persists to disk, survives restarts
Conversation orchestrator (slack-bot/interactive.js)Claude-mediated conversation handler — routes every message through Claude, triggers phases via markers
Phase prompts (slack-bot/phases.js)Conversation system prompts, per-phase Claude prompts, structured output parsers, marker detection
Runner (slack-bot/runner.js)Spawns Claude Code with --print, streams output
mx-workflowThe plugin — /mx:build handles the pipeline
launchd daemonKeeps the bot running on boot, auto-restarts on crash

The bot is a conversational AI by default. Chat naturally — discuss ideas, ask questions, brainstorm. When you’re ready to build, just say so.

You: "I've been thinking about adding a settings page to the dashboard"
Bot: "What kind of settings? Theme, notifications, profile preferences?"
You: "theme toggle and notification preferences, per-user"
Bot: "Good scope for an MVP. You could store prefs in a user_settings table..."
You: "yeah let's build that"
Bot: → Runs discovery → posts questions to thread
You: "web app, yes backend, per-user"
Bot: → Infers context → posts summary
You: "what database would you use?" ← question, not approval
Bot: "Based on the project's existing Supabase setup, I'd add a user_settings table..."
You: "ok go ahead"
Bot: → Generates PRD → posts summary with must-haves
You: "add a reset-to-defaults button" ← feedback, PRD re-generates
Bot: → Re-generates PRD → posts updated summary
You: "approved"
Bot: → Generates plan → posts summary
You: "approved"
Bot: → Builds, QA, finalizes
Bot: → Posts branch and PR link

Claude understands your intent naturally — no special keywords required. It knows when you’re asking a question vs approving vs giving feedback.

Sessions are saved to disk as JSON files. If the bot restarts while you’re chatting or reviewing, it picks up where it left off — just reply in the thread. Sessions expire after 24 hours.

Only the user who started the conversation can interact in that thread. Other users get a polite message pointing them to the session owner.

Add --auto to your message for the original fire-and-forget behavior:

"dashboard: add dark mode --auto"
  1. The bot confirms and creates a live log thread
  2. Runner spawns claude --print with /mx:build --auto
  3. /mx:build --auto runs the full pipeline — discovery, PRD, plan, build, QA
  4. Output streams to Slack every 3 seconds (debounced to avoid rate limits)
  5. On completion, the bot posts the branch name and PR link
TriggerHow
#builds channelAny message in the channel kicks off a build
@mentionMention the bot in any channel with an instruction
Slash command/build <what to build> from anywhere

Each build runs in its own directory under $MX_WORK_DIR/<project-name>/ (e.g., ~/builds/task-management-system/). Directory names are derived from the build instruction automatically. This means:

  • Builds don’t interfere with each other
  • Each project gets a readable, memorable directory name
  • Logs are stored per session in $MX_LOG_DIR/<session-id>.log

Projects are registered automatically after each build completes. The bot derives a meaningful name from the PRD (e.g., task-manager, settings-page) and logs it in .mx-mac-mini.json.

Once registered, you can reference a project by name in future conversations:

PatternExample
Project prefixtask-manager: add dark mode
First wordtask-manager add export feature
Explicit flag--repo task-manager add export
New projectBuild a new SaaS billing system (creates fresh)

No manual project registration required — just build something and it’s available by name.

The build pipeline automatically selects the right strategy based on plan complexity:

SignalStrategy
3+ independent components, separate concerns, or 10+ cross-domain file changesAgent Team (parallel multi-agent build)
Focused on a single concern, < 10 files, linear dependenciesSingle Agent (sequential build)

You can override at the plan review stage if you prefer a different approach.

Run /mx:setup-mac-mini on day one. It handles everything in 5 phases:

PhaseWhat it does
1. System prerequisitesChecks and installs Homebrew, Node.js 20+, Claude Code CLI, Git/SSH, tmux, Tailscale, mx-workflow plugin
2. Slack integrationGuides you through creating a Slack app, collects tokens, writes .env, auto-detects bot user ID, tests connection
3. Daemon setupConfigures launchd to run the bot on boot with auto-restart
4. Verification + summaryTests Slack connection, Claude Code readiness, shows final report

No project registration phase — projects register themselves after each build.

For manual reference, see slack-bot/SETUP.md.

Tail live build logs from your MacBook:

Terminal window
# All bot output
ssh mac-mini "tail -f ~/builds/.logs/slack-bot.log"
# Specific build session
ssh mac-mini "tail -f ~/builds/.logs/<session-id>.log"

To update the bot after pulling new mx-workflow changes:

Terminal window
cd ~/mx-workflow && git pull
cd slack-bot && npm install
launchctl stop com.joshtune.mx-workflow-slack-bot
launchctl start com.joshtune.mx-workflow-slack-bot

No reconfiguration needed — .env, .mx-mac-mini.json, and the daemon plist are preserved.

  • macOS (Mac mini, headless)
  • Node.js 20+
  • Claude Code CLI
  • mx-workflow plugin installed
  • GitHub SSH configured
  • Slack workspace with a bot app
  • @slack/bolt v4+ (installed automatically via npm install)