Local message history & search
slackctl keeps a local, full-text-searchable mirror of the Slack messages it sees — so you can search your history instantly, offline, and without Slack's search API (which is user-token-only and rate-limited).
How it fills up
Recording happens automatically as you use slackctl. Anything message-bearing is captured:
- posts you send (
msg post,msg update,msg template) - history/replies you fetch (
conversations history,conversations replies,conversations export) - live events you stream (
slackctl listenrecords every message event it receives)
So a natural workflow — post, browse, export, or leave listen running — builds a searchable
archive you can query any time. The store is a per-workspace SQLite database.
# Leave a listener running to mirror a channel in real time…
slackctl listen --channels C0123456 &
# …then search what it captured, offline:
slackctl log search "deploy failed"
Searching
slackctl log # recent messages (newest first)
slackctl log --channel C0123456 --since 24h # filter by channel and time
slackctl log --user U0123456 -o json
slackctl log search "deploy failed" # full-text
slackctl log search "incident* AND prod" # FTS5 operators: AND/OR/NOT, prefix*, "phrase"
Search uses SQLite FTS5 when available (the pure-Go build ships it), with the operators
above. A plain query that isn't valid FTS5 syntax (e.g. on-call) transparently falls back to
a substring scan, so ordinary searches never error. --since accepts a Go duration (24h,
7d), a unix time, or a Slack ts.
Managing the store
slackctl log stats # how many messages, channels, and the FTS mode
slackctl log path # where the database lives
slackctl log prune --older-than 2160h # delete anything older than 90 days
Privacy & control
The database holds message text, so treat it like any local secret:
- It lives per-workspace under your config dir (
slackctl log path) with0600permissions. - Disable recording for a single call with
--no-store, e.g.slackctl msg post --channel C0123456 --text "…" --no-store. log pruneand deleting the file (rm "$(slackctl log path)") clear it.- The store is local-only — it's never uploaded, and
logis excluded from the MCP tool surface so an AI agent can't browse it unprompted.
A store problem never breaks a command: if the database can't be opened, slackctl warns once and continues without recording.