MIRAGE shipsDocumentation 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.
DiscordResource in two runtimes:
@struktoai/mirage-node, talks tohttps://discord.com/api/v10/*directly using a bot token.@struktoai/mirage-browser, stays secret-free: a small proxy server on your backend holds the token and forwards/api/discord/*tohttps://discord.com/api/v10/*. The browser only ever sees the proxy URL.
/discord/<guild>/channels/, /discord/<guild>/members/) and the same shell commands (discord-send-message, discord-add-reaction, etc.).
Get a bot token
- Visit the Discord Developer Portal and create a new application.
- Under Bot, add a bot user and copy the Bot Token.
- Under Bot → Privileged Gateway Intents, enable:
- Server Members Intent, required for
/discord/<guild>/members/listings. - Message Content Intent, required to read message text in
.jsonlhistory files.
- Server Members Intent, required for
- Under OAuth2 → URL Generator, select the
botscope and the following bot permissions:Read Messages/View ChannelsRead Message HistorySend Messages(only if you’ll usediscord-send-message)Add Reactions(only if you’ll usediscord-add-reaction)
- Open the generated URL in a browser and invite the bot to your guild.
Node (server-side)
Browser
https://discord.com/api/v10/*, attaching the Authorization: Bot … header server-side.
1. Server: minimal proxy
2. Browser: wire it up
Filesystem layout
channels/ directory with text channels (types 0, 5, 15) and a members/ directory with one .json file per member. Each channel directory contains day-partitioned JSONL files for the 30 days leading up to the channel’s last message, inactive channels show dates around their last activity, not today. The Discord snowflake ID is appended after _ in directory and file names so resource-specific commands can extract it without an extra lookup.
Shell commands
Every standard MIRAGE shell command works on the mounted Discord tree:| Command | Notes |
|---|---|
ls | List guilds, channels, members, dates |
cat | Read .jsonl history or member .json |
head / tail | Smart: uses messages API for file scope |
grep / rg | Smart: uses search API for channel/guild scope |
jq | Query JSON; use .[] prefix for JSONL files |
wc | Line/word/byte counts |
stat | File metadata (name, size, type) |
find | Recursive search with -name, -maxdepth |
tree | Directory tree view |
pwd / cd | Navigate the virtual tree |
echo (glob) | Glob expansion via resolve_glob |
discord-send-message
| Option | Required | Description |
|---|---|---|
--channel_id | yes | Discord channel snowflake ID |
--text | yes | Message text to send |
--message_id | no | Message ID to reply to |
discord-add-reaction
| Option | Required | Description |
|---|---|---|
--channel_id | yes | Discord channel snowflake ID |
--message_id | yes | Message snowflake ID |
--reaction | yes | Emoji (unicode or name) |
discord-list-members
| Option | Required | Description |
|---|---|---|
--guild_id | yes | Discord guild snowflake |
--query | yes | Username search query |
discord-get-server-info
| Option | Required | Description |
|---|---|---|
--guild_id | yes | Discord guild snowflake |
Troubleshooting
Empty `/discord/<guild>/members/` listing
Empty `/discord/<guild>/members/` listing
Listing members requires the Server Members Intent. Enable it in the Discord Developer Portal under Bot → Privileged Gateway Intents. Without it,
members/ returns an empty directory and discord-list-members fails.Empty `content` field in JSONL messages
Empty `content` field in JSONL messages
Reading message text requires the Message Content Intent. Enable it in the Discord Developer Portal under Bot → Privileged Gateway Intents. Without it, the
content field on every message is empty.`401 Unauthorized` from the proxy
`401 Unauthorized` from the proxy
CORS error in browser
CORS error in browser
The browser cannot call
https://discord.com/api/v10/* directly, Discord 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 Discord
`rate_limited` from Discord
DiscordResource uses an IndexCacheStore (default TTL 600s) to deduplicate guild / channel / member listings, but high-volume reads of .jsonl files can still hit Discord’s per-route rate limits. The HTTP transport retries 429 responses honoring retry_after up to 3 times, repeated failures usually mean you should slow down or scope reads to specific channels.Examples
examples/typescript/discord/discord.ts, shell commands against/discord/(ls,cat,grep,jq,tree,find,cd, glob).examples/typescript/discord/discord_vfs.ts,patchNodeFs(ws)so nativenode:fscalls route through the workspace.examples/typescript/discord/discord_fuse.ts, FUSE-mount the workspace so external processes can browse/discord/as a real filesystem.examples/typescript/discord/discord_browser/, proxy server +@struktoai/mirage-browserDiscordResource demo.