You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@discountry/slack-cli

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@discountry/slack-cli

Slack automation CLI for AI agents

latest
Source
npmnpm
Version
0.6.1
Version published
Maintainers
1
Created
Source

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):

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

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

npm i -g agent-slack

OR run via Nix flake:

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 (recommended):

npx skills add stablyai/agent-slack
Manual installation
bash ./scripts/install-skill.sh

Command map (high level)

slack
├── update                         # self-update (detects npm/bun/binary)
├── auth
│   ├── whoami
│   ├── test
│   ├── import-desktop
│   ├── import-chrome
│   ├── import-firefox
│   └── parse-curl
├── message
│   ├── get   <target>             # fetch 1 message (+ thread meta )
│   ├── list  <target>             # fetch thread or recent channel messages
│   ├── send  <target> <text>      # send / reply (supports --attach)
│   ├── draft <target> [text]      # open Slack-like editor in browser
│   ├── edit  <target> <text>      # edit a message
│   ├── delete <target>            # delete a message
│   └── react
│       ├── add    <target> <emoji>
│       └── remove <target> <emoji>
├── channel
│   ├── list                        # list conversations (user-scoped or all)
│   ├── new                         # create channel
│   └── invite                      # invite users to channel
├── user
│   ├── list
│   └── get <user>
├── search
│   ├── all      <query>           # messages + files
│   ├── messages <query>
│   └── files    <query>
└── canvas
    └── get <canvas-url-or-id>     # 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:

slack auth whoami
slack auth import-desktop
slack auth import-chrome
slack auth import-firefox
slack auth test

Alternatively, set env vars:

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

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

export SLACK_TOKEN="xoxb-..."
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/<channel>/p<digits>[?thread_ts=...]
  • Channel: #general (or bare general) or a channel ID like C0123...

In practice:

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

# List a full thread by channel + thread root ts
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:

slack message get "#general" --workspace "https://stablygroup.slack.com" --ts "1770165109.628379"
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

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

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

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

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

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

Optional:

# Include reactions + which users reacted
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).

# Open editor for a channel
slack message draft "#general"

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

# Reply in a thread
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

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

Channel mode requires --ts:

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

Attach options for message send:

  • --attach <path> upload a local file (repeatable)

List, create, and invite channels

# List conversations for current user (users.conversations)
slack channel list

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

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

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

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

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

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

# External invite with permission for invitees to invite others
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:

{
  "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:

{
  "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 absolute paths in message.files[].path:

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

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

Search (messages + files)

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

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

# Search files only (downloads files and returns local paths)
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 <url-or-unique-substring> when using #channel names across multiple workspaces.

Users

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

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

Fetch a Canvas as Markdown

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

Developing / Contributing

See CONTRIBUTING.md.

Stably

Stably

Code. Ship. Test.

Documentation · Homepage


FAQs

Package last updated on 15 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts