wuuvy wuuvy
Documentation

wuuvy Docs

Launch wuuvy, drive it from the built-in terminal, install it on PATH, and run it against Maven or Gradle projects from any shell.

Installation

Download the latest wuuvy.jar release from your license portal after purchase. That single JAR is the entire application - there is no installer, no native binary, no setup step. Save it wherever you like.

Optionally, run the install command once to self-obfuscate the JAR and drop wuuvy, ofc-jar, and ofc-jar-inside launchers on your PATH, so you can call them from any terminal - cmd, PowerShell, IntelliJ's terminal, VS Code's terminal, git-bash, WSL.

Launching wuuvy

wuuvy runs as a graphical, interactive terminal window. Launch it the same way you'd open any runnable JAR:

  • Windows: double-click wuuvy.jar, or run javaw -jar wuuvy.jar from a shortcut.
  • macOS: double-click wuuvy.jar from Finder, or run java -jar wuuvy.jar from Terminal.
  • Linux: java -jar wuuvy.jar from any shell.

When it opens, you'll see the wuuvy terminal window with the banner and an interactive prompt:

wuuvy
×
wuuvy [Version 1.0.0] copyright (C) All rights reserved Commands (this terminal): ofc -> pick a .jar, obfuscate with 'all' ofc-jar <tech1,tech2,...> -> pick a .jar, obfuscate with given techniques ofc-list -> list available techniques install -> put wuuvy / ofc-jar / ofc-jar-inside on PATH uninstall -> remove the launchers from PATH cls | exit After install, in any cmd / PowerShell / bash terminal: ofc-jar mod my-mod.jar -> standalone obfuscate (mod-safe preset) ofc-jar all my-app.jar out.jar -> with explicit output path ofc-jar-inside -methods -> build current project, obfuscate wuuvy integrate -> wire wuuvy into Gradle/Maven wuuvy\>

From this point, everything happens inside the wuuvy terminal - you type commands at the wuuvy\> prompt and press Enter.

Quick Start

The fastest way to protect a JAR: launch wuuvy, run ofc, and pick your JAR in the file dialog that appears.

wuuvy
×
wuuvy\> ofc In : C:\dev\projects\app\app.jar Out : C:\dev\projects\app\app_ofc.jar Seed: 1714082930117 Tech: [all] classes=1284 methods=9214 strings=3380 indy=612 Elapsed: 4821 ms wuuvy\>

wuuvy writes the protected JAR next to the original, suffixed with _ofc. No source changes, no runtime agent, no manifest editing required.

Note: the all profile enables every pass, including runtime hardening and anti-analysis tripwires. For most commercial apps you'll want a tailored profile - see the technique flags and presets sections below.

Requirements

  • Java Runtime: JRE or JDK 8 or newer to run wuuvy itself.
  • Target class format: wuuvy produces class files valid for JVM 8 through JVM 24.
  • Display: the interactive terminal opens a graphical window, so a desktop environment is required for it. For headless servers and CI, use the command-line entry point instead - it has no GUI dependency.
  • Memory: for JARs under 100 MB the default heap is sufficient. Larger JARs may benefit from launching with -Xmx2g or higher.

Terminal Commands

Every command is typed at the wuuvy\> prompt. Arguments are comma-separated, no spaces. Names are case-insensitive.

CommandWhat it does
ofcOpens a file picker. Applies the full all profile to the JAR you select and writes <name>_ofc.jar next to it.
ofc-jar <flags>Opens a file picker, then applies a custom comma-separated list of techniques. Example: ofc-jar rename,string-enc,shuffle.
ofc-listPrints every available transformation flag, grouped by category.
installSelf-obfuscates the running wuuvy jar, installs it to ~/.wuuvy/, and adds wuuvy, ofc-jar, and ofc-jar-inside launchers to your user PATH.
uninstallRemoves the install directory and drops the PATH entry created by install.
clsClears the terminal window.
exitCloses the wuuvy terminal.

Selecting a JAR

Whenever you run ofc or ofc-jar, wuuvy pops up a native file-chooser dialog so you can pick the target. The dialog remembers your last-used directory between runs, so repeat builds only take two clicks.

wuuvy writes the output JAR to the same directory as the input, with the suffix _ofc. For example, selecting C:\dev\projects\app\app.jar produces C:\dev\projects\app\app_ofc.jar. The original is never modified.

Technique Flags

Run ofc-list inside wuuvy to print the full list. Each name shown is exactly the token you pass to ofc-jar (or to -t on the command line). For detailed descriptions of what each pass does and when to use it, see the Techniques Reference on the home page.

Example - a light, IDE-friendly combination:

wuuvy
×
wuuvy\> ofc-jar rename,rename-fields,string-enc,shuffle,debug In : C:\dev\projects\app\app.jar Out : C:\dev\projects\app\app_ofc.jar Tech: [rename, rename-fields, string-enc, shuffle, debug] Elapsed: 1738 ms wuuvy\>

