Skip to content
Back to skills

Slack

ASecurity

Use when AI encounters Slack permalinks (https://*.slack.com/archives/...), Slack IDs (C.../U.../D.../F...), thread 讨论上下文, 搜索 Slack 历史消息, 按邮箱/handle 反查用户, 浏览频道最近动态, 下载 Slack 附件(截图/日志/CSV/PDF), 或需要把 @handle / #name / ^subteam 解析成 ID 时.

  • 52 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added May 27, 2026
developmentpythongojavashellbashsqlreactgitapi

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 20 files and shows the line behind each finding

Scanned May 27, 2026

npx -y skills add Innei/Kagura --skill slack --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Slack?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Slack
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/innei-slack/badge)](https://www.skillsdirectory.com/skills/innei-slack)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: slack
description: >-
  Use when AI encounters Slack permalinks (https://*.slack.com/archives/...),
  Slack IDs (C.../U.../D.../F...), thread 讨论上下文, 搜索 Slack 历史消息,
  按邮箱/handle 反查用户, 浏览频道最近动态, 下载 Slack 附件(截图/日志/CSV/PDF),
  或需要把 @handle / #name / ^subteam 解析成 ID 时.
---

# Slack Skill

只读 Slack Web API 的 9 个子命令封装,统一入口 `scripts/slack.py`。
**不写消息 / 不加 reaction / 不 mark-read** —— 这些动作由调用方 Bot 自己处理,client 层有硬编码白名单拦截。

---

## When to Use

**触发信号**(AI 看到任一信号即考虑调用):

- `https://*.slack.com/archives/...` 链接
- `C[A-Z0-9]{8,}` / `U[A-Z0-9]{8,}` / `D[A-Z0-9]{8,}` / `F[A-Z0-9]{8,}` 风格 ID
- `p123456789012345` 风格的消息 ts
- 用户提到 "Slack" / "thread" / "频道" / "群里" / "@某人 在 Slack 说"
- Jira/PR 正文里的 Slack permalink(排查类任务需要 QA/RD 讨论上下文)

**术语对照**:

| 用户说法 | 含义 |
|---|---|
| slack / 消息 / DM / 频道 / thread / permalink | 本 skill |
| Slack URL `https://xxx.slack.com/archives/...` | `get` / `replies` / `files_download --url` 入参 |
| `@handle` / `@name` / `#channel` / `^subteam` | `resolve` / `users` / `channels` 入参 |
| `ts` / `thread_ts` | Slack 时间戳 ID(`1234567890.123456`) |

---

## Quick Reference

**入口**:

```
.agent-slack/skills/slack/scripts/slack.py
```

查找顺序:`./.agent-slack/skills/slack/scripts/slack.py` → `<git-root>/.agent-slack/skills/slack/scripts/slack.py` → `<git-root>/slack/scripts/slack.py`(仓库开发路径)→ `find . -path '*skills/slack/scripts/slack.py'`。

**所有调用** = `python3 <path> <subcommand> [flags]`;**禁止** `import sk.*` 绕过入口。

**子命令表**:

| 子命令 | 作用 | 典型入参 |
|---|---|---|
| `get` | 读单条消息 | `--url <permalink>` |
| `replies` | 读整个 thread | `--url <任一消息 permalink>` |
| `history` | 浏览频道最近消息 | `--channel <#name\|C...>` `--limit <n\|1d\|2h>` |
| `search` | 全域搜消息(xoxp 专属) | `<query 字符串,原生 modifier>` |
| `files_download` | 下附件 | `--file-id F...` 或 `--url <permalink>` |
| `channels` | 搜/列频道(走 cache) | `--query <name>` / `--type public` |
| `users` | 查人(ID/email/name) | `--id U...` / `--email ...` / `--query <name>` |
| `resolve` | 字符串 → 对象 | `resolve "#eng"` / `"@alice"` / `"^oncall"` / `U.../C.../F.../email` |
| `cache_refresh` | 刷本地 users/channels/subteams 字典 | — |

每条都支持 `--help`。大输出用 `--output <file>`(stdout 只打 `saved: <path>`)。

---

## Setup

| 项 | 说明 |
|---|---|
| Python | ≥ 3.9 |
| 依赖 | **无**(只用标准库 `urllib`,零 `pip install`) |
| 配置 | 复制 `slack/.env.example` → `slack/.env`,至少填 `SLACK_BOT_TOKEN` |

**Token 路由**(client 自动挑):

| 操作 | Token 优先级 |
|---|---|
| 除 `search` 外全部 | `SLACK_BOT_TOKEN` → `SLACK_USER_TOKEN` → `SLACK_TOKEN` |
| `search` | `SLACK_USER_TOKEN` → `SLACK_TOKEN`(**必须 xoxp**,bot token 会被 Slack 拒) |

**Cache 自动刷新**(Chunk 4):`channels` / `users --query` / `resolve "#name|@handle|^handle"` 在 cache 不存在或 > TTL 时会同步刷一次;单条 lookup(`users --id/--email`、`resolve U.../C.../email`)走 live API,不触发刷新。消息类命令(`get`/`replies`/`history`/`search`)**不会**自动刷新,避免高频放大成全量 `users.list`。

Cache 环境变量:`SLACK_SKILL_CACHE_TTL=<秒>`(默认 3 天)、`SLACK_SKILL_CACHE_NO_AUTO=1`(关自动刷新)、`SLACK_SKILL_CACHE_DIR=<path>`(覆盖默认 `$PWD/.agent-slack/cache/slack/`)。

---

## Recipes

所有响应形状:消息对象一律含 `ts` / `author` / `text_raw`(保留 `<@U>` `<#C>` 原始 token)/ `text_rendered`(`@name` `#channel` 还原,Block Kit 走 Markdown)/ `blocks_rendered` / `files` / `reactions` / `raw`(原始 payload)。**二次处理用 `text_raw`,喂 AI/人读用 `text_rendered`**。

### 读消息 / thread

```bash
# 单条
python3 slack/scripts/slack.py get --url "<permalink>"

# 整个 thread(permalink 任意一条即可)
python3 slack/scripts/slack.py replies --url "<permalink>" [--limit 20] [--output /tmp/t.json]
```

`replies --limit` 算的是 **回复数**,root 总是返回。

### 浏览频道

```bash
# 按条数
python3 slack/scripts/slack.py history --channel "#eng" --limit 20

# 按时间窗口(m/h/d/w)
python3 slack/scripts/slack.py history --channel "C08P..." --limit 1d

# 连 thread 回复一起抓(适合做"今天频道全景")
python3 slack/scripts/slack.py history --channel "#eng" --limit 1d --include-thread-replies
```

`--limit` 两种语义:纯数字 = 条数;`<n>{m|h|d|w}` = 时间窗口(不限条数)。

### 查人 / 查频道 / 一键 resolve

```bash
python3 slack/scripts/slack.py channels --query release --sort popularity --limit 10
python3 slack/scripts/slack.py users --email alice@example.com
python3 slack/scripts/slack.py resolve "@alice"       # → user
python3 slack/scripts/slack.py resolve "#eng-release" # → channel
python3 slack/scripts/slack.py resolve "^oncall"      # → subteam
python3 slack/scripts/slack.py resolve U06GM8PAFEX    # → 直接 live lookup
```

`resolve` 返回 `{ kind: user|channel|subteam, resolved, candidates?, cache_refresh? }`;拿到 id 再喂 `history --channel <id>` / `replies --url ...`。

### 全域搜索(xoxp 专属)

```bash
# query 原样透传给 Slack,原生 modifier 全可用
python3 slack/scripts/slack.py search "deploy in:#eng from:@alice after:2026-01-01" --limit 50
python3 slack/scripts/slack.py search "incident-4712" --sort timestamp --sort-dir asc --limit 200
```

`--limit` 跨页自动翻(`--max-pages` 默认 5,Slack 单页上限 100)。返回的 matches 同样走 `render` + `preload_users`。

### 下载附件

Slack 的 `url_private` **需要 Bearer token**,AI 工具层没有 token → 不下载就看不见图/PDF/CSV。

```bash
# 读消息时顺便下(最常用)
python3 slack/scripts/slack.py get --url "<permalink>" --download-files [--types image,pdf]

# 只下单个文件
python3 slack/scripts/slack.py files_download --file-id F012ABC --types all --out /tmp/f/
```

每个 `files[i]` 会被填 `local_path` / `download_category` / `download_status`,顶层有 `downloads: { total_files, downloaded, skipped, errored, files_dir }`。

**`--types` 类别**:`text`(post/snippet/md/csv/log/**源码后缀** py/js/ts/go/java/rb/json/yaml/sql …)、`image`、`video`、`audio`、`pdf`、`archive`、`other`、`all`。`--download-files` 默认走 `SLACK_SKILL_DOWNLOAD_TYPES`,缺省是 `text`(AI 上下文友好)。

**幂等**:文件名 `{file_id}{ext}`;再跑一次 → `download_status: skipped:already_exists`。想重下手动 `rm`。

---

## Common Mistakes

命令层遇 Slack API 错会打 `error: <method>: <code> | <detail>` 到 stderr,已知 code **紧跟一行 `hint: ...`**。

| Slack error | 含义 | hint |
|---|---|---|
| `channel_not_found` | 频道 ID/名不存在或 token 无权 | `slack.py channels --query <name>` 找正确 id |
| `not_in_channel` | Bot 没加该私密频道 | Slack 里 `/invite @your-bot` |
| `user_not_found` | 用户不存在或 token 看不到 | `slack.py users --query <name>` 或传完整 `U0...` |
| `not_allowed_token_type` | 该接口只收 xoxp | `search` 必须配 `SLACK_USER_TOKEN` |
| `missing_scope` | scope 不足 | 对照 `.env.example` 补 scope → 重新 Install to Workspace |
| `invalid_auth` / `not_authed` | token 无效/过期/未配 | 检查 `.env`;xoxp 可能被 SSO 失效 |
| `ratelimited` | 速率限制 | skill 已自动 Retry-After;仍超限说明并发过大 |
| `message_not_found` | permalink 指向消息不存在/已删 | **thread 回复的 permalink 必须带 `?thread_ts=<root_ts>`**;Slack UI 复制出来的天然就有,自己拼 URL 容易漏 |
| `file_not_found` | file id 不存在或 token 看不到 | 用 `get`/`replies` 响应里的 `files[].id`(F 开头) |
| `thread_not_found` | 该消息不是 thread 首帖 / 还没回复 | 改用 `get`;或传某条回复的 permalink |

**退出码**:`2` = token 缺失 / argparse 错;`3` = 触发只读白名单(调用了非白名单方法);`4` = 参数非法(格式错 / channel 不在 `SLACK_SKILL_ALLOWED_CHANNELS`);`1` = 其他(含未识别的 Slack API error)。

**Bearer token 永不出现在任何日志/错误信息**(`sk/files.py` 走 `redact()`)。

---

## NEVER

- ❌ 发消息 / 改 reaction / mark-read —— 属于调用方 Bot 的职责
- ❌ `import sk.*` 或绕过 `slack.py` 入口
- ❌ token 写进命令行 argv —— 放 `.env` 或 shell env
- ❌ 拿 `text_rendered` 做正则提数 —— 用 `text_raw`
- ❌ 对超长 thread / `history --limit 1d` / 批量 `search` 直接 stdout —— 用 `--output <file>`,否则 AI 上下文爆炸

Files in this skill

  • .env.example3 KB
  • README.md6.8 KB
  • SKILL.md8.9 KB
  • scripts/sk/__init__.py174 B
  • scripts/sk/cache.py9 KB
  • scripts/sk/channels.py3.9 KB
  • scripts/sk/cli.py5.1 KB
  • scripts/sk/client.py6.9 KB
  • scripts/sk/cmd_cache_refresh.py6.7 KB
  • scripts/sk/cmd_channels.py4.7 KB
  • scripts/sk/cmd_files_download.py6.8 KB
  • scripts/sk/cmd_get.py4 KB
  • scripts/sk/cmd_history.py7.6 KB
  • scripts/sk/cmd_replies.py4.7 KB
  • scripts/sk/cmd_resolve.py9.3 KB
  • scripts/sk/cmd_search.py6.2 KB
  • scripts/sk/cmd_users.py6.9 KB
  • scripts/sk/config.py4.1 KB
  • scripts/sk/errors.py1.5 KB
  • scripts/sk/files.py10.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.