shhac/agent-skills · Archived

agent-slack

Read and act on Slack from the terminal: permalinks, threads, history, unreads, saved-for-later, canvases, and workflows; message and file search; attachment downloads; user lookup; channel listing and creation; DMs; sending, editing, deleting, scheduling, and reacting; and raw Slack API calls. Use when asked to fetch a Slack message URL, read a thread or channel, check unreads, search Slack, post or edit a message, invite someone to a channel, or run a workflow.

First seen Jul 7, 2026

Installation

$ npx skills add shhac/agent-skills --skill agent-slack

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from shhac/agent-skills · top by installs.

npx skills add shhac/agent-skills

Browse all from shhac/agent-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsBash(agent-slack *) Read

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 12,655 B
  • docs SUMMARY.md 486 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 9 installs

SKILL.md

agent-slack

JSON in, JSON out, no interactivity. Lists are NDJSON (one object per line, then {"@pagination":…} / {"@referencedusers":…} meta lines). Entity gets — user get, channel get, usergroup get, emoji get — accept 1..N ids and emit NDJSON by default: one result line per id in input order, either the record or {"@unresolved":{"id","reason","fixableby","hint"?}} for an id that couldn't be resolved. Item-level misses exit 0; only a command-level failure (auth, network) exits 1. --format json on a single get returns the pretty object; --format json on multi collapses to {"data":[…],"@unresolved":[…]}. message get, message draft get, workflow get, and canvas get are single-arg and now emit NDJSON by default (one line); --format json|yaml returns the pretty object. config get takes 1..N keys and emits NDJSON (one line per key, or {"@unresolved":…} per miss). Errors are a single JSON object on stderr: {"error":"…","fixableby":"agent|human|retry","hint"?:"…","retryafterseconds"?:N}. fixableby=agent → fix the input and retry; human → credentials/permissions need a person; retry → transient failure, wait and re-run (retryafterseconds gives the recommended back-off when present).

Safety. Read and search freely. Do not send, edit, delete, react, schedule, invite, create channels, or add/remove emoji unless the user explicitly asked for that action. Destructive commands — message edit|delete, message draft delete, message scheduled cancel, channel new|invite, emoji add|remove — require --yes; without it they return a description of what would happen. Show that to the user before retrying with --yes.

This page covers the common paths inline. Every domain has complete, always- current detail in agent-slack <domain> usage — pull that (or the bundled references at the bottom) when a task needs a domain not shown here.

Setup (once)

agent-slack auth import-desktop            # from Slack Desktop — best, no need to quit
# …or, if you don't run Slack Desktop:
agent-slack auth import-browser firefox    # chrome|brave|firefox|zen|opera|safari
agent-slack auth test                      # am I set up? → who I am + which workspace
agent-slack auth list                      # configured credential sets (aliases)
agent-slack auth set-default acme          # if several workspaces (alias or URL)

If no import works, agent-slack auth add --workspace-url <url> --form opens a native OS dialog so the human enters the token without it appearing in chat. Never ask the user to paste a token into the conversation, and never read credentials out of the store yourself; every command authenticates internally. Env override: SLACKTOKEN (+ SLACKCOOKIED + SLACKWORKSPACE_URL for xoxc browser tokens); expired browser tokens self-heal from Slack Desktop. With several workspaces, commands use the default; pass --workspace <alias> (or any unique substring) to target another (a message permalink carries its own workspace and overrides it). Credential sets are alias-keyed — several aliases may hold the same workspace URL (e.g. two humans in one Slack). Full menu — per-browser caveats, bot tokens, cURL import: agent-slack auth usage.

Reading

agent-slack message get "https://acme.slack.com/archives/C…/p1770165109628379"   # quote it — a bare & truncates in the shell
agent-slack message get "#general" --ts "1770165109.628379"
agent-slack message list "#general" --limit 25
agent-slack message list "#general" --thread-ts "1770165109.628379"   # whole thread
agent-slack unreads --counts-only

