npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

agent-slack

v0.6.1

Published

Slack automation CLI for AI agents

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

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
bash ./scripts/install-skill.sh

Command map (high level)

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

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:

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

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

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

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

# 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).

# 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

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:

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 <path> upload a local file (repeatable)

List, create, and invite channels

# 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,[email protected]"

# Invite external Slack Connect users by email (restricted by default)
agent-slack channel invite --channel "incident-war-room" --users "[email protected]" --external

# External invite with permission for invitees to invite others
agent-slack channel invite --channel "incident-war-room" --users "[email protected]" --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 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)

# 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 <url-or-unique-substring> when using #channel names across multiple workspaces.

Users

# 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

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.