install / uninstall

The interactive terminal is convenient for one-offs, but for everyday use you'll want wuuvy available from any shell. Run install once inside the GUI terminal:

wuuvy
×
wuuvy\> install Installing wuuvy... [1/4] preparing... [2/4] building... [3/4] installing... [4/4] registering commands... Installed. Open a NEW terminal and try: wuuvy ofc-jar mod my-mod.jar ofc-jar-inside -methods wuuvy integrate wuuvy\>

What install actually does:

  • Self-obfuscates the current wuuvy jar using a conservative profile that's been validated to keep it runnable after the pass (so the copy on disk doesn't look anything like the downloaded one).
  • Copies the result to ~/.wuuvy/wuuvy.jar.
  • Writes launchers (.cmd on Windows, shell scripts elsewhere) into ~/.wuuvy/bin/: wuuvy, ofc-jar, and ofc-jar-inside.
  • Appends ~/.wuuvy/bin to your user PATH - via [Environment]::SetEnvironmentVariable('Path', ..., 'User') on Windows, or an export PATH line in .zshrc / .bashrc / .profile on Unix.

Open a new terminal afterwards so the PATH change is picked up. uninstall reverses all of that.

ofc-jar (any terminal)

ofc-jar is the simplest way to obfuscate from any shell after install. It accepts a preset name (all, mod, mod-strict, methods, light, paranoid) or a comma-separated list of techniques as the first argument.

# Forms accepted ofc-jar <techs> # build current project, then obfuscate ofc-jar <techs> <in.jar> # obfuscate <in.jar> -> <in>_ofc.jar in cwd ofc-jar <techs> <in.jar> <out.jar> # obfuscate to explicit output path # Examples ofc-jar all my-app.jar ofc-jar mod my-mod.jar # Minecraft-mod-safe preset ofc-jar string-enc,int-enc,cff foo.jar foo-stealth.jar ofc-jar methods # in cwd, build then obfuscate

Bad technique names fail fast with unknown technique: foo instead of being silently dropped. The result jar is <name>_ofc.jar in the current directory unless you give an explicit output path.

wuuvy <jar>

Once installed, wuuvy is a headless CLI - no GUI, suitable for scripts and CI. Run it against an existing jar and it writes <name>_ofc.jar into your current working directory.

# obfuscate with the full 'all' profile wuuvy app.jar # preset: method-focused pass set wuuvy app.jar -methods # preset: minimal / IDE-friendly wuuvy app.jar -light # exact technique list wuuvy app.jar -t rename,rename-fields,string-enc,shuffle,debug # override output path wuuvy app.jar -methods -o dist/app-stealth.jar # list every available technique wuuvy list # show banner and help wuuvy help

ofc-jar-inside (build + obfuscate in one step)

ofc-jar-inside is an alias for wuuvy inside. You run it from inside a project directory - it walks up looking for a pom.xml, build.gradle(.kts), an IntelliJ .idea folder, or the newest built jar, runs the right build command, then obfuscates the result.

# from the root of any Maven or Gradle project ofc-jar-inside # with a preset or explicit techniques ofc-jar-inside -methods ofc-jar-inside -light ofc-jar-inside -t rename,string-enc,shuffle # force a different project root ofc-jar-inside --root path/to/project # override where the _ofc.jar lands ofc-jar-inside -methods -o release/app-stealth.jar

The output JAR is dropped into the current working directory (not target/ / build/libs/), so it doesn't clash with your build outputs and is easy to attach to a release.

Maven Projects

When ofc-jar-inside finds a pom.xml at (or above) the current directory, it invokes Maven directly:

mvn -q -DskipTests package

It then takes the newest JAR in target/ and obfuscates it. A typical run looks like:

PowerShell
×
PS C:\dev\my-service> ofc-jar-inside -methods Root : C:\dev\my-service Build : mvn package (in C:\dev\my-service) Built : C:\dev\my-service\target\my-service-1.4.0.jar Out : C:\dev\my-service\my-service-1.4.0_ofc.jar Tech : [junk-methods, dup-methods, rename, main-rename, rename-static, sig-strip, param-strip, nop-insert, opaque-pred] Elapsed: 2915 ms

For repeat builds, wire wuuvy into the package phase of your pom.xml with the snippet generated by wuuvy maven-init. Then a normal mvn package produces both the regular jar in target/ and the obfuscated <name>_ofc.jar next to it.

Gradle Projects

When a build.gradle or build.gradle.kts is detected, ofc-jar-inside runs the project's own Gradle wrapper if present, otherwise the installed gradle:

# if ./gradlew[.bat] exists: ./gradlew build -q -x test # otherwise: gradle build -q -x test

