Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mirage.strukto.ai/llms.txt

Use this file to discover all available pages before exploring further.

The Slack resource exposes a Slack workspace as a virtual filesystem mounted at some prefix such as /slack/. For token setup, see Slack Setup.

Config

import os

from mirage import MountMode, Workspace
from mirage.resource.slack import SlackConfig, SlackResource

config = SlackConfig(token=os.environ["SLACK_BOT_TOKEN"])
resource = SlackResource(config=config)
ws = Workspace({"/slack": resource}, mode=MountMode.READ)

Filesystem Layout

/slack/
  channels/
    <channel-name>__<channel-id>/
      <yyyy-mm-dd>.jsonl
      ...
  dms/
    <user-name>__<dm-id>/
      <yyyy-mm-dd>.jsonl
      ...
  users/
    <username>.json
    ...
Example:
/slack/
  channels/
    general__C04KEPWF6V7/
      2026-04-04.jsonl
      2026-04-05.jsonl
    random__C04JVGZM7UN/
      2026-04-11.jsonl
  dms/
    alice__D0AQDJ5FP9V/
      2026-04-04.jsonl
    slackbot__D0ARPA1QSPJ/
      2026-04-04.jsonl
  users/
    alice__U12345678.json
    bob__U87654321.json
Directory names embed the Slack ID so that write commands (slack-post-message --channel_id, etc.) can reference the correct resource without extra lookups.

Channels

/slack/channels/ lists public and private channels the bot has access to. The channel ID is appended after __. Each channel directory contains day-partitioned .jsonl history files for the last 90 days (or since channel creation, whichever is shorter). The date range is derived from the channel’s created timestamp.

DMs

/slack/dms/ lists direct message conversations. The DM ID is appended after __. Like channels, DM directories contain daily .jsonl history files.

Users

/slack/users/ lists one .json file per non-deleted, non-bot user. Reading a user file calls get_user_profile() and returns the full profile JSON from the Slack API.

Cache

The Slack resource uses IndexCacheStore (same as Discord and other resources). Index entries store channel IDs, DM IDs, user IDs, and channel creation timestamps for date range computation. There is no separate content cache - file content caching is handled by the workspace IOResult mechanism.

Example

import asyncio
import os

from dotenv import load_dotenv

from mirage import MountMode, Workspace
from mirage.resource.slack import SlackConfig, SlackResource

load_dotenv(".env.development")

config = SlackConfig(token=os.environ["SLACK_BOT_TOKEN"])
resource = SlackResource(config=config)


async def main():
    ws = Workspace({"/slack": resource}, mode=MountMode.READ)

    # List structure
    r = await ws.execute("ls /slack/")
    print(await r.stdout_str())

    # List channels
    r = await ws.execute("ls /slack/channels/")
    print(await r.stdout_str())

    ch = r.stdout_str().strip().splitlines()[0].strip()
    base = f"/slack/channels/{ch}"

    # Read messages from a specific date
    r = await ws.execute(f'cat "{base}/2026-04-04.jsonl" | head -n 3')
    print(await r.stdout_str())

    # Read user profile
    r = await ws.execute("cat /slack/users/alice.json")
    print(await r.stdout_str())

    # Extract message text with jq
    r = await ws.execute(
        f'cat "{base}/2026-04-04.jsonl"'
        ' | jq -r ".[] | .text" | head -n 5')
    print(await r.stdout_str())

    # Search across channel (scans all date files)
    r = await ws.execute(f'rg message "{base}/"')
    print(await r.stdout_str())

    # Tree view
    r = await ws.execute("tree -L 1 /slack/")
    print(await r.stdout_str())

    # Navigate with cd/pwd
    await ws.execute(f'cd "{base}"')
    r = await ws.execute("pwd")
    print(await r.stdout_str())


if __name__ == "__main__":
    asyncio.run(main())
See examples/chat/slack.py for the full working example.

Finding IDs

