Compatibility
Minecraft: Java Edition
Platforms
Links
Tags
Creators
Details
Spyglass
Run your server from Discord, and watch every command typed on it. Define your own slash commands in one block of config. No coding, no phoning home.
Features
- Your own slash commands : the config key is the command, so
/bantakes three lines - Live command feed : every command run in game, mirrored to a Discord channel you pick
- Around 85 placeholders : player, location, world, health, ping, command, Discord user, server stats
- Smart filters : ignore lists with wildcards, an only-these whitelist, ignored players, bypass permission
- Password safe :
login,registerand private message commands are ignored out of the box - Rate limit proof : lines are batched into one message every few seconds instead of spamming Discord
- Config errors that explain themselves : a broken file gives you the line, column and the fix, and nothing gets applied
- MiniMessage formatting : gradients, hover text and clickable commands, all from
messages.yml - Injection safe : a player named
<red>cannot recolour your staff channel or plant a clickable command - One command setup check :
/spyglass testverifies token, channel ID and bot permissions at once - Zero telemetry : no update checker, no analytics, the only connection it makes is to Discord
Your commands, your config
The config key doubles as the command name and its signature. This is the whole setup for a working /ban:
commands:
"ban {username}":
discord-command-description: "Used to ban members"
minecraft-command: "/ban {username}"
Add three dots to the last option when it should take a whole sentence, and let Discord autocomplete from your live player list:
"kick {username} {reason...}":
discord-command-description: "Kick a player off the server"
minecraft-command: "/kick {username} {reason}"
arguments:
username:
suggest-online-players: true
reason:
required: false
One slash command can run several Minecraft commands in order, lock to specific roles, users or channels, carry a cooldown, run as console or as a player, and reply privately.
Argument types: string, integer, number, boolean, user, channel, role, with optional fixed choices.
Watch every command
command-monitor:
enabled: true
channel-id: "1234567890123456789"
format: "{username}: {command}"
Every placeholder works in the format, so you choose how much detail lands in Discord:
format: "`{time}` **{username}** ran `{command}`"
format: "[{world}] {username} ({x}, {y}, {z}) ran {command}"
Players, console, RCON, and commands that came from Discord are all covered. Discord ones are credited to the Discord user rather than to the console.
Broken config tells you how to fix it
Both files are parsed before anything is applied. A syntax error changes nothing, your running settings stay live, and you get this instead of a stack trace:
[Spyglass] config.yml could not be loaded - it has a YAML syntax error.
[Spyglass] Line 83, column 22: mapping values are not allowed here
[Spyglass] 83 | text: Now playing: survival mode
[Spyglass] | ^
[Spyglass] Fix: this value contains a colon. Wrap the whole value in "double quotes"
It knows unquoted colons, tab indentation, misaligned indentation, unclosed quotes, duplicate keys, and keys that start with a brace.
Commands
| Command | Description |
|---|---|
/spyglass reload |
Reload config.yml and messages.yml |
/spyglass status |
Discord connection, monitor stats, config warnings |
/spyglass commands |
List every configured Discord command |
/spyglass test |
Post a test line to the monitor channel |
/spyglass help |
Show the command list in game |
/sg |
Alias for /spyglass |
/glass |
Alias for /spyglass |
Permissions
| Permission | Default | Description |
|---|---|---|
| spyglass.admin | op | Full access to every sub-command |
| spyglass.reload | op | Use /spyglass reload |
| spyglass.status | op | Use /spyglass status |
| spyglass.commands | op | Use /spyglass commands |
| spyglass.test | op | Use /spyglass test |
| spyglass.monitor.bypass | false | This player's commands are never relayed |
Who may use a slash command is set in config.yml by Discord role, user or channel, not by Minecraft permissions.
Setup
- Drop the jar in
plugins/and start the server once - Create a bot at the Discord developer portal, open Bot, press Reset Token
- Invite it from OAuth2 > URL Generator with
botandapplications.commandsticked - Turn on Developer Mode in Discord, then right click to Copy ID
- Put your token and server ID in
config.yml - Run
/spyglass reload, then/spyglass test
No privileged intents to enable.
Requirements
- Bukkit / Spigot / Paper / Purpur 1.21 to 26.2
- Java 21+
- A Discord bot token
Spyglass only uses standard Bukkit API, so the same jar runs unmodified on all four.