It then picks the newest JAR under build/libs/ (skipping -sources.jar, -javadoc.jar, and any previously-obfuscated *_ofc.jar) and obfuscates it. Shadow/fat jars work - the newest-modified jar wins, so if your shadowJar task produces build/libs/app-all.jar, that's what gets picked up.

For repeat builds, wire wuuvy into your Gradle build with the snippet generated by wuuvy gradle-init. Then ./gradlew obfuscate produces both jars in build/libs/.

wuuvy integrate (Gradle / Maven plugin in one command)

wuuvy integrate auto-detects the build system in your current directory and writes a ready-to-paste integration snippet:

# From inside any Gradle or Maven project root: wuuvy integrate # Or call the specific generators directly: wuuvy gradle-init # writes wuuvy.gradle (or .kts) next to build.gradle wuuvy gradle-init -preset mod # bake in the 'mod' preset wuuvy maven-init # writes wuuvy-pom-snippet.xml next to pom.xml wuuvy maven-init -preset all # bake in 'all'

Gradle

The Gradle generator detects whether you have build.gradle (Groovy) or build.gradle.kts (Kotlin DSL) and emits the matching syntax. The generated wuuvy.gradle adds an obfuscate task that runs after jar:

// add this one line to build.gradle apply from: 'wuuvy.gradle' // then: ./gradlew obfuscate # uses the preset baked at gradle-init time ./gradlew obfuscate -Pofc.tech=methods # override at command line ./gradlew obfuscate -Pofc.tech=string-enc,int-enc,cff

Output is build/libs/<name>_ofc.jar. Uncomment the tasks.named('build') { dependsOn 'obfuscate' } line at the bottom of the snippet to make every ./gradlew build produce the obfuscated jar automatically.

Maven

The Maven generator writes a wuuvy-pom-snippet.xml with a complete <plugin> block built on exec-maven-plugin, bound to the package phase. Paste it into <build><plugins>...</plugins></build>:

mvn package # uses the preset baked at maven-init time mvn package -Dofc.tech=methods # override at command line mvn package -Dofc.tech=string-enc,int-enc,cff

Output is target/<name>_ofc.jar. The snippet reads ${user.home}/.wuuvy/wuuvy.jar - i.e. the install you already have - so there is no Maven Central artifact to depend on, and offline builds work as long as install has been run on the build agent.

How it works: both generated snippets just exec java -jar ~/.wuuvy/wuuvy.jar ofc-jar <techs> <in> <out>. There's no plugin artifact to download and no transitive dependencies dragged into your build. If ~/.wuuvy/wuuvy.jar is missing, the task fails loudly with a clear message rather than silently producing an unprotected jar.

CI/CD

CI environments are headless, so the GUI terminal isn't available there. Use the installed CLI on the build agent instead. A typical pattern:

  1. Stage wuuvy.jar in a trusted location (artifact cache, internal release bucket, or the repo itself under .ci/).
  2. On the agent, run java -jar wuuvy.jar <your-built.jar> -methods -o dist/app.jar after your normal build step. No install is needed - java -jar is sufficient for one-shot invocations.
  3. Upload the resulting _ofc.jar as your release artifact.

A few things worth knowing:

  • Exit codes: the CLI returns 0 on success, 2 if the input jar isn't found, 3 if inside couldn't locate or build a jar, non-zero for any other failure. Your pipeline's default "fail on non-zero" behaviour is sufficient.
  • No display needed: only the interactive Main entry opens a Swing window. The wuuvy CLI (the Wuuvy entry point) and wuuvy inside run fully headless. You do not need xvfb.
  • Non-determinism: the seed defaults to System.currentTimeMillis(), so renaming and layout differ run-to-run. If you need byte-reproducible output, keep the output jar as the released artifact rather than trying to reproduce it.
  • Caching: wuuvy has no build-avoidance of its own. If you want to skip re-obfuscation when inputs haven't changed, gate the step in your pipeline by hashing the input jar.

Presets

The CLI exposes a handful of shorthand presets in addition to -t <list>. The standalone ofc-jar takes them as the first positional argument; wuuvy takes them as -<name> flags.

PresetExpands toUse it when
allthe all meta-technique (every pass)you want maximum protection and have verified your app runs under it
modMinecraft-mod-safe technique set (Forge / Fabric / NeoForge). Excludes anno-strip, access-max, resource-enc, manifest-clean, main-rename, strip-inner, and debugyou're shipping a Minecraft mod and need to keep the loader, mixin transformer, and asset reader functional
mod-strictmod plus the techniques added since the original mod set was tuned (array-enc, ldc-widen, cd-junk) and the anti-tamper layer (anti-dump, crc32-check). User-config opt-ins (sig-check / env-gate / fp-gate) are still off - those need explicit setup to not self-haltyou're pushing a mod harder and accept a small compatibility risk; back off to plain mod if issues arise
methodsjunk-methods, dup-methods, rename, main-rename, rename-static, sig-strip, param-strip, nop-insert, opaque-predyou want method-level obfuscation without touching strings, control flow, or class layout
lightdebug, rename, shuffle, strip-inner, synthyou just want identifiers renamed and debug info stripped - safe for almost any framework
paranoidall plus anti-dump, crc32-check, sig-check, env-gate, fp-gate, verify-readback. Will halt the JVM unless the jar is signed, OFC_RUN_KEY matches, and host fingerprint matches the obfuscation hostshipping a one-host one-runtime build; do NOT use for portable jars or anything tested without signing

