Spyglass
Forensic logging and rollback for Paper 1.21.x
Spyglass records block, container, chat, command, combat, and movement events, lets you query them with a key:value language, and rolls back any of it - by player, region, cause, or in bulk - while the server holds 20 TPS.
Three storage backends: embedded SQLite (zero setup, default), MongoDB, and ClickHouse. SQLite makes it as easy to drop in as CoreProtect; the larger backends are there when you outgrow it.
Performance
2,000,376-block rollback - Paper 1.21.8, 6 GB heap, Aikar flags:
| SG SQLite | SG MongoDB | SG ClickHouse | CP SQLite | CP MySQL | |
|---|---|---|---|---|---|
| Rollback | ~3 s | ~7 s | ~5 s | ~11 s | ~12 s |
| Undo / restore | ~3 s | ~6 s | ~4 s | ~9 s | ~210 s |
| TPS (min / avg) | 20.0 / 20.0 | 20.0 / 20.0 | 20.0 / 20.0 | 14 / 19 | 13 / 20 |
| Worst single tick | ~37 ms | ~100 ms | ~50 ms | ~670 ms | ~270 ms |
| On-disk footprint | ~156 MiB | ~145 MiB | ~11 MiB | ~160 MiB | ~180 MiB |
Rollback runs entirely off the main thread. No backend dips below 20 TPS.
Features
Spyglass only
- Combat logging - hits and projectile shots
- Movement and teleport logging
- Password redaction in command logs
- Item search by display name, lore, or enchantment
- Cross-server search via an optional Velocity companion
- Extension API - custom events, query params, display renderers, rollback effects
- Container salvage - items inside a rollback-destroyed container are recoverable via
/sg inventory - One-command undo, any size, walks back through your history
- Crash-resume - an interrupted rollback is resumable from a saved cursor on restart
- Rollback emits no new log rows
- Automatic data pruning / configurable TTL
- Rollback runs fully off the main thread
Shared with CoreProtect
- Block, container, and entity logging
- Chat, command, session, and IP logging
- Explosions, fire, liquids, and growth
- WorldEdit capture - all operations, not just
//set - Inspector wand and block history lookup
- Rollback and restore by player, time, or region
CoreProtect only
- Preview a rollback before applying
Requirements
- Paper 1.21.8 or newer 1.21.x (not Spigot or Folia)
- Java 21
- One of: SQLite (default, zero setup), MongoDB, or ClickHouse
- Optional: WorldEdit 7.3+ or FastAsyncWorldEdit 2.15+ for edit capture and
-weregion queries
Commands
Root: /spyglass or /sg. All permissions default to op.
| Command | Aliases | Permission |
|---|---|---|
/sg search <query> |
s, lookup | spyglass.search |
/sg rollback <query> |
rb, roll | spyglass.rollback |
/sg restore <query> |
rs | spyglass.rollback |
/sg undo |
u | spyglass.rollback |
/sg rbqueue |
queue, rbq | spyglass.rollback |
/sg tool |
t, inspect | spyglass.tool |
/sg inventory |
inv, salvage | spyglass.rollback |
/sg events |
e | spyglass.use |
/sg page <n> |
p, pg | spyglass.use |
/sg help |
h, ? | spyglass.use |
Two permissions gate a feature rather than a command:
spyglass.search.ip- reveals join IPs and unlocks theip:query keyspyglass.worldedit- allows the-weflag to use a WorldEdit selection as the search region
Query language
Search, rollback, and restore share one key:value syntax. Combine any number of keys; prefix a value with ! to exclude it.
/sg search p:Steve b:diamond_ore t:1d r:50
/sg rollback p:griefer a:break,!place t:6h r:100
Keys
| Key | Notes |
|---|---|
p: |
Player(s) - comma-separated for OR, p:!Steve to exclude |
a: |
Event type - see /sg events; a:!place to exclude |
b: |
Block material - b:!chest to exclude |
i: |
Item material |
iname: |
Item display name (substring) |
ilore: |
Item lore line (substring) |
ench: |
Enchantment - e.g. ench:sharpness=5 |
e: |
Entity type |
c: |
Cause - e.g. c:tnt,!creeper |
m: |
Chat, sign, or book text (substring) |
r: |
Radius in blocks |
t: |
Time window - t:1d, t:30m, t:1d12h (default: 4h) |
w: |
World name |
srv: |
Server name (multi-server) |
ip: |
Source IP - requires spyglass.search.ip |
Flags
| Flag | Effect |
|---|---|
-g |
Global - skip the default radius |
-we |
Use your active WorldEdit selection as the region |
-ord:asc / -ord:desc |
Sort order |
-ng |
Don't merge duplicate adjacent results |
-nc |
Suppress the chat summary line |
-ex |
Show extra detail columns |
-nod:r,t |
Drop defaults (run with no radius or time bound) |
Examples
# Who broke this block in the last day?
/sg search b:* t:1d r:5
# Roll back everything a player did in the last 2 hours, globally.
/sg rollback p:Bob a:place,break t:2h -g
# TNT grief - player-lit TNT is attributed to the igniter.
/sg rollback p:griefer t:1h r:30
# Roll back everything except containers.
/sg rollback p:griefer t:6h r:100 b:!chest
# Who picked up a sword named Excalibur?
/sg search a:pickup iname:Excalibur t:1w -g
# Track a sharpness V item through drops and pickups.
/sg search ench:sharpness=5 t:1d -g
# Every command a specific IP ran today.
/sg search ip:1.2.3.4 a:command t:1d -g
# Restore breaks inside a WorldEdit selection from the last hour.
//wand
/sg restore a:break t:1h -we
License
Source-available under the PolyForm Internal Use License 1.0.0, with an added permission for Minecraft servers. You may run it and fork it for your own servers, including commercial ones. Redistribution, sublicensing, and resale are not permitted.