Skip to main content
MIRAGE ships SlackResource in two runtimes:
  • @struktoai/mirage-node, talks to https://slack.com/api/* directly using a bot token (and optionally a user token for search.messages).
  • @struktoai/mirage-browser, stays secret-free: a small proxy server on your backend holds the token and forwards /api/slack/* to https://slack.com/api/*. The browser only ever sees the proxy URL.
Both runtimes expose the same filesystem shape (/slack/channels/, /slack/dms/, /slack/users/) and the same shell commands, and both pair with the slack CLI for acting on the workspace.

Get a bot token

  1. Visit the Slack API basics page and create an app for your workspace.
  2. Under OAuth & Permissions, add the bot scopes you need. The minimum for read access is:
    • channels:history, channels:read
    • groups:history, groups:read
    • im:history, im:read
    • users:read
  3. For posting messages, also add chat:write.
  4. For search.messages, Slack requires a user token (xoxp-…) with search:read. Bot tokens (xoxb-…) get not_allowed_token_type. Provide it via the optional searchToken field.
  5. Install the app to your workspace and copy the Bot User OAuth Token (xoxb-…).

Node (server-side)

Browser

The browser package never sees the bot token. Instead, point it at a relative URL that your backend proxies to https://slack.com/api/*, attaching the Authorization: Bearer … header server-side.

1. Server: minimal proxy

2. Browser: wire it up

Calling https://slack.com/api/* directly from a browser fails CORS. The proxy is mandatory, Slack does not set permissive CORS headers.

Filesystem layout

Each channel or DM directory contains day-partitioned directories for the last 90 days (or since channel creation). Each date directory contains chat.jsonl plus a files/ directory for attachments shared that day. Each user file is the full profile JSON returned by users.profile.get. The Slack ID is embedded after __ in directory and file names so you can extract it for the resource-specific commands without an extra lookup.

Shell commands

Every standard MIRAGE shell command works on the mounted Slack tree: Acting on Slack (sending, reacting, pins, member info, search) goes through the slack CLI when installed; the mounted tree stays read-oriented.

Troubleshooting

search.messages requires a user token (xoxp-…) with search:read scope. Set searchToken on the SlackConfig:
Without it, workspace-scope rg and slack search fail; channel-scope rg (e.g. rg foo /slack/channels/general__C…/) still works since it streams the JSONL files directly.
The browser cannot call https://slack.com/api/* directly, Slack does not set permissive CORS headers. You must run the proxy server shown above (or your own equivalent) and point proxyUrl at it.
SlackResource uses an IndexCacheStore (default TTL 600s) to deduplicate channel / user / date listings, but high-volume reads of .jsonl files can still hit Slack’s per-method rate limits. Cache hits avoid the API entirely; tune indexTtl if your workspace changes slowly. Per Slack docs, Tier 3 methods like conversations.history allow ~50 requests / minute / workspace.

Examples

See Python Slack Resource for the equivalent Python wiring.