An open API service indexing awesome lists of open source software.

https://github.com/stablyai/agent-slack

Slack automation CLI for AI agents
https://github.com/stablyai/agent-slack

agent automation cli slack

Last synced: 17 days ago
JSON representation

Slack automation CLI for AI agents

Awesome Lists containing this project

README

          

# agent-slack

Slack automation CLI for AI agents (TypeScript + Bun).

Guiding principle:

- **Token-efficient** — (compact JSON, minimal duplication, and empty/null fields pruned) so LLMs can consume results cheaply.
- **Zero-config auth** — Auth just works if you have Slack Desktop (with fallbacks available). No Python dependency.
- **Human-in-the-loop** — When appropriate (not in CI environments), loop humans in. Ex: `message draft`
image

## Getting started

Install via Bun (recommended):

```bash
curl -fsSL https://raw.githubusercontent.com/stablyai/agent-slack/main/install.sh | sh
```

OR npm global install (requires Node >= 22.5):

```bash
npm i -g agent-slack
```

OR run via Nix flake:

```bash
nix run github:stablyai/agent-slack
```

## At a glance

- **Read**: fetch a message, browse channel history, list full threads
- **Search**: messages + files (with filters)
- **Artifacts**: auto-download snippets/images/files to local paths for agents
- **Write**: reply, edit/delete messages, add reactions (bullet lists auto-render as native Slack rich text)
- **Channels**: list conversations, create channels, and invite users by id/handle/email
- **Canvas**: fetch Slack canvases as Markdown

## Agent skill

This repo ships an agent skill at `skills/agent-slack/` compatible with Claude Code, Codex, Cursor, etc

