A purely client-sided anticheat for Minecraft Java 1.21.11 (Fabric).
Detects both 1.8-era and 1.21.11-era cheats by passively observing other players through the packets the server already rebroadcasts to you. No server component, no network transmission, no outgoing packets.
Local-only alerts and overlays. No bans. No interference. No outgoing packets.
- Rolling world capture. The world around a
/ius clipused to be swept all at once when you saved, which froze the client on ~300 synchronous chunk snapshots. It's now rolled up in the background while the scene is still live (16 chunks/tick, nearest-first), so/ius clipreturns instantly. A window that spans a teleport records one segment per place, so both places replay. - Clips capture the whole scene. Nearby non-player entities (mobs, animals, boats, minecarts) and every block edit observed during the window are captured alongside the players, and replays draw them through their own vanilla entity models. New config toggles: Clip captures entities, Entity capture cap, Rolling world budget, New-segment distance.
- Your own body is in the replay. The capture buffer recorded everyone but you, so a freecam replay showed every other player and an empty spot where you had been standing. You are now captured like any other player and drawn as a ghost at your buffered position, and the live body is hidden while the replay runs in every camera mode (freecam, pov, follow and free), so you appear exactly once instead of twice. This costs no clip-format change: your snap is an ordinary player snap, so it rides through
.iusclipsave and load untouched and works under both Modern and Legacy playclip. A clip recorded by an older build carries no snap of you, and there the live body stays visible exactly as before. - Clip format v13. Per-segment worlds, block-edit deltas, entity capture, body/head yaw. Clips from v2 through v12, including SnapClip's v9-v12, are still read, though the older layouts are coded from the format's shape rather than from a reference clip, since none exist in this repo to test against, so treat that path as best-effort. A file that does not match is refused instead of half-loaded: the reader checks that it consumed exactly the bytes on disk and reports a truncated or unrecognized clip. An older Iustitia build cannot read a v13 clip, so re-export one if you need to open it there.
- Detection pass. Combat detection-rate work: a shared sustained-episode gate across the per-hit combat checks, a ghost-reach tier for
reach(motionless-pair branch with a 3.2-block ceiling), an occlusion fix sothroughWallsactually sees hits behind walls, and anoFallDamageburst re-base that keeps wind-charge jumps legal while burst-spoof falls still flag. The last two known false positives (ladder climbs underflyEnvelope, water walking) are gone. - Five built-in profiles.
standardstays the everyday profile, and four more join it:lenient(blatant combat cheats only),strict(every check, twice as sensitive),moderation(staff review, with every flag on its own line, audio cues and the transcript panel) anddebug(diagnostic, everything on). They differ in one detection number,setbackVL, so a profile is the same detector with a different trip point.standardalso stopped reporting the seven checks a minigame server implements itself. The setup wizard offers the first four, and/ius presetsdescribes each one;debugis/ius preset debug. - Open collaboration. Contributor infrastructure:
CONTRIBUTING.md/SECURITY.md/SUPPORT.md/CODE_OF_CONDUCT.md, issue + PR templates, CI workflows, an automated three-pass live-test harness (scripts/live_selftest.py, 92 scenarios: legit / cheat / replay), and an agent-facing contributor skill (.claude/skills/iustitia-contributor/).
Your existing settings carry straight over: every option added since v1.1.0 is an additive config field with a has(...) back-compat guard, and IustitiaConfig.CONFIG_VERSION is unchanged in this release (it is 5, last bumped in v1.3.0). Older .iusclip files are read on the terms noted above.
Iustitia is a Fabric client mod that watches every other player on your server and flags impossible world/combat interactions: the kind of thing a reach hack, a killaura, a fly hack, or a timer cheat produces. It does this entirely on your client:
- Read-only on incoming packets. A single mixin (
ClientPlayNetworkHandlerMixin) observes server packets and feeds them into a tracking pipeline. It never sends anything to the server and never mutates the local player. The watch follow-cam (/ius spectate, see below) is the one deliberate exception: it overrides the camera only, while you're actively spectating, and auto-reverts the instant you stop, move, get hit, or the target leaves. Vanilla re-derives the camera every frame, so it can never get stuck. - Other players only. It builds a server-space model of every other client player (position, yaw/pitch, sprint/sneak, hurt ticks, vehicle, deltas) from rebroadcast state, then runs 36 detection checks against that model each tick.
- Fail-open everywhere. Every check and mixin body is wrapped so a thrown exception is swallowed and skipped. A detection error never crashes your client and never produces a false positive. A chunk-unloaded player is a false negative, never a false positive.
- Two streams, kept separate. Chat alerts fire only when a check's violation level crosses its setback threshold. Verbose console logging (every flag, a pipeline heartbeat) is opt-in via
/ius verbosefor validation/debugging and is off by default. The release build is silent inlatest.logunless you turn it on. When it is on, each line is handed to a background writer rather than written on the tick thread, so a busy server's flag volume cannot cost you frames; the heartbeat reportsdropped=Nif the writer ever fell behind, which tells you a transcript is partial (detection data itself is never dropped —/ius histis exact).
It is a detection/inspection tool, not an enforcement tool: it tells you who looks like a cheater. It does not kick, ban, or report anyone, and it sends nothing anywhere.
| Dependency | Version |
|---|---|
| Minecraft | 1.21.11 |
| Fabric Loader | 0.19.3+ |
| Fabric API | 0.141.3+1.21.11 (any compatible) |
| fabric-language-kotlin | 1.13.9+kotlin.2.3.10 (any compatible) |
| Yet Another Config Lib (YACL) | 3.8.2+1.21.11 (any compatible) |
| Java | 21 |
| Recommended: ViaFabricPlus | for playing on 1.8-era servers via protocol translation |
All three library mods (Fabric API, fabric-language-kotlin, YACL) are standard and can be installed alongside any other modpack. Iustitia is written to fail-open and not crash when other mods are present.
- Install Fabric Loader 0.19.3+ for Minecraft 1.21.11.
- Drop Fabric API, fabric-language-kotlin, and YACL into your
mods/folder. - Drop the latest
iustitia-<version>.jarinto yourmods/folder. - (To detect cheats on 1.8-era servers) Install ViaFabricPlus so your 1.21.11 client can join them.
- Launch. A one-time first-launch wizard asks how you use Iustitia (Standard / Lenient / Strict / Moderation) and pre-sets sensible defaults. Join any server with other players.
That's it. Alerts appear in chat; other players get a colored tier prefix on their nametag where the server allows it (see Nametag prefixes).
/ius # list checks + enabled state (alias of /iustitia)
/ius status # health panel: master, tracked players, protocol, alerts
/ius help # in-game command help
/ius help reach # describe a check + its live config (or /ius help spectate, transcript, …)
/ius hist # session top offenders (searchable screen)
/ius hist <name> # a player's profile card + recent flags
/ius spectate <name> # watch follow-cam on a player (or your crosshair target; /ius spectate off to stop)
/ius transcript <name> # copyable session timeline (or /ius transcript panel <name> for the side panel)
/ius evidence <name> # one-line summary of their last few seconds of flags
/ius note <name> <cat> <text…> # tag a player (closet/blatant/needsReview/legit); /ius note <name> to read
/ius session # session summary: tracked players, tier counts, who peaked highest
/ius report <name> # full report card → clipboard (markdown, json, or text)
/ius snapshot [name] # one-line evidence snapshot of your crosshair target → clipboard
/ius replay [<player>|<sec>] [<sec>] [1|0.5|0.25] # rewind the last N seconds in-world as ghost models (1× by default; 0.5/0.25 = slow-mo; bare = 30s, no focus)
/ius replay pause|resume|seek <s>|step +|-|speed 1|0.5|0.25|cam free|follow|pov|freecam|off # playback controls while a replay runs
/ius clip <sec> [name] # export the last N seconds of positions + alerts (+ the loaded chunk world) to a portable .iusclip file
/ius playclip [name] [1|0.5|0.25] # play a saved clip back in-world as a solid textured world + ghosts, relocated to you (/ius playclip off to stop; bare = list clips)
/ius deleteclip <name> # delete a saved .iusclip by name (alias /ius delclip <name>)
/ius clips # open the clip manager screen (list / play / delete saved .iusclip files)
/ius preset <name> # apply a named config preset (built-ins: standard, lenient, strict, moderation, debug; or a custom preset)
/ius createpreset <name> # save the current config as a custom preset (persists to .iustitia/presets/<name>.json)
/ius deletepreset <name> # delete a custom preset (built-ins can't be deleted)
/ius presets # list all presets (built-in + custom)
/ius clear <name|all> # reset one player's flags (tier→green) or everyone's (exemptions untouched)
/ius exempt [name [on|off]] # exempt a player from all checks (bare = list exempted); persists across sessions
/ius alerts # mute/unmute all chat alerts (detection keeps running)
/ius keybinds # open the keybind hub screen
/ius config # open the YACL config screen
There are also thirteen keybinds (snapshot, transcript, session, keybinds, config, note, compact, watch, replay toggle, plus four numpad replay controls: pause/resume, seek +5s, seek −5s, exit) — configurable in vanilla Controls → Miscellaneous, and listed with conflict-detection in the keybind hub (/ius keybinds).
See USERMANUAL.md for a non-developer walkthrough.
┌─────────────────────────────┐
server packets │ ClientPlayNetworkHandler │ (read-only mixin — no send path)
──────────────►│ Mixin → PacketSignals │
└──────────────┬──────────────┘
│ swing / hurt / position / metadata
▼
┌──────────────────────┐
│ EntityTrackerManager │ server-space model of every other player
│ + ProtocolDetector │ (1.8-era vs modern combat timing)
└──────────┬───────────┘
│ TrackedPlayer (pos, yaw/pitch, deltas, sprint, hurtTick…)
▼
┌──────────────────────┐ per tick: ClientTickEvents.END_CLIENT_TICK
│ 36 Checks (combat + │ ──► Check.process() / onAttack() / onSwing()
│ movement/rotation/ │ ──► vl += level ; decay each clean tick
│ packet) │
└──────────┬───────────┘
│ flag() when vl > setbackVL
▼
┌──────────────────────┐
│ AlertManager + │ ──► chat alert (throttled, join-grace)
│ FlagHistory + CheckInfo│ ──► /ius hist, status, nametag tier
└──────────────────────┘
┌─────────────────────────────┐
render thread │ PlayerEntityRendererMixin │ nametag tier prefix + burst pulse
│ ArmorStandEntityRendererMx │ nametag fallback for armor-stand holograms
│ PlayerListHudMixin │ tab-list tier badge
│ CameraMixin │ offender-selfie + watch follow-cam (auto-reverting)
│ EntityRendererMixin │ hides live entities + your own body in a replay
└─────────────────────────────┘ (all render-only, no visibility hack, no send path)
ClientPlayNetworkHandlerMixin— the read-only packet observer.defaultRequire: 1(loud-fail if it ever drifts on a future MC build, because a silent packet miss means silent false negatives).PlayerEntityRendererMixin— the nametag tier prefix + burst-pulse renderer. Cosmetic, render-only, fail-open (a future-build signature drift would at worst make prefixes silently not appear).ArmorStandEntityRendererMixin— extends the nametag fallback to armor-stand holograms (servers that ride the nametag on an armor stand). Render-only, fail-open.PlayerListHudMixin— prepends the tier glyph (+ score) to each OTHER player's row in the Tab list.@InjectongetPlayerNameat RETURN, fail-open.EntityRenderStateAccessor—@AccessorfordisplayName/playerNameonEntityRenderState.CameraMixin— the offender-selfie (single-frame) and watch follow-cam (sustained) camera overrides. Both rely on vanilla re-deriving the camera before the@At("TAIL")inject each frame, so the override only persists while actively re-applied: the instant it stops, the view reverts to the local player (the safe state).EntityRendererMixin— the "rewind feel" hide-live for instant replay: cancelsshouldRenderfor every OTHER player while a replay is active with hide-live on, and cancels it for your own body too once the playing window carries a captured snap of you, so you are not drawn twice and not left hanging in front of the POV camera. Freecam hides your body regardless, as it always has. (The baseEntityRendereris the target becausePlayerEntityRendererinheritsshouldRenderand doesn't override it.) Render-only, fail-open; a cheap volatile-read early-out when no replay is running.
No @Redirect or @Overwrite is used anywhere. No send-path mixins. No local-player mutation (the watch follow-cam overrides the camera only, and is the sole deliberate exception — see above).
ProtocolDetector distinguishes 1.8-era combat (via ViaFabricPlus) from modern 1.21.11 combat and adjusts the hurt-confirmation lookback (3 ticks on 1.8 vs 2 on modern), so attack-inference timing is correct on both. Checks that depend on server ticking (timer/blinker, teleport) carry a server-lag exemption so a lagging server doesn't manufacture false positives.
Each check has its own config slice (enabled, setbackVL, decay, threshold) editable live via /ius or YACL. Checks marked definitive can prove cheating and drive the red nametag tier; the rest are inferential and drive yellow.
| id | detects | definitive |
|---|---|---|
reach |
Hit a victim beyond vanilla melee reach (lag-compensated). | ✓ |
multiTarget |
Struck ≥2 distinct victims in one tick (multi-aura). | ✓ |
clickStatistics |
Click cadence too uniform / too fast (autoclicker). | |
throughWalls |
Attacked a victim with no line-of-sight to the torso. | ✓ |
criticals |
Spoofed a grounded crit hop to crit while on the ground. | ✓ |
maceSmash |
Warped Y around an attack to inflate mace smash fall-damage (MaceKill). | ✓ |
noKnockback |
Took a hit without the expected knockback (anti-KB). | |
keepSprint |
Kept sprinting through an attack instead of the legit slowdown. | |
wTap |
Reset sprint KB pattern mismatch (W-Tap / SuperKB cheat). | |
jumpOnHurt |
Jumped instantly on taking damage (anti-KB hop). | |
backtrack |
Hit a victim from a stale (backtracked) position. | |
hitsWithoutSwing |
Dealt melee damage with no swing animation (no-swing / hit-select). | |
killAura |
Silent-aim / aim-snap suite (thirteen sub-components, one VL pool). | |
autoBlock |
Swung while a shield was raised (auto-block / block-hit). | ✓ |
hitFlick |
Redirected aim off the hitbox at the attack tick (HitFlick). | ✓ |
triggerbot |
Auto-attacked the instant the crosshair reached a hitbox (sub-reaction). |
killAura is a port of Rain-Anticheat's 1.8.9 silent-aim suite (corroborator-tier: thirteen sub-components, one VL pool); hitFlick is a Vape/Slinky-style knockback-redirect detector; triggerbot is a lax, blatant-only rising-edge reaction-timing detector (deliberately not definitive — yellow tier — pending live validation). maceSmash catches the 1.21 mace fall-damage fake; hitsWithoutSwing is a weak no-swing corroborator that never initiates a tier alone.
| id | detects | definitive |
|---|---|---|
speedEnvelope |
Moved horizontally faster than the vanilla speed envelope. | |
flyEnvelope |
Vertical motion broke vanilla physics (fly / hover / ascend). | ✓ |
spider |
Climbed a solid wall with no ladder/vine/scaffold (wall-climb). | ✓ |
noFallDamage |
Spoofed on-ground to avoid fall damage. | |
stepHeight |
Stepped up a block higher than the vanilla step height. | |
teleport |
Position jumped in a way that isn't a vanilla teleport/pearl. | ✓ |
longJump |
Covered too much horizontal distance in one air tick. | ✓ |
noSlow |
Moved at full speed while using an item that should slow you. | |
backwardSprint |
Sprinted backward (OmniSprint) — blatant-only, KB-exempt. | |
wallSprint |
Held sprint metadata while pressed against a wall (OmniSprint wall-sprint). | ✓ |
sprintHack |
Sprint metadata set where vanilla cancels it — in water, while sneaking, or while Blind. | ✓ |
waterWalk |
Walked on water (Jesus / water-walk). | ✓ |
elytraSpeed |
Elytra glide exceeded the vanilla speed cap. | |
rotationTracking |
Aim rotated too uniformly while tracking a target. | |
rotationSnapBack |
Aim snapped back after an attack (aim-snap). | |
phaseClip |
Moved through a solid block (phase / no-clip). | ✓ |
packetGap |
Packet timing gap inconsistent with vanilla ticking (timer/blinker). | |
aimWrap |
Aim rotated faster than a legit flick (>threshold°/tick). | |
pitchBound |
Pitch outside the vanilla [-90, 90] bound. | |
scaffoldRotation |
Scaffold placement rotation inconsistent with legit bridging. | ✓ |
The fixed alert layout:
§8[§diustitia§8] §f(Name) §<sev>(Check) §<sev>(VL)
Severity color scales with the violation ratio vl / setbackVL: <2× yellow (§e), <3× orange (§6), ≥3× red (§c). The trailing number is the violation count (ceiling of VL).
The line is self-documenting and interactive (both are local chat-component events; no packet is sent):
- Hover → the check's one-line description, this player's session alert count, and the severity legend.
- Click → runs
/ius hist <name>to open that player's flag history.
Alerts are throttled per (player, check) and suppressed during a join-grace window (default 30s) so a player who just rendered in doesn't burst-fire.
Other players get a tier prefix drawn on their nametag. Vanilla visibility is respected (no wallhack: the prefix only appears when vanilla would show the nametag):
| prefix | tier | meaning |
|---|---|---|
§a[+]§r |
green | no chat alerts this session (clean / low-flag) |
§e[!]§r |
yellow | ≥1 primary red-capable alert has fired (suspect) |
§c[X]§r |
red | ≥2 distinct red-capable checks have proven cheating (sticky for the session, decays one tier per ~10 min idle) |
When nametag burst pulse is on (default), the prefix briefly pulses white/tier-color for ~3 s after a fresh yellow/red alert. Display-only (no check logic changed). The numeric confidence score behind a tier is available in /ius hist, /ius session, the snapshot, and the crosshair confidence HUD, not on the nametag itself.
The prefix is written at the HEAD of PlayerEntityRenderer.renderLabelIfPresent (the draw method), so it survives label batching, and is mirrored into the Tab list by PlayerListHudMixin.
Server coverage caveat: the prefix only appears on servers that populate the vanilla nametag field (displayName). This works on most servers, including minemen.club and 1.8-era servers. Some servers suppress the vanilla nametag and render their own server-side name hologram instead; on those, Iustitia has no displayName to attach to and the prefix will not appear. This is by design (the alternative would be a wallhack-style visibility hack, which Iustitia refuses to do). Confirmed-affected: stray.gg and mcpvp.club (the latter shows a black-background label that is actually the server's BELOW_NAME health indicator, not the vanilla name).
A control surface and a visual layer that turn raw detections into a moderation workflow, all still read-only and client-sided.
/ius transcript <name>— a Discord-copyable session timeline (swings, inferred hits, reach samples, velocity received, checks fired)./ius transcript panel <name>toggles a live side panel./ius evidence <name>— collapses the last few seconds of a player's flags into one chat line./ius note <name> <category> <text…>— moderator tag (closet / blatant / needsReview / legit)./ius note <name>re-reads it./ius session— session summary: players tracked, tier counts, who peaked highest (confidence score)./ius session screenopens a dense one-screen version./ius report <name> [markdown|json|text]— a full report card copied to your clipboard./ius snapshot [name]— a one-line evidence snapshot of your crosshair target, copied to clipboard.
Thirteen configurable binds registered in vanilla Controls → Miscellaneous: snapshot, transcript, session, keybinds, config, note, compact, watch (default F9), replayToggle (numpad *, starts/stops a replay), plus four numpad replay controls — replayPause (numpad 5), replaySeekFwd (numpad +, +5s, works while playing), replaySeekBack (numpad −, −5s), and replayExit (numpad 0). /ius keybinds opens a hub screen that lists them all and highlights any that conflict with another bind in red.
/ius spectate [name] (or the watch keybind, default F9) starts a sustained follow-cam on a player: it forces F1, shows a third-party view of the target (all entities, including yourself, still rendered), and lets you orbit with the mouse while the target stays centered. It auto-stops when you move >0.5 blocks, get hit, or the target leaves render range; /ius spectate off (or the bind again) stops it manually. The camera auto-reverts to your view the instant it stops (vanilla re-derives it each frame, so it can never get stuck).
A moderator-style "instant replay" of the scene and a portable evidence-clip format. All client-side, all render-only (no detection logic touched):
/ius replay [<player>|<seconds>] [<seconds>] [1|0.5|0.25]: reconstructs the last N seconds (≤60) from a rolling 60 s capture buffer and plays it back in-world as translucent humanoid ghost models of you and every tracked player at their buffered positions, at full (1×) speed by default (add0.5or0.25for slow-mo). The named player is the highlighted focus (cyan +▶name marker). Ghosts are colored by that player's cheat tier (green/yellow/red) with a floating name tag so you can read who is who, and a facing nub shows each one's buffered yaw. With Clip captures entities on (default) the replay also draws the rest of the captured scene — mobs, animals, boats and minecarts, within 64 blocks of you at capture time — each through its own vanilla entity model, so a replay of a fight shows what the players were actually fighting. By default the live players and your own body are hidden during a replay ("rewind feel": only the ghosts render); the live game + detection keep running underneath and rendering snaps back the instant the replay stops. The<player>arg is optional and overloaded: a number = the duration with no focus (/ius replay 60); a name = the focus player, optionally followed by<seconds> [speed](/ius replay thoria 60 0.5); bare/ius replay= the default 30 s window, no focus. Playback controls while a replay runs:/ius replay pause/resume,seek <s>,step +|−(frame-step, while paused),speed 1|0.5|0.25,cam free|follow|pov|freecam(free = your view; follow = orbit the focus ghost; pov = the focus ghost's eyes; freecam = a detached free-fly camera you move with WASD + mouse, no collision, the Iustitia-native free-spectate; only for a chunk-bearing/ius playclip), andoff. Four numpad keybinds mirror the controls without leaving the game: numpad 5 = pause/resume, numpad +/− = seek ±5 s (works while playing), numpad 0 = exit. Needs the Replay capture buffer toggle on (default on)./ius clip <seconds> [name]: exports the last N seconds of your own and every tracked player's positions + every alert to a portable binary.iusclipfile under%APPDATA%/.iustitia/clips. An evidence clip you can play back later, not just a screenshot.[name]is the clip's filename (verbatim, so/ius playclip <name>round-trips) and also sets the focus player when it matches someone online; omit forscene_<tick>. Always writes (explicit export, independent of the Persist-across-sessions toggle). With Clip captures full world on (default), the clip carries the world around the action: full 16×16 columns, every Y section including underground, bounded by a configurable chunk radius (Chunk capture radius, default 8 → 17×17, capped 4..16) and a total-section budget, so the file stays sane even at max render distance. The world is no longer swept once when you save: it is rolled up in small per-tick pieces (16 chunks/tick, nearest-first) while the scene is still live, so/ius clipreturns immediately instead of freezing the client, and a window that spans a teleport records one segment per place so both replay instead of only the last. Nearby non-player entities (mobs, animals, boats, minecarts) and every block edit (blocks placed/broken during the window, observed by a read-only chunk hook) are captured alongside, so a clip replays the scene and its changes, not just player positions. The world is stored block-by-block (block names + per-section palettes), so a clip recorded on server A is watchable in full on server B, map and underground included. The one case that still sweeps once is a window the rolling capture has nothing for (a fresh session, or the toggle just turned on). This supersedes the v5 wireframe-shell terrain capture; v5 clips still load for back-compat. Fail-open: a capture error saves a world-less clip (ghosts only)./ius playclip [name] [1|0.5|0.25]. Loads a saved.iusclipand plays it back in-world, at full (1×) speed by default (pass0.5or0.25for slow-mo). Bare/ius playcliplists your saved clips;/ius playclip offstops a playing clip. The whole scene (ghosts and the bundled chunk world) is relocated to you: the focus player starts at your current position, and the captured world renders around you. The clip carries your own recorded body as well, so you appear where you were standing rather than wherever you are now, and your live body is hidden for the duration (a Legacy-mode clip, which is ghosts over the live world with no bundled world, gets the same treatment). For a v6+ clip the captured chunks render as solid, textured blocks (real block models via vanillaBlockRenderManager, face-culled, fullbright: the actual world, not a wireframe), and the live world is hidden for the duration so the clip's world replaces it (restored the instant the clip stops; pure render substitution: no blocks are placed, no packets sent, no server edit). Then/ius replay cam freecamdetaches the camera so you can fly anywhere in the clip's world with WASD + mouse, including underground (no collision: follow a player who went underground right through the stone); the local player's own walking is suppressed while freecam runs. For a v5 clip (wireframe-terrain) or v2–v4 clip (ghosts only), playback is back-compat: ghosts relocate as today, with the v5 wireframe shell if present; no solid world, no live-world hiding./ius clips: opens a clip manager screen listing every saved.iusclipwith its focus + frame/alert counts (and a chunk-section count when the clip carries a captured world, or a terrain-block count for older v5 clips); left-click to play, right-click to delete. Same data as bare/ius playclip, but browsable.
/ius clear <name|all>: wipes one player's flags (detection vl, flag timeline, tier, and alert routing → nametag back to green) or, withall, everyone's. Tracking and replay keep running; exemptions are untouched. A bare/ius clearprints usage (a bare clear is too easy to fat-finger into a wipe)./ius exempt [name [on|off]]: exempts a player from every check at theCheck.flagchokepoint (the very first line, before vl is incremented), so they stop flagging entirely. Bare/ius exemptlists the currently-exempted players; a bare name toggles;on/offset explicitly. Exemptions persist toexemptions.json(under%APPDATA%/.iustitiawhen persistence is on) and are not cleared on world change, so a trusted regular stays exempt across sessions and server hops. Exempting does not clear existing flags; pair it with/ius clear <name>to reset the tier.
All four instant-replay tools have toggles in /ius config (Replay capture buffer / Replay hides live players / Replay player models / Relocate scene to me / Clip captures full world / Chunk capture radius / Clip chunk render distance / Clip captures entities / Entity capture cap / Rolling world budget / New-segment distance). /ius replay plays ghosts at their exact recorded world coordinates (it's instant, same-server/same-dimension, so no anchoring is needed; v1.1.0 behavior), while /ius playclip relocates the scene to you (the focus player starts at your spot), gated by Relocate scene to me. /ius replay never carries the map (same-server, same-map use); only /ius clip captures it and only /ius playclip renders it. Note the chunk-world capture is loaded-chunks-only (the client only has chunks in render distance) and is radius-bounded to keep the file size down: a larger radius means a bigger file and a bigger rolling capture in memory (bounded by Rolling world budget: a section is up to 4096 bytes of palette indices, so the 24 000-section default is roughly 20–95 MB of live captured world depending on how full the segments are — a fully captured 17×17-radius segment is ~3 500 sections ≈ 14 MB, and about seven of those fit the default budget; lower it on a memory-tight client and raise it if a long /ius record keeps losing its earliest world). The Clip chunk render distance slider (default 6, range 4..12) bounds how far the clip's solid world draws around the camera each frame: a lower value trades visible distance for FPS (the per-chunk block draw is the main playclip cost), a higher value shows more of the captured world at once. The chunk world also bakes lazily: only in-range chunks are built, nearest-first a few per frame, so the world streams in from the camera outward instead of loading in one spike. Far-from-focus chunks are never built unless you fly toward them.
- Target highlight. A tier-colored wireframe box around the player your crosshair is on.
- Burst sparks: a brief tier-colored particle burst at a player's eye on a fresh tier-relevant alert.
- Hover tooltip: after the crosshair rests on one player for ~1.5 s, an expanded top-center banner (tier + score + why-this-tier + FP hint + most-flagged checks). Suppresses the compact crosshair panel while up.
- Crosshair confidence HUD. A compact panel near the crosshair with the looked-at player's tier glyph + score + why-this-tier + FP hint.
- Server-lag HUD indicator: a top-left ⚠ marker while a server-lag burst is recent (shows why alerts are being softened).
- Tab-list badge: the tier glyph (+ score) prepended to each other player's row in the Tab list.
- Offender selfie: a single-frame third-person screenshot of a freshly-red player, saved to
%APPDATA%/.iustitia/snapshots(when persistence is on).
Each overlay has its own toggle in /ius config and is off-able independently.
- In-game:
/ius configopens a YACL screen with a toggle per check plus all the global switches — master, chat alerts, nametag prefixes / burst pulse / green-tick, alert presets, smart batching, audio cues, lag-soften, compact mode, the render/HUD overlays, persistence, and the first-launch wizard. - Commands:
/ius toggle <check>,/ius threshold <check> <value>,/ius alerts <check|name> [on|off],/ius verbose,/ius reload,/ius reset,/ius wizard(re-run the setup wizard). - On disk:
config/iustitia.json(hand-rolled JSON via Gson; no extra serialization dependency). Edited live values are saved automatically (debounced, off the render thread). - Optional persistence: when Persist across sessions is on, moderator notes, tier/flag history, evidence snapshots, transcript/evidence exports, and the player exemption list are saved to
%APPDATA%/.iustitia(roaming) and reappear after a restart. Off by default — everything is in-memory session-only otherwise. (Evidence clips under.iustitia/clipsand exemptions underexemptions.jsonalways write, since exporting a clip or exempting a player is an explicit action.) - Alert presets (
alertLevel): 0 = quiet (red-severity band only), 1 = normal (orange + red), 2 = verbose (all). Display-only, no check logic changes. Smart batching collapses rapid same-player flags into one line after a quiet window; audio cues play a note-block chime per flushed batch (yellow pling vs red bass,audioVolume-adjustable — default off, so a fresh config is fully silent); lag-soften prefixes[lag]and (under quiet) drops non-red alerts during a server-lag burst. Compact mode shortens alert lines and screen rows to one-liners.
Each check's threshold is check-specific (Reach→max reach, MultiTarget→min victims, ClickStatistics→CPS cap, SpeedEnvelope→bps cap, Triggerbot→min fast-hits, etc.). /ius help <check> prints the live config + description for any check.
Iustitia is an open-source community project. Contributions are welcome from Minecraft/Fabric developers, anticheat researchers, moderators, documentation writers, testers, and developers who use AI-assisted tools.
Start here:
| If you want to... | Go to |
|---|---|
| Build the project, understand the rules, or open a pull request | CONTRIBUTING.md |
| Find the right place for a bug, compatibility report, false positive, or feature idea | SUPPORT.md and the GitHub issue templates |
| Report a security or privacy concern | SECURITY.md |
| Understand the community standards | CODE_OF_CONDUCT.md |
| Use Claude Code or another AI agent safely | AI-assisted development guide |
| Use the Iustitia Claude Code skill | .claude/skills/iustitia-contributor/SKILL.md |
| Run the repository verification tool | python scripts/verify_contribution.py --static --run-build |
| Verify a detection/replay change without touching the game | Automated live testing — python scripts/live_selftest.py |
| Validate a change that affects mixins, rendering, replay, or live client behavior | Live verification guide |
Human and AI-assisted contributors follow the same review standard: the contributor remains responsible for the code, the evidence behind detection changes, the test results, and the pull request description. AI-generated code must be disclosed in the pull request and must not be submitted without human review.
# from the repository root
python scripts/verify_contribution.py --static --run-build
./gradlew test
python scripts/live_selftest.py # automated live tests: real client, three passes, no input needed
./gradlew runClient # only for what the automated suite cannot seeThe verification tool checks project structure, Fabric metadata, mixin registration, check/config parity, generated check metadata, documentation links, and the build result. It also reports which live checks are required based on changed files.
scripts/live_selftest.py boots a real client, drives legitimate and cheating bot
players, and reports false positives (the LEGIT pass) and bypasses (the CHEAT pass) — see
Automated live testing. For changes to runtime client
behavior that the suite cannot observe (mixin packet decode, rendering), follow the
live verification checklist before opening a pull request.
git clone https://github.com/ThoriaDevelopment/Iustitia.git
cd Iustitia
./gradlew buildThe built mod jar is at build/libs/iustitia-<version>.jar. A sources jar is also produced. Requires JDK 21 and internet access on first build (Loom downloads Minecraft + mappings).
./gradlew runClient # launch a dev client with Iustitia loadedIustitia is purely client-sided. It reads incoming server packets that your client already receives, runs detection locally, and writes to your local chat and your local config file. It does not transmit, upload, or report anything to any server, endpoint, or third party. There is no telemetry, no analytics, no network code beyond reading what the server sends you.
By default, muting, tiering, flag history, moderator notes, and evidence data are all in-memory and cleared on restart (or /ius reset). The optional Persist across sessions toggle (persistenceEnabled) writes moderator notes, tier/flag history, evidence snapshots, transcript/evidence exports, and the player exemption list to %APPDATA%/.iustitia on your own machine so they survive a restart, still local, still never uploaded. Evidence clips (.iustitia/clips) and the exemption list (exemptions.json) always write when you explicitly create them. Nothing else is written to disk unless you turn persistence on.
- False positives are possible. Iustitia infers cheating from rebroadcast state, which is lossy. Every borderline (yellow) check is a heuristic. Treat yellow as "worth watching," not "definitely cheating." Red (definitive) checks are tuned to be high-confidence but should still be corroborated via
/ius histbefore acting. - Server-side nametags (stray.gg, mcpvp.club, and any server that hides the vanilla nametag) will not show the prefix — see Nametag prefixes.
- Chunk-unloaded players are false negatives (we can't observe what the server stops telling us), never false positives.
- It does not stop cheaters. It only tells you who looks like one. There is no enforcement.
MIT — see LICENSE.