Resource-specific commands require Slack IDs (channel_id, user_id, ts). These can be extracted from the filesystem:
# Channel ID - embedded in directory name after "__"
ls /slack/channels/
# → general__C04KEPWF6V7   ← channel_id = C04KEPWF6V7

# User ID - embedded in filename after "__"
ls /slack/users/
# → alice__U04K21SEVR9.json   ← user_id = U04K21SEVR9

# Message timestamp (ts) - inside JSONL messages
jq -r '.[] | "\(.ts) [\(.user)] \(.text)"' \
  "/slack/channels/general__C04KEPWF6V7/2026-04-04.jsonl"
# → 1712345678.123456 [U04K21SEVR9] hello world

# Find a specific message then reply
jq -r '.[] | select(.text | test("hello")) | .ts' \
  "/slack/channels/general__C04KEPWF6V7/2026-04-04.jsonl"
# → 1712345678.123456
slack-reply-to-thread --channel_id C04KEPWF6V7 \
  --ts 1712345678.123456 --text "Reply to hello"

Working with Large Channels

Channels with many messages produce large .jsonl files per day. Tips for efficient access:
# Check message count per day
wc -l "/slack/channels/general__C04KEPWF6V7/2026-04-04.jsonl"

# Read only recent messages
tail -n 10 "/slack/channels/general__C04KEPWF6V7/2026-04-04.jsonl"

# Search across all dates (scans each file)
rg "keyword" "/slack/channels/general__C04KEPWF6V7/"

# Extract specific fields to reduce output
jq -r '.[] | "\(.ts) [\(.user)] \(.text)"' \
  "/slack/channels/general__C04KEPWF6V7/2026-04-04.jsonl" | head -n 20

# Count messages per user
cat "/slack/channels/general__C04KEPWF6V7/2026-04-04.jsonl" \
  | jq -r '.[] | .user' | sort | uniq -c

Shell Commands

Standard commands available on the mounted Slack tree:
CommandNotes
lsList channels, DMs, users, dates
catRead .jsonl history or user .json
head / tailFirst/last N lines
grep / rgPattern search (file or directory level)
jqQuery JSON; use .[] prefix for JSONL
wcLine/word/byte counts
statFile metadata (name, size, type)
findRecursive search with -name, -maxdepth
treeDirectory tree view
Resource-specific commands:

slack-post-message

Post a message to a channel.
slack-post-message --channel_id C04KEPWF6V7 --text "Hello from MIRAGE"
OptionRequiredDescription
--channel_idyesSlack channel ID
--textyesMessage text to send
Returns the posted message JSON.

slack-reply-to-thread

Reply to a specific thread.
slack-reply-to-thread --channel_id C04KEPWF6V7 --ts 1712345678.123456 --text "Thread reply"
OptionRequiredDescription
--channel_idyesSlack channel ID
--tsyesThread parent timestamp
--textyesReply text
The --ts value is the message timestamp (e.g., from a .jsonl entry’s ts field). Returns the posted reply JSON.

slack-add-reaction

Add an emoji reaction to a message.
slack-add-reaction --channel_id C04KEPWF6V7 --ts 1712345678.123456 --reaction thumbsup
OptionRequiredDescription
--channel_idyesSlack channel ID
--tsyesMessage timestamp to react to
--reactionyesEmoji name (without colons)

slack-get-users

Search for users by name, real name, or email.
slack-get-users --query "alice"
OptionRequiredDescription
--queryyesSearch query
Returns matching users as JSON array.

slack-get-user-profile

Get a single user’s full profile.
slack-get-user-profile --user_id U04K21SEVR9
OptionRequiredDescription
--user_idyesSlack user ID
Returns the user profile JSON. The user ID can be found in filenames under /slack/users/ (e.g., alice__U04K21SEVR9.json). Search messages across the workspace.
slack-search --query "incident report"
OptionRequiredDescription
--queryyesSearch query
Returns search results as JSON.