The interactive terminal doesn't use these preset names directly - ofc always applies all, and the in-terminal ofc-jar takes a comma-separated technique list. The standalone ofc-jar command (after install) accepts both presets and technique lists as the first positional arg.

Minecraft Mods

Minecraft mods have hard constraints - reflection-heavy loaders (Forge / Fabric / NeoForge), Sponge Mixin transformers, annotation-driven entry points. The mod preset is hand-tuned to compose with these.

The obfuscator already has Mod awareness built in:

  • Mod entry points are protected from rename: classes referenced from fabric.mod.json, META-INF/mods.toml, META-INF/neoforge.mods.toml, and any *.mixins.json are auto-collected and excluded from class renaming.
  • Mixin classes are skipped: any class with the @Mixin annotation is preserved verbatim. boze.mixins.json still resolves its targets by name after obfuscation.
  • Reflection-protected names: Class.forName / getDeclaredMethod / getDeclaredField string arguments are scanned across the jar and added to the no-rename set.
# typical workflow for a Fabric mod: cd path/to/mercwarex gradle build ofc-jar mod build/libs/mercwarex-1.0-SNAPSHOT.jar mercwarex-stealth.jar # or wire it into the build once: cd path/to/mercwarex wuuvy integrate echo "apply from: 'wuuvy.gradle'" >> build.gradle ./gradlew obfuscate -Pofc.tech=mod

Ship the auto-emitted ProGuard-format .mapping file with releases - without it, user crash reports become unreadable obfuscated stack traces.

Don't enable for mods: anno-strip strips @Mod / @SubscribeEvent; access-max breaks final invariants Forge relies on; resource-enc would encrypt textures, sounds, and lang files; main-rename is a no-op (mods have no Main-Class); debug strips line numbers so user crash reports become unreadable.

Troubleshooting

wuuvy window closes immediately after launch

Usually means a mismatched Java runtime. wuuvy needs Java 8 or newer. Run java -version from your terminal to check what's installed. On Windows, if double-clicking the JAR does nothing, try launching it from a terminal with java -jar wuuvy.jar so you can see any error output.

install says "added to user PATH" but wuuvy still isn't found

Windows and most shells only re-read environment variables when a process starts, so the terminal you ran install from won't see the change. Close it and open a new one. On Unix, either open a new shell or source the rc file install appended to (it tells you which).

ClassNotFoundException / NoSuchMethodError at runtime

Almost always caused by reflection or service loading in the protected app. Reproduce with a lighter preset to confirm - rerun with -light, and if the error disappears, renaming or stripping is hitting a reflectively-loaded class. Launching the protected app with -verbose:class will show exactly which class the JVM failed to find.

Protected JAR launches but throws at a specific method

Likely one aggressive pass conflicting with your code. Bisect with -t to isolate the culprit - start by removing cff, opaque-pred, indy-hide-*, and const-math. When the failing pass is identified, fall back to a technique list that excludes it (for example, build on top of -methods or -light rather than -all).

Slower startup after obfuscation

Expected if you enabled string-enc, clinit-finals, or any indy-hide-* pass - decryption and trampoline code runs at class load. For cold-start-sensitive apps (AWS Lambda, serverless), drop to -methods or -light and profile before adding heavier passes back.

ofc-jar-inside: "could not find or build a jar under <dir>"

The auto-detector couldn't find a pom.xml, build.gradle(.kts), IntelliJ artifact output under out/artifacts/, or a plain jar within three directories of where you ran it. Either run from inside the project root, pass --root, or build the jar yourself and call wuuvy <path-to-jar> directly.

My framework's reflection stops working

Most frameworks need reflection-touched classes to keep their original names. Common problem areas:

  • Spring: @Component, @Service, @Repository, @Controller classes, and the fields Spring injects into them.
  • Jackson / Gson: every DTO/POJO you (de)serialize - field names are the wire format.
  • JPA / Hibernate: @Entity classes and their fields.
  • JavaFX / FXML: controllers referenced by fx:controller.

In the current release the pragmatic answer is to drop back to -methods or -light and skip the identifier-rewriting passes that are breaking reflection. Finer-grained keep rules are on the roadmap.