slack-acp

module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 8, 2026 License: MIT

README

slack-acp

CI Go Reference Go Report Card

A Slack bot that relays each Slack thread to a spawned ACP-compatible agent (fir --mode acp, claude-code, gemini-cli, etc.) over stdio.

One binary, no MCP surface, runs over Slack Socket Mode (no public webhook URL needed).

Status

Early — v0.1.x. DM and @mention work; threaded follow-ups reuse the same ACP session; agent output streams back into a single Slack message that updates as the agent thinks. Tested primarily against fir --mode acp; other ACP agents (claude-code, gemini-cli) should work but have had less shakeout. Built on the same patterns as poe-acp.

How it works

 Slack ──ws (Socket Mode)──> slack-acp ──stdio (ACP)──> agent (fir --mode acp)
  • Each Slack thread (channel_id + thread_ts) maps 1:1 to one ACP session.
  • Each session gets a stable working directory at <StateDir>/threads/<channel_id>/<thread_ts> so per-agent state (skills, MCP, auth, scratch files) stays isolated and persists across restarts.
  • A new message in the same thread reuses the existing session; a follow-up before the previous response finishes cancels the in-flight prompt.
  • Streaming output is throttled to ~1 update/sec to stay inside Slack's chat.update rate limits.
  • Permission requests from the agent are auto-approved (acp-kit's default permission policy). The bot is meant to run as a trusted, private agent — gate access at the allowed_user_ids / allowed_channel_ids boundary instead.

Setup

Install

macOS / Linux via Homebrew:

brew install kfet/ai/slack-acp

Anywhere else (Linux without Homebrew, CI, containers) — one-liner that picks the right prebuilt binary for your OS/arch, verifies its checksum against checksums.txt, and drops it in /usr/local/bin (or $HOME/.local/bin if that's not writable):

curl -fsSL https://raw.githubusercontent.com/kfet/slack-acp/main/install.sh | sh

Pin a version or install elsewhere with env overrides:

curl -fsSL https://raw.githubusercontent.com/kfet/slack-acp/main/install.sh \
    | VERSION=v0.1.0 BIN_DIR=$HOME/.local/bin sh

Or build from source: go install github.com/kfet/slack-acp/cmd/slack-acp@latest.

Slack app

The fastest path is the bundled app manifest:

  1. Go to https://api.slack.com/appsCreate New AppFrom a manifest.
  2. Pick your workspace, paste docs/slack-app-manifest.json, tweak the name if you want, Create.
  3. Basic InformationApp-Level TokensGenerate a token with scope connections:write. Save the xapp-… token.
  4. Install AppInstall to Workspace. Save the xoxb-… bot token.

The manifest already enables Socket Mode, the Messages tab (so DMs have a compose box), bot scopes, and the app_mention + message.im events.

One-shot wizard
slack-acp init

Prompts for both tokens, verifies them with auth.test, and writes $XDG_CONFIG_HOME/slack-acp/config.json and $XDG_CONFIG_HOME/slack-acp/env (both mode 0600). The env file is in the shape systemd / launchd units want (SLACK_BOT_TOKEN=…\nSLACK_APP_TOKEN=…). Flags: --bot-token / --app-token for non-interactive, --skip-verify for offline bootstrap, --force to overwrite an existing config.

Supervised service
slack-acp install-service --dry-run    # preview the unit
slack-acp install-service               # write it

Detects the platform and emits a tailored systemd-user unit (~/.config/systemd/user/slack-acp.service) on Linux or a launchd LaunchAgent plist (~/Library/LaunchAgents/dev.<user>.slack-acp.plist) on macOS, pointing at the binary, config, and env file init wrote. --force to overwrite, --goos linux|darwin to preview the other platform's unit (for production installs, ssh to the target host and run the command there so embedded paths match that host's layout). The command prints the systemctl/launchctl lines you need to enable and start the service; it deliberately doesn't run them itself.

Run

SLACK_BOT_TOKEN=xoxb-… SLACK_APP_TOKEN=xapp-… \
  slack-acp --agent-cmd "fir --mode acp"

Or with a config file:

{
  "bot_token": "xoxb-…",
  "app_token": "xapp-…",
  "agent_cmd": ["fir", "--mode", "acp"],
  "allowed_user_ids": ["U0123456"],
  "state_dir": "/var/lib/slack-acp"
}
slack-acp --config /etc/slack-acp.json

See docs/config.example.json for a full key reference. All keys are optional — tokens may be supplied via env (SLACK_BOT_TOKEN / SLACK_APP_TOKEN) and the rest fall back to built-in defaults.

slack-acp --print-paths resolves and prints the config file, state directory, and agent command without starting the bot — handy for verifying what a unit file or env will actually use.

Repository layout

cmd/slack-acp/        entry point: flags + wiring
internal/config/      JSON config loader (DisallowUnknownFields)
internal/handler/     Slack event → ACP prompt + streaming sink
internal/initcmd/     `slack-acp init` first-run wizard
internal/installsvc/  systemd / launchd supervisor unit generator
internal/router/      (channel,thread_ts) → ACP session map + GC
internal/skills/      embedded skill bundle + fir-style catalog (wraps `acp-kit/skills`)
internal/slackproto/  Socket Mode client + throttled message streamer
internal/sysprompt/   Slack-mrkdwn sysprompt composer injected per session
docs/                 design notes + Slack app manifest template

Shared ACP primitives live in github.com/kfet/acp-kit: client (ACP stdio agent process + permission gates), log (debug logger), skills (skill loader + catalog formatter). The same primitives back poe-acp, so wire-level fixes land once.

See docs/design.md for goals, non-goals, and the session-lifecycle model.

Build & test

make test        # go test ./...
make all         # vet + race + cross-builds + license check

License

MIT — see LICENSE.

Directories

Path Synopsis
cmd
slack-acp command
slack-acp is a standalone Slack bot that runs an ACP-compatible agent (e.g.
slack-acp is a standalone Slack bot that runs an ACP-compatible agent (e.g.
internal
config
Package config loads the slack-acp JSON config file.
Package config loads the slack-acp JSON config file.
handler
Package handler glues slackproto + router + acpclient: it turns inbound Slack events into ACP prompts and streams the agent's session updates back into a Slack thread message.
Package handler glues slackproto + router + acpclient: it turns inbound Slack events into ACP prompts and streams the agent's session updates back into a Slack thread message.
initcmd
Package initcmd implements the `slack-acp init` first-run wizard.
Package initcmd implements the `slack-acp init` first-run wizard.
installsvc
Package installsvc generates a supervisor unit (systemd user unit on Linux, launchd LaunchAgent plist on macOS) that runs slack-acp under a long-lived process supervisor, pointing at the config + env file that `slack-acp init` already wrote.
Package installsvc generates a supervisor unit (systemd user unit on Linux, launchd LaunchAgent plist on macOS) that runs slack-acp under a long-lived process supervisor, pointing at the config + env file that `slack-acp init` already wrote.
router
Package router maps a Slack thread (channel + thread_ts) to an ACP session inside a shared agent process.
Package router maps a Slack thread (channel + thread_ts) to an ACP session inside a shared agent process.
skills
Package skills embeds the slack-acp curated bundle and delegates loading, merging, and catalog formatting to acp-kit/skills.
Package skills embeds the slack-acp curated bundle and delegates loading, merging, and catalog formatting to acp-kit/skills.
slackproto
Package slackproto adapts slack-go's Socket Mode client to a small handler-shaped surface used by the relay.
Package slackproto adapts slack-go's Socket Mode client to a small handler-shaped surface used by the relay.
statusline
Package statusline is the Slack-mrkdwn renderer for the dev.acp-kit.status-line/v1 ACP extension.
Package statusline is the Slack-mrkdwn renderer for the dev.acp-kit.status-line/v1 ACP extension.
sysprompt
Package sysprompt builds the durable system-prompt text the relay injects into every ACP session so the agent knows its replies land in Slack and must use Slack's mrkdwn dialect rather than standard CommonMark.
Package sysprompt builds the durable system-prompt text the relay injects into every ACP session so the agent knows its replies land in Slack and must use Slack's mrkdwn dialect rather than standard CommonMark.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL