SlackVFS in two runtimes:
@struktoai/mirage-node, talks tohttps://slack.com/api/*directly using a bot token (and optionally a user token forsearch.messages).@struktoai/mirage-browser, stays secret-free: a small proxy server on your backend holds the token and forwards/api/slack/*tohttps://slack.com/api/*. The browser only ever sees the proxy URL.
/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
- Visit the Slack API basics page and create an app for your workspace.
- Under OAuth & Permissions, add the bot scopes you need. For read access:
channels:history,channels:readgroups:history,groups:read(optional, private channels)im:history,im:read(optional, direct messages)mpim:history,mpim:read(optional, group direct messages)users:read
- For the CLI
send-messagecommand, also addchat:write. The mount never posts. - For
search.messages, Slack requires a user token (xoxp-…) withsearch:read. Bot tokens (xoxb-…) getnot_allowed_token_type. Provide it via the optionalsearchTokenfield. - Install the app to your workspace and copy the Bot User OAuth Token (
xoxb-…).
Node (server-side)
Config
Fields marked secret are redacted in snapshots.
Browser
https://slack.com/api/*, attaching the Authorization: Bearer … header server-side.
Config
Fields marked secret are redacted in snapshots.
1. Server: minimal proxy
2. Browser: wire it up
VFS.md
The VFS.md an agent reads with Slack mounted at/<path>.
- Rendered
- Raw
Virtual Filesystem
/<path> layout
Supported Unix Commands for VFS
Unix commands work on each path as on a local filesystem, as far as the path supports them:Limitations of Unix Commands for VFS
Where a path differs from a local filesystem:Run
man to list every command, and man <cmd> or <cmd> --help for one command’s usage.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 VFS-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.
Integration
What Slack answers through its own API, so fewer files are read. Integration explains each command.
The Python Slack docs list when each search answers and what it can miss.
Troubleshooting
not_allowed_token_type on slack search
not_allowed_token_type on slack search
The account CLI’s
slack search command calls search.messages, which requires a user token (xoxp-…) with search:read scope. Include searchToken in the config passed to ws.registerCli; see the Slack CLI setup. Without it, slack search fails. VFS grep and rg still scan the mounted files; they simply skip the optional Slack-search optimization.CORS error in browser
CORS error in browser
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.rate_limited from Slack
rate_limited from Slack
SlackVFS 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; raise the index ttl (index: { ttl }) together with the mount’s ttl if your workspace changes slowly.History limits depend on app distribution. Check Slack’s current
conversations.history method limits
for your installation.Examples
examples/typescript/vfs/slack/slack.ts, shell commands against/slack/(ls,cat,grep,jq,tree,find,cd, glob).examples/typescript/vfs/slack/slack_vfs.ts,patchNodeFs(ws)so nativenode:fscalls route through the workspace.examples/typescript/vfs/slack/slack_fuse.ts, FUSE-mount the workspace so external processes can browse/slack/as a real filesystem.examples/browser/vfs/slack/, proxy server +@struktoai/mirage-browserSlackVFS demo.
Time scope
Setstart_time and/or end_time in the mount’s YAML config (or pass
start_time/end_time to Python; startTime/endTime to the TypeScript
constructor). Bounds are RFC3339 timestamps with an explicit timezone and
at most millisecond precision. Start is inclusive; end is exclusive.
An omitted or null bound is open. Start must precede end.
stat, date globs, and grep/rg cannot escape the scope: a search only rules
out files, so scoped searches scan the filtered files. User/member
and channel/server metadata remain visible as context.
These settings apply to the VFS, not to separately installed account CLIs.
mode: read prevents mount writes; it does not freeze upstream edits or deletions.
Rebuild/remount the VFS to change its scope so cached listings and bytes are cleared.