message get returns a permalink, a thread summary {ts,length}, and downloads attachments (local paths in files[].path; --no-download to skip; lists stay metadata-only — add --download or agent-slack file download F…). Reads resolve referenced users/channels/usergroups to profiles by default (referenced_* maps); tune with --resolve none|cached|auto|fresh. --include-reactions adds reactions. Targeting rules (permalink vs #channel vs U… DM, --ts): [references/targets.md](references/targets.md). These are the common reads; reaction filters, body-length caps, and the full flag set are in agent-slack message usage.

The message body is the content field — one rendered-Markdown string merging Slack's raw text, blocks, and attachment/app-card unfurls. There is no text field in output. A row without content genuinely has no text body; re-fetching another way won't reveal more (--full shows the raw payload if you must check).

Files over MCP (agent-slack mcp): an MCP client has no filesystem, so the local paths above come back as fetchable references ({"@type":"file","root":"cache","path":"<teamid>/<userid>/downloads/F….png"}) and you read them with the bridge's built-in fs tool — no host path needed. Pass the path from the reference verbatim; downloads nest under the identity (<teamid>/<userid>/downloads/), so don't assume a bare downloads/ prefix:

fs get  cache <team_id>/<user_id>/downloads/F0BD….png   # returns the bytes (images inline as image blocks)
fs find cache -e png                                     # discover downloaded images
fs ls   cache <team_id>/<user_id>/downloads              # list a directory

get refuses files over a small inline limit. In plain-CLI use the paths are real and Read-able directly. Detail: [references/commands/message.md](references/commands/message.md).

Searching

agent-slack search messages "deploy failed" --channel "#ops" --after 2026-06-01
agent-slack search files "architecture diagram" --content-type image

File hits download automatically and report local paths you can Read.

Writing

agent-slack message send "#general" "ship it :rocket: — [release notes](https://acme.com/releases/4.2)"
agent-slack message send U05BRPTKL6A "ping"                  # DM auto-opens
agent-slack message send "<permalink>" "see the [run](https://ci.acme.com/123)"   # reply in thread
agent-slack message send "#general" "see attached" --attach ./report.md
agent-slack message react add "<permalink>" :eyes:
agent-slack message edit "<permalink>" "fixed wording" --yes        # edit/delete gated
agent-slack message delete "<permalink>" --yes

Message text is standard Markdown — bold, italic/italic, strike, ` code , fenced code, - bullets, 1. numbers, > quotes. Indent a list item to nest it (any depth; bullets and numbers mix freely, and a sub-list doesn't restart the numbering above it). Links: write label for a labeled hyperlink; an unlabeled [url](url) or <url> renders as Slack's inline link chip (the scheme-stripped pill the composer makes from a pasted URL). Don't drop a truly bare URL in and hope it renders nicely — it won't auto-link. Two gotchas: text is underline (our extension, not bold) and \ escapes a literal marker. Mentions auto-resolve: @here/@channel, @U… ids, and bare @name/@group handles. Pass --slack-markdown for Slack's native mrkdwn (bold*, <url|label>); reads return Markdown too. Read [references/formatting.md](references/formatting.md) before composing any formatted message — full table of links, mentions, escaping, and the --slack-markdown dialect. Scheduling, forwarding, and the draft hand-off flow: agent-slack message usage`.

Waiting for a reply

ts=$(agent-slack message send "#team" "deploy blocked — proceed or hold?" | jq -r .ts)
agent-slack message await "#team" --since "$ts" --events message,reaction --timeout 30m

That is the pattern for asking a human something. A person answers in one of three ways — a message in the channel, a reply threaded on your message, or just an emoji reaction on it — and you cannot predict which. The call above catches all three. Verified live: the human threaded her first answer and reacted with a custom :letsdothis: emoji.

Two things make it correct rather than lucky:

  • --since is what stops you missing the answer. Pass the ts your send

returned. It is exclusive, and it makes the command check what already arrived before it started listening — otherwise a fast reply lands in the gap between sending and waiting and is never seen. Replies threaded on that message count too, not just channel-level ones.

  • --events message,reaction — reactions are opt-in. Leave the reaction

name unfiltered and judge it yourself: ✅ ✔️ ☑️ 👍 🎉, a workspace's custom :approved:, or a plain "yes" all mean approval. If you do narrow with --reaction, read skipped — it carries the ❌ that would otherwise look like silence, and "rejected" must never be read as "no answer yet".

A timeout is not an error: exit 0, {"received": false}, and a cursor to pass as the next --since, so looping loses nothing.

agent-slack message stream --channel "#alerts" --duration 30m --idle-timeout 10m

That is the pattern for watching a channel — deploys, alerts, an incident room. NDJSON, one event per line, @summary with per-channel cursors at the end. Always bounded, so it returns.

App posts count as messages and carry author.botid with no author.userid — most alert traffic is apps, so never key on user_id alone. Both commands drop the socket's bookkeeping noise (typing, read marks, badges) and never re-emit a thread's parent when a reply arrives. Neither polls or spends rate-limit budget. stream needs browser auth; await falls back to polling on a bot token. Full flags: [references/commands/message.md](references/commands/message.md).

Finding people & channels

agent-slack channel list                      # compact; --full for raw
agent-slack channel get "#general" "#ops"     # NDJSON default (one line per id; @unresolved for misses)
agent-slack channel members "#general" --resolve auto   # who's in it
agent-slack user get @alice @bob              # NDJSON default; @unresolved per miss; exit 0
agent-slack user dm-open @alice @bob          # group DM channel id

Other domains

Each has full detail in agent-slack <domain> usage — read it only when the task needs that domain (so finding a user never makes you load emoji, etc.):

Domain For Detail
usergroup subteams (@group): list / get / members agent-slack usergroup usage
emoji custom emoji: list / get / search; add / remove (--yes) agent-slack emoji usage
message draft · scheduled hand-off drafts for a human; scheduled sends agent-slack message usage
workflow discover and run Slack workflows agent-slack workflow usage
canvas fetch a canvas as Markdown agent-slack canvas usage
later saved-for-later (Slack's Later tab) agent-slack later usage
file point-pull a file (F…) seen in any output agent-slack file usage
cache · config inspect / warm / purge the cache; persist TTLs agent-slack cache usage
api raw Slack API escape hatch (api call <method>) agent-slack api usage

The resolution cache (channel/user/handle/workflow/emoji lookups) fills automatically as you work and is transparent — reach for cache only to pre-warm (cache warm) or clear it.

More detail

  • Live, always-current: agent-slack usage (overview) and

agent-slack <domain> usage (per-domain — the authoritative source).

  • Bundled deep-dives:

[references/commands.md](references/commands.md) — full command map, split per domain, with flags and --yes gates · [references/targets.md](references/targets.md) — targeting and multi-workspace · [references/formatting.md](references/formatting.md) — Markdown, mentions, --slack-markdown · [references/output.md](references/output.md) — NDJSON/meta contract, --full, payload shapes, cache.