展示 HN:用于代理的 Slack 命令行界面
Show HN: Slack CLI for Agents

原始链接: https://github.com/stablyai/agent-slack

## agent-slack:AI 代理的 Slack 自动化 CLI `agent-slack` 是一个基于 TypeScript/Bun 的 CLI 工具,旨在为 AI 代理提供无缝的 Slack 集成。其核心原则是**高效的 token 输出**——提供紧凑的 JSON 响应,并去除数据中的 null/空字段,以最大限度地降低 LLM 成本。 **主要特性:** * **零配置认证:** 使用 Slack Desktop 自动认证(具有 Chrome 回退和手动选项)。 * **消息处理:** `get`(单条消息 + 线程元数据)、`list`(完整线程)、`send`(回复)和 `react` 命令。 * **搜索:** 强大的消息和文件搜索功能,具有过滤选项(频道、用户、日期、内容类型)。 * **工件:** 自动下载文件(代码片段、图片等)到本地目录,为代理提供通过绝对路径直接访问文件的能力。 * **Canvas 支持:** 获取 Slack canvases 并将其转换为 Markdown。 * **用户管理:** 列出并获取用户信息。 **安装:** `curl -fsSL https://raw.githubusercontent.com/stablyai/agent-slack/master/install.sh | sh` 或通过 `npx skills add stablyai/agent-slack`。 `agent-slack` 专为用作代理技能(与 Claude、Codex、Cursor 兼容)而设计,并优先考虑易用性和 LLM 数据处理效率。输出始终为 JSON 格式,针对经济高效的处理进行了优化。

StablyAI开发了一款新的Slack命令行工具,并在Hacker News上分享。该工具允许代理与Slack交互,无需依赖Slack官方(且通常受限)的MCP。该工具在GitHub上可用,高效利用token,无需配置(使用Slack Desktop自动认证),并且可以自动下载文件/代码片段,以及将Slack画布读取为markdown格式。 讨论强调了使用命令行工具代替MCP的“代理技能”的增长趋势,提供更大的灵活性和更容易与现有LLM API集成。然而,Slack Enterprise (Grid)用户被警告该工具可能会触发劫持检测,需要替代方案,例如使用无头浏览器。 开发者愿意解决Grid兼容性问题。用户发现该工具可用,但一些人指出了一些小的限制,例如需要在线程中进行用户ID转换才能显示用户名,开发者计划解决此问题。 也有用户提出了token导入功能的需求。
相关文章

原文

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

Guiding principle:

  • token-efficient output by default (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.
  • Read: fetch a message, detect threads, list full threads
  • Search: messages + files (with filters)
  • Artifacts: auto-download snippets/images/files to local paths for agents
  • Write: reply in thread, add reactions
  • Canvas: fetch Slack canvases as Markdown
curl -fsSL https://raw.githubusercontent.com/stablyai/agent-slack/master/install.sh | sh

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 bash ./scripts/install-skill.sh ```
agent-slack
├── auth
│   ├── whoami
│   ├── test
│   ├── import-desktop
│   ├── import-chrome
│   └── parse-curl
├── message
│   ├── get   <target>             # fetch 1 message (+ thread meta )
│   ├── list  <target>             # fetch full thread
│   ├── send  <target> <text>      # send / reply (does the right thing)
│   └── react
│       ├── add    <target> <emoji>
│       └── remove <target> <emoji>
├── 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, authentication happens automatically:

  • Default: reads Slack Desktop local data (no need to quit Slack)
  • Fallback: if that fails, tries Chrome extraction (if Slack is open in Chrome)

You can also run manual imports:

agent-slack auth whoami
agent-slack auth import-desktop
agent-slack auth import-chrome
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

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

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

Tip

You should probably just use the skill for your agent instead of reading below.

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

Optional:

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

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": { "replyCount": 5, "participants": ["U123", "U456"] }
}

message list fetches all messages in a thread (or channel history if no thread). 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

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
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 https://...slack.com when using #channel names across multiple workspaces.
# 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.


Stably

Code. Ship. Test.

Documentation · Homepage


联系我们 contact @ memedata.com