Skip to content
Back to skills

Slackx

ASecurity

Use the `slackx` CLI to cache and read Slack threads, channel history, DMs, users, and channels from a local SQLite database. It fetches threads via `conversations.replies`, channel history via `conversations.history`, and workspace users/channels, storing everything locally so subsequent reads are instant and incremental. Trigger when the user wants to read, cache, refresh, or poll a Slack thread or channel, render a thread with human-readable author names, search the workspace and cache mat...

  • 10 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 6, 2026
securitypythongobashsqlreacttestinggitapidatabase

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 6, 2026

npx -y skills add tomzx/agents --skill slackx --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Slackx?

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

Security grade badge for Slackx
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tomzx-slackx/badge)](https://www.skillsdirectory.com/skills/tomzx-slackx)

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: slackx
description: >
  Use the `slackx` CLI to cache and read Slack threads, channel history, DMs,
  users, and channels from a local SQLite database. It fetches threads via
  `conversations.replies`, channel history via `conversations.history`, and
  workspace users/channels, storing everything locally so subsequent reads are
  instant and incremental. Trigger when the user wants to read, cache, refresh,
  or poll a Slack thread or channel, render a thread with human-readable author
  names, search the workspace and cache matches, or says "slackx" explicitly.
  Other Slack skills (slack-resolve-threads,
  slack-kb-channel, slack-kb-individual) build on top of this tool.
cli: slackx
---

# slackx Skill

`slackx` is a small Python CLI (package name `slack-cached`) that caches Slack
threads, channel messages, DMs, users, and channels to a local SQLite database.
Given a Slack permalink (or a channel and root timestamp), it fetches the thread
via `conversations.replies` and stores every message. On subsequent runs it only
fetches new replies (and detects edits) by passing `oldest` to the API based on
the highest cached `ts`.

It is the single source of Slack thread content for the other Slack skills:
`slack-resolve-threads` reads threads through `slackx conversations show`, and
the knowledge-base skills use it to cache and render conversations.

---

## Command tree

The CLI is grouped into subcommands. The old flat commands (`fetch`, `show`,
`search`, `poll`, `fetch-users`, `fetch-channels`, `show-users`,
`show-channels`, `show-channel`) no longer exist.

```
slackx
  conversations   fetch | show | search | poll
  channels        fetch | list
  users           fetch | list
  cache           status | clear
  serve
```

Every command takes `--help` (or `-h`) and shows its own options and
positional arguments.

### Options live on the leaf command

`--db`, `--workspace`, `--api-base-url`, and `--log-level` are options on each
leaf command, not on `slackx` itself. Put them after the command:

```bash
slackx cache status --db /tmp/x.db --log-level debug
slackx users list --json --workspace acme
```

The equivalent environment variables (for example `SLACK_API_BASE_URL`) still
apply process-wide and are the easiest way to point every command at an
alternate API. There is no top-level `-v/--verbose`; use `--log-level`
(`debug`, `info`, `warning`, `error`, `critical`, default `info`).

---

## Prerequisites

### Binary

Check whether the binary is on PATH; install from the source repo if not:

```bash
if ! command -v slackx &>/dev/null; then
  git clone https://github.com/TomzxCode/slackx /tmp/slackx
  uv tool install /tmp/slackx
fi
```

The install provides two binaries, `slackx` and `slack-fake-server`. If
`uv tool install` isn't desired, run it in place with
`uv run --project /tmp/slackx slackx ...`. Confirm it works: `slackx --help`.

### Authentication

Credentials are loaded in this order:

1. A `.env` file in the current working directory, if present. Source it before
   invoking `slackx` so the variables become real environment variables:
   ```bash
   if [[ -f .env ]]; then
     set -a
     source .env
     set +a
   fi
   ```
   The file uses `KEY=VALUE` lines (same keys as below). Existing environment
   variables always win over `.env` values, so explicit exports or CI secrets
   are never overridden.
2. Environment variables: `SLACK_TOKEN` (and optional `SLACK_COOKIE` for
   xoxc/web-client tokens).
3. A config file at `$XDG_CONFIG_HOME/slackx/config`
   (defaults to `~/.config/slackx/config`).
   It uses a simple `KEY=VALUE` format:
   ```
   SLACK_TOKEN=xoxb-...
   SLACK_COOKIE=...
   SLACK_API_BASE_URL=https://slack.com/api
   ```

An `xoxc-` browser token also requires its matching `xoxd-` d cookie
(`SLACK_COOKIE`); both values must come from the same browser session. Bot
tokens (`xoxb-`) only need `SLACK_TOKEN`.

### Cache location

Each Slack workspace gets its own cache database at
`$XDG_CACHE_HOME/slackx/<workspace>/threads.db` (or
`~/.cache/slackx/<workspace>/threads.db`). The workspace is discovered
automatically via `auth.test`; select one explicitly with `--workspace <name>`,
or point at a specific file with `--db /path/to/file.db`.

---

## Targeting a conversation

`conversations fetch` and `conversations show` take a `TARGET` positional that
is one of:

- a Slack permalink (thread or channel),
- a channel id (`C...`, `G...`, `D...`), a channel name (e.g. `general`), or a
  `#`-prefixed name (e.g. `#general`),
- a DM, given a user id (e.g. `U001`) or an `@handle`.

Add `--ts <root_ts>` to read a specific thread from a channel or DM target.
Without `--ts`, the command operates on the channel's recent messages.

Run `slackx channels fetch` first if you want to resolve channels by name, and
`slackx users fetch` to resolve `@handle` DMs.

---

## Conversations

### Fetch (cache or refresh)

`conversations fetch` always reaches out to Slack. It prints a summary; the
summary and logs go to stderr, and no conversation output goes to stdout.

```bash
# a thread by permalink
slackx conversations fetch https://acme.slack.com/archives/C0123ABCDEF/p1700000000123456

# a thread by channel and ts
slackx conversations fetch C0123ABCDEF --ts 1700000000.123456

# recent channel messages (lookback defaults to 1d)
slackx conversations fetch C0123ABCDEF
slackx conversations fetch C0123ABCDEF --last 7d

# every reply for every thread in the channel
slackx conversations fetch C0123ABCDEF --full-threads --last all
```

`--last` accepts `24h`, `2d5h30m`, `90m`, or `all` for full history.

### Show (read from cache)

`conversations show` prints a thread or channel to stdout (human-readable by
default). It auto-fetches when not already cached; pass `--no-fetch` to read
only the cache.

```bash
slackx conversations show https://acme.slack.com/archives/C0123ABCDEF/p1700000000123456
slackx conversations show --json https://acme.slack.com/archives/C0123ABCDEF/p1700000000123456
slackx conversations show C0123ABCDEF --ts 1700000000.123456 --jsonl >> threads.jsonl
slackx conversations show C0123ABCDEF --last all
slackx conversations show C0123ABCDEF --last all --with-thread-message
```

Options:

- `--fetch/--no-fetch`: auto-fetch on a cache miss (default on).
- `--json`: pretty-printed JSON.
- `--jsonl`: the whole payload as a single compact JSON line, easy to append to
  a file.
- `--with-thread-message`: when showing a channel, also include thread replies,
  rendered marked as belonging to their thread (default is top-level messages
  only).
- `--last`: channel lookback window (default `1d`).

Output shapes:

- **thread `--json`**: keys `channel`, `channel_name`, `thread_ts`,
  `message_count`, `messages`. Each message carries `ts`, `user`, `text`,
  `user_name`, and the full Slack `payload` (including `reactions`).
- **channel `--json`**: keys `channel`, `channel_name`, `message_count`,
  `messages`. Each message carries `ts`, `user`, `text`, `thread_ts`,
  `is_thread_reply`, `user_name` (no full `payload`).
- **human**: one block per message with timestamp, author, and text.

When the thread's authors are present in the cached users, `show` renders their
real name and handle (e.g. `Alice Smith (alice)`) instead of raw user ids. Run
`slackx users fetch` once to populate names.

### Search

Search the workspace with the same query syntax as the Slack search box. Every
matched message is cached under its `(channel, thread_ts)` so it can be
revisited later with `show`. Search is always a live API call.

```bash
slackx conversations search "deploy failed"
slackx conversations search "from:@alice after:2024-01-01" --json
slackx conversations search "incident" --jsonl
slackx conversations search "incident" --full-threads
```

Options:

- `--count`: maximum results per page (default 20).
- `--limit`: maximum total matches to fetch (default 200; `0` for no limit).
  Broad queries can span hundreds of pages, so the cap keeps them from taking a
  long time under Slack's rate limits.
- `--sort` (`score` or `timestamp`, default `timestamp`) and `--sort-dir`
  (`asc` or `desc`, default `desc`).
- `--full-threads`: also fetch every reply for each matched thread.
- `--fields`: comma-separated fields to include, in order:
  `channel,channel_name,ts,thread_ts,user,user_name,text,permalink,payload`
  (default `channel,channel_name,ts,thread_ts,user,user_name,text,permalink`).
- `--json` / `--jsonl`.

`after:` and `before:` are exclusive date bounds. To search a single day
(e.g. `2026-09-18`), bracket it with the day before and the day after:
`after:<prev-day> before:<next-day>`, since `after:2026-09-18` would exclude
that day itself.

```bash
slackx conversations search "after:2026-09-17 before:2026-09-19" --json
```

The `--json` payload has keys `query`, `match_count`, `matches`, where each
match carries the configured fields.

### Poll

Poll multiple channels concurrently in a loop for new messages. Uses
`httpx.AsyncClient` with an `asyncio.Semaphore` for concurrent, non-blocking
HTTP requests. Reads `X-RateLimit-Remaining` headers to proactively throttle
before hitting 429s. Stops gracefully with `Ctrl+C`.

```bash
slackx conversations poll --channels C001,#general,random --interval 5m --last 5m --concurrency 3
```

`--channels` is required. Each entry may be a channel id, a bare name, or a
`#`-prefixed name. Names are resolved against cached channels, so run
`slackx channels fetch` first if resolving by name. Add `--full-threads` to
expand threads, and `--json` for per-cycle JSON summaries on stdout.

---

## Channels

Cache or refresh every visible channel, or a single channel by id or name:

```bash
slackx channels fetch
slackx channels fetch C001
```

Print cached channels (human-readable by default, `--json` for pretty JSON,
`--jsonl` for a single compact JSON line). Pass a channel id, name, or URL to
show only that channel; it is fetched from Slack via `conversations.info` when
not cached, unless `--no-fetch` is given.

```bash
slackx channels list
slackx channels list C001 --json
slackx channels list general --jsonl
slackx channels list https://acme.slack.com/archives/C001
```

Options: `--fetch/--no-fetch`, `--limit` (0 for all), and `--fields`
(`id,name,is_private,display_name,fetched_at,payload`, default
`id,name,is_private`). The `--json` payload has keys `channel_count` and
`channels`.

Unknown or inaccessible channels surface a clean `channel_not_found` error
(exit code 1) rather than a traceback.

---

## Users

Cache or refresh every workspace user, or a single user by id:

```bash
slackx users fetch
slackx users fetch U001
```

Print cached users (human-readable by default). Pass a user id to show only
that user; it is fetched from Slack via `users.info` when not cached, unless
`--no-fetch` is given.

```bash
slackx users list
slackx users list --json
slackx users list --jsonl
slackx users list U001 --json
```

Options: `--fetch/--no-fetch`, `--limit` (0 for all), and `--fields`
(`id,name,real_name,fetched_at,payload`, default `id,name,real_name`). The
`--json` payload has keys `user_count` and `users`.

---

## Cache management

Inspect and clear the local cache without calling Slack.

```bash
slackx cache status
slackx cache status --json
slackx cache status --jsonl
```

`cache status` prints counts and last update per entity (channels, users,
threads, messages).

```bash
slackx cache clear                 # asks for confirmation on a TTY
slackx cache clear messages
slackx cache clear channels --yes
slackx cache clear users -y
slackx cache clear all --yes
```

`cache clear` takes an optional `TARGET` of `all` (default), `messages`,
`channels`, or `users`, and `--yes/-y` to skip the confirmation prompt.
Clearing messages also clears their thread metadata, so the threads are
refetched on next use.

---

## Web UI

Browse the cached database through a local Slack-like web UI (Ctrl+P jumps
between channels and conversations; refresh buttons trigger live fetches when
credentials are configured):

```bash
slackx serve --port 8280
slackx serve --host 0.0.0.0 --port 8280
```

---

## URL parsing

`slackx` accepts Slack archives URLs in these forms:

- `https://<workspace>.slack.com/archives/<CHANNEL_ID>` (channel, fetches
  history)
- `https://<workspace>.slack.com/archives/<CHANNEL_ID>/p<PTS>` (thread, where
  `p<PTS>` is the timestamp with the dot removed)
- `https://<workspace>.slack.com/archives/<CHANNEL_ID>/p<PTS>?thread_ts=<TS>`
  (a reply permalink; the thread root `ts` is taken from `thread_ts` so the
  whole thread is fetched)

When the URL points at a reply, the message timestamp in the path is the
reply's `ts`, and the actual thread root `ts` is in the `thread_ts` query
parameter. The tool returns the thread root so `conversations.replies` fetches
the entire thread.

For explicit channel ids without a URL, pass the channel id as the target
(optionally with `--ts <TS>` for a single thread).

---

## Refresh behavior

`conversations fetch` always reaches out to Slack. If the thread is already
cached, it requests `conversations.replies` with `oldest=<latest_cached_ts>` so
the API returns only new replies (and any recent edits at that boundary).
Messages are upserted by `ts`, so edits replace the older version in place.

For a channel target, `fetch` requests `conversations.history` with
`oldest=<now - lookback>`, so only recent top-level messages are fetched. Each
top-level message is stored as its own thread root; messages with replies are
expanded via `conversations.replies` when `--full-threads` is given.

HTTP 429 / `ratelimited` responses are retried automatically with exponential
backoff (up to 5 attempts), respecting the `Retry-After` header.

---

## Fake Slack server (testing)

A built-in fake Slack API server for testing and development:

```bash
uv run slack-fake-server --port 8199 --num-threads 50
```

It serves deterministic workspace data (`conversations.list`,
`conversations.replies`, `conversations.history`, `conversations.info`,
`users.list`) and can simulate Slack-tier rate limiting with `--rate-limits`.
Other options include `--host`, `--seed`, `--num-users`, `--num-channels`,
`--num-ims`, `--messages-per-thread`, `--activity-ratio`, and `--epoch-base`.

Point `slackx` at it with the API base URL option on the leaf command (or the
environment variable):

```bash
slackx conversations fetch C001 --api-base-url http://localhost:8199/api
```

---

## Tips

- Run `slackx users fetch` once at the start of a session so every later `show`
  renders author names instead of raw user ids.
- Use `conversations show --json` on a thread when a consuming skill needs the
  full Slack `payload` (e.g. `reactions` on the root message for
  `slack-resolve-threads`).
- Use `--jsonl` when appending many threads to a single file for batch
  processing.
- `show` auto-fetches on a cache miss, but an existing cached thread only
  refreshes on its reply boundary. Run an explicit `conversations fetch` first
  when you need the current live state.
- Run `slackx channels fetch` before `conversations poll` if you want to
  reference channels by name instead of id.
- For inline review comments or PR operations, use `ghx`, not this tool; this
  tool is Slack-only and read-only (no write/reaction path).

---

## Wrap up

After completing the user's request, summarise:

1. Which thread(s) or channel(s) were fetched or shown, and whether the cache
   was used or the API was called.
2. The output format used (human, `--json`, `--jsonl`).
3. Whether users/channels were cached (so author names render), if relevant.

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…