- name
- slack-latest
- description
- Gather recent Slack messages, read threads, send replies, and upload/download files. Use when the user asks about Slack activity or wants to interact with Slack.
# Slack: gather, read, send, file upload/download
`slack.py` is a self-contained Python script (no dependencies beyond
the standard library) at `{baseDir}/slack.py`.
## Authentication
**환경변수 방식** (권장 — `~/.env.local`에 설정):
```bash
export SLACK_WORKSPACE_URL="https://WORKSPACE.slack.com"
export SLACK_TOKEN="xoxc-..."
export SLACK_COOKIE="xoxd-..."
```
환경변수가 없으면 `~/.config/skills/slack-latest/credentials.json` 파일을 읽음.
### 토큰 발급 (브라우저 cURL 복사)
1. Slack **웹 브라우저**에서 F12 → Network 탭
2. 필터에 `api/` 입력 → `*.slack.com/api/` 요청 찾기
3. 우클릭 → **Copy as cURL**
4. 토큰 저장:
```bash
pbpaste | python3 {baseDir}/slack.py auth
```
**토큰 수명:** 브라우저 로그아웃 시 만료. 인증 에러 발생하면 재설정.
검증:
```bash
python3 {baseDir}/slack.py auth-test
```
## Gather recent messages
채널 메시지 수집. **기본적으로 `--no-dm`을 사용**하여 개인 DM을 제외한다.
```bash
# 채널만 (DM 제외) — 기본 사용법
python3 {baseDir}/slack.py gather --days 3 --no-dm --out ~/tmp/slack-recent.json
# DM 포함 (사용자가 명시적으로 요청한 경우만)
python3 {baseDir}/slack.py gather --days 3 --out ~/tmp/slack-recent.json
```
Output: JSON array grouped by channel (most recently active first).
### Options
| Flag | Description |
|------|-------------|
| `--days N` | time window (default: 3) |
| `--no-dm` | **DM/group DM 제외** (채널만) |
| `--max-text N` | truncate message text in chars (default: 500) |
| `--include-ids` | add `_id`, `_uid`, `_ts` for follow-up API calls |
| `--compact` | single-line JSON (saves ~25% size) |
| `--out PATH` | output file path (default: ~/tmp/slack-recent.json) |
### Output format
```json
[
{
"channel": "#general",
"messages": [
{
"from": "홍길동", "at": "2026-03-07 12:18 KST",
"text": "배포 완료했습니다",
"replies": [
{"from": "김영희", "at": "2026-03-07 12:20 KST", "text": "확인!"}
]
}
]
}
]
```
- Messages: oldest-first (narrative order)
- Thread replies expanded inline under `replies`
- `older_replies: N` when replies fall outside time window
- Timestamps in KST (UTC+9, suffix `KST`)
## Read one channel's history (bot alert 회수 — "문제 없나?!")
`gather` 는 bot_message 를 noise 로 버려서, **봇이 쏘는 alert 채널**(서버응답체크 / cube alerts 등)을
통째 누락한다. `history` 는 단일 채널을 읽되 `--include-bot` 으로 bot alert 를 살리고,
alert 본문이 `attachments`/`blocks` 에만 있을 때도 `text` 로 복원한다. read-only.
이것이 운영 점검("문제 없나?!")에서 **P0 bot alert 회수 경로**다.
```bash
# bot alert 채널 — --include-bot 필수
python3 {baseDir}/slack.py history --channel C095PQMMW9J \
--days 14 --include-ids --include-bot --out /tmp/noti-server-history.json
```
출력은 `gather` 호환 `[{"channel","_id","messages":[...]}]` 라서 incidentcli
`slack_alert` ingest 가 바로 먹는다:
```bash
cd ~/repos/work/incidentcli
./run.sh ingest --from slack_alert --input /tmp/noti-server-history.json \
--incident-id <DENOTE_ID> --window FROM..UNTIL --out /tmp/envelope.json
./run.sh validate-output /tmp/envelope.json
```
| Flag | Description |
|------|-------------|
| `--channel` | Channel ID (required) |
| `--include-bot` | **bot_message alert 포함** (기본 제외 — alert 채널엔 필수) |
| `--days N` | time window (default: 1). 비면 7/14 로 넓혀도 됨 — **빈 결과는 정상일 수 있음** |
| `--channel-name` | 표시 이름 override (기본: conversations.info 로 해석) |
| `--include-ids` | `_uid` 추가 (`_ts`/`_id` 는 항상 포함) |
| `--max-text N` | message text truncate (default: 800) |
| `--compact` / `--out` | gather 와 동일 |
- DM 은 대상이 아니다(단일 채널 ID 만). gather 의 DM 기본 제외 원칙과 send 전 확인 원칙은 그대로 유지.
- 진짜 시스템 noise(`channel_join` 등)만 항상 skip, bot alert 는 `--include-bot` 로 제어.
## Read a single thread
```bash
python3 {baseDir}/slack.py thread --channel C0123456789 --ts 1700000000.000001
```
## Send (text, file, or both)
`send` 는 텍스트만 / 파일만 / 텍스트+파일 첨부 모두 지원. 스레드 답글도 가능.
```bash
# 텍스트만 (chat.postMessage)
python3 {baseDir}/slack.py send --channel C0123456789 --text "Hello"
# 스레드 답글
python3 {baseDir}/slack.py send --channel C0123456789 \
--thread-ts 1700000000.000001 --text "Got it"
# 파일만 업로드 (files.upload v2 — getUploadURLExternal + complete)
python3 {baseDir}/slack.py send --channel D09336BAYF7 \
--file ~/Documents/report.pdf
# 파일 + 메시지 (--text 가 initial_comment 로 들어감)
python3 {baseDir}/slack.py send --channel D09336BAYF7 \
--file ~/report.pdf \
--text "이사님, 검토 요청드립니다."
# 스레드 안에 파일 첨부
python3 {baseDir}/slack.py send --channel C0123456789 \
--thread-ts 1700000000.000001 \
--file ~/snapshot.png --text "방금 캡쳐"
```
옵션:
| Flag | Description |
|------|-------------|
| `--channel` | Channel/DM ID (required) |
| `--text` | 메시지 본문. `--file` 과 함께 쓰면 첨부 코멘트로 들어감 |
| `--file` | 업로드할 파일 경로 |
| `--title` | 파일 제목 (기본: 파일명). `--file` 없으면 무시 |
| `--thread-ts` | 스레드 답글 timestamp |
`--text` 와 `--file` 둘 다 비어 있으면 에러.
## Download a file
```bash
# 파일 ID 로 다운로드 (현재 디렉토리에 원본 파일명으로 저장)
python3 {baseDir}/slack.py get-file --file-id F0B529622S3
# Permalink URL 로도 가능 (URL 안에서 F<ID> 자동 추출)
python3 {baseDir}/slack.py get-file \
--url "https://team.slack.com/files/U092.../F0B5.../report.doc"
# 출력 경로/디렉토리 지정
python3 {baseDir}/slack.py get-file --file-id F0B529622S3 --out /tmp/report.doc
python3 {baseDir}/slack.py get-file --file-id F0B529622S3 --out ~/Downloads/
```
파일 ID 는 `gather --include-ids` 결과의 메시지에 보이는 `files[].id`, 또는
업로드 후 응답의 `permalink` URL 에서 얻을 수 있다.
## 에이전트 규칙
1. **DM은 기본 제외**: gather 시 항상 `--no-dm` 사용. 사용자가 명시적으로 DM 요청 시에만 생략
2. **메시지/파일 전송 전 확인**: `send` 실행 전 반드시 사용자 확인 (파일 첨부도 동일)
3. **다운로드 파일 위치 보고**: `get-file` 결과의 `saved` 경로를 사용자에게 알림
4. **개인정보 주의**: 수집된 메시지와 다운로드한 파일을 외부에 노출하지 않음
Voir sur GitHub