**Install via [skills.sh](https://skills.sh)** (recommended):

```bash
npx skills add stablyai/agent-slack
```

Manual installation

```bash
bash ./scripts/install-skill.sh
```

## Command map (high level)

```text
agent-slack
├── update # self-update (detects npm/bun/binary)
├── auth
│ ├── whoami
│ ├── test
│ ├── import-desktop
│ ├── import-chrome
│ ├── import-firefox
│ └── parse-curl
├── message
│ ├── get # fetch 1 message (+ thread meta )
│ ├── list # fetch thread or recent channel messages
│ ├── send # send / reply (supports --attach)
│ ├── draft [text] # open Slack-like editor in browser
│ ├── edit # edit a message
│ ├── delete # delete a message
│ └── react
│ ├── add
│ └── remove
├── channel
│ ├── list # list conversations (user-scoped or all)
│ ├── new # create channel
│ └── invite # invite users to channel
├── user
│ ├── list
│ └── get
├── search
│ ├── all # messages + files
│ ├── messages
│ └── files
├── workflow
│ ├── list # workflows bookmarked in a channel
│ ├── preview # trigger metadata (no side effects)
│ ├── get # workflow definition + form fields
│ └── run # trip a workflow trigger
└── canvas
└── get # canvas → markdown
```

Notes:

- Output is **always JSON** and aggressively pruned (`null`/empty fields removed).
- Attached files are auto-downloaded and returned as absolute local paths.

## Authentication (no fancy setup)

On macOS and Windows, authentication happens automatically:

- Default: reads Slack Desktop local data (no need to quit Slack)
- Fallbacks: if that fails, tries Chrome/Firefox extraction (macOS)

You can also run manual imports:

```bash
agent-slack auth whoami
agent-slack auth import-desktop
agent-slack auth import-chrome
agent-slack auth import-firefox
agent-slack auth test
```

Alternatively, set env vars:

```bash
export SLACK_TOKEN="xoxc-..." # browser token
export SLACK_COOKIE_D="xoxd-..." # cookie d
agent-slack auth test
```

Or use a standard Slack token (xoxb/xoxp):

```bash
export SLACK_TOKEN="xoxb-..."
agent-slack auth test
```

## Targets: URL or channel

`message get` / `message list` accept either a Slack message URL or a channel reference:

- URL: `https://workspace.slack.com/archives//p[?thread_ts=...]`
- Channel: `#general` (or bare `general`) or a channel ID like `C0123...`

In practice:

```bash
# Get a single message by channel + ts
agent-slack message get "#general" --ts "1770165109.628379"

# List a full thread by channel + thread root ts
agent-slack message list "#general" --thread-ts "1770165109.000001"
```

If you have multiple workspaces configured and you use a channel **name** (`#channel` / `channel`), you must pass `--workspace` (or set `SLACK_WORKSPACE_URL`).
`--workspace` accepts a full URL or a unique substring selector:

```bash
agent-slack message get "#general" --workspace "https://stablygroup.slack.com" --ts "1770165109.628379"
agent-slack message get "#general" --workspace "stablygroup" --ts "1770165109.628379"
```

## Examples

> [!TIP]
> You should probably just use the skill for your agent instead of reading below.

### Read messages / threads

```bash
# Single message (+ thread summary if threaded)
agent-slack message get "https://workspace.slack.com/archives/C123/p1700000000000000"

# Full thread for a message
agent-slack message list "https://workspace.slack.com/archives/C123/p1700000000000000"

# Recent channel messages (browse channel history)
agent-slack message list "#general" --limit 20

# Recent channel messages that are marked with :eyes:
agent-slack message list "#general" --with-reaction eyes --oldest "1770165109.000000" --limit 20

# Recent channel messages that do not have :dart:
agent-slack message list "#general" --without-reaction dart --oldest "1770165109.000000" --limit 20
```

Optional:

```bash
# Include reactions + which users reacted
agent-slack message get "https://workspace.slack.com/archives/C123/p1700000000000000" --include-reactions
```

### Draft a message (browser editor)

Opens a Slack-like WYSIWYG editor in your browser for composing messages with full formatting support (bold, italic, strikethrough, links, lists, quotes, code, code blocks).

```bash
# Open editor for a channel
agent-slack message draft "#general"

# Open editor with initial text
agent-slack message draft "#general" "Here's my update"

# Reply in a thread
agent-slack message draft "https://workspace.slack.com/archives/C123/p1700000000000000"
```

After sending, the editor shows a "View in Slack" link to the posted message.

### Reply, edit, delete, and react

```bash
agent-slack message send "https://workspace.slack.com/archives/C123/p1700000000000000" "I can take this."
agent-slack message send "#alerts-staging" "here's the report" --attach ./report.md
agent-slack message edit "https://workspace.slack.com/archives/C123/p1700000000000000" "I can take this today."
agent-slack message delete "https://workspace.slack.com/archives/C123/p1700000000000000"
agent-slack message react add "https://workspace.slack.com/archives/C123/p1700000000000000" "eyes"
agent-slack message react remove "https://workspace.slack.com/archives/C123/p1700000000000000" "eyes"
```

Channel mode requires `--ts`:

```bash
agent-slack message edit "#general" "Updated text" --workspace "myteam" --ts "1770165109.628379"
agent-slack message delete "#general" --workspace "myteam" --ts "1770165109.628379"
```

Attach options for `message send`:

- `--attach ` upload a local file (repeatable)

### List, create, and invite channels

```bash
# List conversations for current user (users.conversations)
agent-slack channel list

# List conversations for a specific user
agent-slack channel list --user "@alice" --limit 50

# List all workspace conversations (conversations.list)
agent-slack channel list --all --limit 100

# Create a public channel
agent-slack channel new --name "incident-war-room"

# Create a private channel
agent-slack channel new --name "incident-leads" --private

# Invite users by id, handle, or email
agent-slack channel invite --channel "incident-war-room" --users "U01AAAA,@alice,bob@example.com"

# Invite external Slack Connect users by email (restricted by default)
agent-slack channel invite --channel "incident-war-room" --users "partner@vendor.com" --external

# External invite with permission for invitees to invite others
agent-slack channel invite --channel "incident-war-room" --users "partner@vendor.com" --external --allow-external-user-invites
```

Notes:

- `channel list` returns a single page plus `next_cursor`; use `--cursor` to fetch the next page.
- `channel list --all` and `channel list --user` are mutually exclusive.
- `--external` maps to `conversations.inviteShared` and expects email targets.
- External invites default to restricted mode (`external_limited=true`); add `--allow-external-user-invites` to disable that restriction.
- External invites require Slack Connect permissions/scopes in your workspace.

### Message get vs list

**`message get`** fetches a single message. If the message is in a thread, it also returns thread metadata (reply count, participants) but **not** the full thread contents:

```json
{
"message": { "ts": "...", "text": "...", "user": "U123", ... },
"thread": { "ts": "...", "length": 6 }
}
```

**`message list`** fetches all replies in a thread, or recent channel messages when no thread is specified. Use this when you need the full conversation:

```json
{
"messages": [
{ "ts": "...", "text": "...", "user": "U123", ... },
{ "ts": "...", "text": "...", "user": "U456", ... }
]
}
```

When to use which:

- Use `get` to check a single message or see if there's a thread worth expanding
- Use `list` to read an entire thread conversation
- Use `list` on a channel (without `--thread-ts`) to browse recent channel messages
- Use `list` with `--with-reaction` / `--without-reaction` plus `--oldest` to filter channel history by reaction markers

### Files (snippets/images/attachments)

`message get/list` auto-download attached files to an agent-friendly temp directory and return file metadata in `message.files[]`, including `name` when Slack provides the original filename and `path` for the local download. Failed downloads keep the attachment entry, preserve `message.files[].path` with a local `.download-error.txt` file, and include `message.files[].error`. `search messages` and `search all` use the same attachment shape for message results, while `search files` skips entries whose download fails.

- macOS default: `~/.agent-slack/tmp/downloads/`

Agents can read those paths directly (e.g. snippets as `.txt`, images as `.png`).

### Search (messages + files)

```bash
# Search both messages and files
agent-slack search all "smoke tests failed" --channel "#alerts" --after 2026-01-01 --before 2026-02-01

# Search messages only
agent-slack search messages "stably ai" --user "@stablyai" --channel general

# Search files only (downloads files and returns local paths)
agent-slack search files "testing" --content-type snippet --limit 10
```

Tips:

- For reliable results, include `--channel ...` (channel-scoped search scans history/files and filters locally).
- Use `--workspace ` when using `#channel` names across multiple workspaces.

### Users

```bash
# List users (email requires appropriate Slack scopes; fields are pruned if missing)
agent-slack user list --workspace "https://workspace.slack.com" --limit 200 | jq .

# Get one user by id or handle
agent-slack user get U12345678 --workspace "https://workspace.slack.com" | jq .
agent-slack user get "@alice" --workspace "https://workspace.slack.com" | jq .
```

### Fetch a Canvas as Markdown

```bash
agent-slack canvas get "https://workspace.slack.com/docs/T123/F456"
agent-slack canvas get "F456" --workspace "https://workspace.slack.com"
```

## Developing / Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).

---



Stably


Stably


Code. Ship. Test.


Documentation ·
Homepage