Installation

disrobe is distributed two ways: prebuilt binaries from the GitHub Releases tab, and build from source with a single Rust toolchain. There is intentionally no PyPI/npm/Homebrew/crates.io/Docker channel for the binary itself; GitHub Releases is the canonical distribution point.

Each tagged release attaches prebuilt, statically-linkable binaries for the common targets, alongside SHA256SUMS, a cosign keyless signature bundle per archive, a GitHub build-provenance attestation, and a CycloneDX SBOM. See Security for the full verification story.

OSArchitectures
Windows 10/11x86-64, ARM64
Linux (glibc + musl)x86-64, ARM64
macOS 13+x86-64, ARM64 (Apple Silicon)
  1. Download the archive for your platform from the Releases page.

  2. Verify the checksum:

    sha256sum -c SHA256SUMS        # Linux / macOS
    
  3. (Optional) verify the cosign signature against the Sigstore transparency log:

    cosign verify-blob \
      --certificate-identity-regexp '^https://github.com/1-3-7/disrobe/' \
      --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
      --bundle    disrobe-<version>-<target>.tar.zst.cosign.bundle \
      disrobe-<version>-<target>.tar.zst
    
  4. Extract and place disrobe (disrobe.exe on Windows) anywhere on your PATH.

Build from source

Building requires Rust 1.95 or newer (stable). That is the only build dependency for the core; the optional external backends are fetched separately (see below).

git clone https://github.com/1-3-7/disrobe
cd disrobe
cargo build --release
./target/release/disrobe --version

A release build takes roughly four to six minutes on commodity hardware. The binary lands at target/release/disrobe; copy it onto your PATH.

Per-OS notes

  • Windows: the binary is disrobe.exe.
  • Linux: the musl build is fully static; the glibc build needs a matching glibc.
  • macOS: x86-64 and ARM64 (Apple silicon) archives are published separately. Gatekeeper may quarantine an unsigned download; clear it with xattr -d com.apple.quarantine disrobe.

The dependency boundary

Building and running disrobe are one dependency set. Grading and reproducing its published numbers are two others, and the three never blur together.

CategoryWhat is in itWhat breaks without it
Core (build and run)Rust 1.95+ stable, nothing elseNothing; cargo build --release produces the full binary
Optional backendGhidra, CFR, jadx, ILSpy, de4dot, and others, selected with --backend <tool>One feature: that pass falls back to the in-house default, which still runs
Grading onlyCPython, javac, the real JVM verifier, wasmtime, lua/luac, MRI, the .NET SDK, and the Go toolchainOne grade: the recovery is unaffected, but that ecosystem's number cannot be regraded locally
Benchmark repro onlyThe pinned competing tools in evidence/competitors/One number: the head-to-head row cannot be reproduced; disrobe's own recovery is unaffected

The per-ecosystem list for the last two rows is in evidence/README.md.

Slim build

cargo build --release produces the full everything-binary: every language and format pass compiled in. For a smaller artifact, opt into a slim build that keeps the always-on core (Python bytecode, native PE / ELF / Mach-O, and the container and format layer) and drops the optional passes:

cargo build -p disrobe-cli --release --no-default-features
# same build, shorter
cargo build-slim

Slim drops the optional language and format passes (JavaScript / TypeScript, WebAssembly, JVM / Android, .NET, Go, Lua, PHP, Ruby, BEAM, Swift, AS3, and more) and the multi-stage auto chain. It also drops every network and asynchronous surface: the HTTP server, the gRPC endpoint, the MCP companion, the prowl harvester, and the HTTP client that install-deps uses to download a third-party tool. A slim binary links none of tokio, axum, tonic, tower-http, tokio-util, tokio-stream, reqwest, hyper, rustls, rmcp or keyring, which a committed CI gate enforces by reading the dependency tree, so the binary cannot open a socket at all. Dropping the passes also drops large dependency trees such as the embedded JavaScript engine and the WebAssembly toolchain. On a Windows release build that trims the binary from 112.8 MB to 44.1 MB, about 61 percent smaller. Both figures are decimal megabytes measured on this repository's release profile, which strips symbols and links with fat LTO; the exact figure varies by platform and toolchain. A slim --help also lists 42 subcommands rather than 67, because a pass that is not compiled in is not declared. The wasm subcommand is one of the surfaces that does stay declared in a slim binary. If you run it, it reports why the pass is missing:

$ disrobe wasm decompile app.wasm
Error: the `wasm` pass is not compiled into this binary (slim build); rebuild with default features (feature `wasm`)

Layer specific passes back onto a slim base with --features, for example --no-default-features --features wasm,jvm.

Verifying the install

disrobe --version          # print the version
disrobe passes             # direct families plus auto-chain pass IDs
disrobe --help             # full subcommand surface
disrobe <pass> --help      # drill into any pass, e.g. `disrobe py --help`

Optional external backends

disrobe's in-house passes run with zero external dependencies. A subset of capabilities, however, wrap mature external tools headlessly: Ghidra for native decompilation; CFR / Vineflower / Procyon / jadx for the JVM and Android; ILSpy / dnSpy / de4dot for .NET; Rizin and friends elsewhere. These are never the product for bytecode languages (disrobe ships its own in-house decompilers there) and are always optional.

Probe what is installed and what is missing:

disrobe doctor                 # probe 46 to 51 external tools depending on the platform
disrobe doctor --auto-install  # install every missing tool that has a known install action

A missing tool with no install action (a commercial tool, a tool that ships bundled with another tool, a platform-exclusive tool, or a tool preinstalled by the operating system) is not silently dropped. --auto-install records it as a skip with a typed reason, in both text and --json output.

Install a single tool through your platform's native package manager (winget / brew / apt / dnf / pacman / apk). disrobe never installs itself this way; it only fetches the optional backends:

disrobe install --list         # list every known tool + per-platform package name
disrobe install ghidra
disrobe install upx

Heavyweight dependencies that ship as upstream release archives rather than OS packages (Ghidra, for instance) have a dedicated installer:

disrobe install-deps ghidra
disrobe install-deps --all

Shell completions and man pages

disrobe completions bash --install        # also: zsh, fish, powershell, elvish
disrobe man --out ./man                   # one .1 page per subcommand