modcrawl
Detect, inspect, and analyze Minecraft mods and plugins from JARs.
|
How it works
Inspects the ZIP entries inside a JAR without extracting. Picks the first matching sentinel file (Paper > Bukkit > NeoForge > Forge mods.toml > Forge mcmod.info > Fabric), then parses the corresponding metadata file and extracts dependency declarations.
Supported loaders
| Loader | Sentinel file | Metadata format |
|---|---|---|
| Fabric | fabric.mod.json |
JSON |
| Forge (mods.toml) | META-INF/mods.toml |
TOML |
| NeoForge | META-INF/neoforge.mods.toml |
TOML |
| Forge (mcmod.info) | mcmod.info |
JSON |
| Bukkit / Spigot | plugin.yml |
YAML |
| Paper | paper-plugin.yml |
YAML |
Adding a new loader means one new module implementing ModHandler and a single register() call — no core changes.
Install
Or download a prebuilt binary from GitHub Releases — the modcrawl.h header is shipped as a standalone asset (not inside archives).
Library
use identify;
use read_metadata;
use analyze;
let mod_type = identify?;
let meta = read_metadata?;
println!; // human-readable
println!; // JSON
let report = analyze?; // exclude jar-in-jar
for dep in &report.dependencies
Reader variants for in-memory buffers:
use Cursor;
use identify_reader;
use read_metadata_reader;
use analyze_reader;
let data = read?;
let mut cursor = new;
let mod_type = identify_reader?;
Dependency analysis
Dependencies are deduplicated by name. When the same dependency appears with different kinds (e.g. depends + recommends), the higher-priority kind wins:
Required > LoadBefore > Optional > Recommended > Suggested
Jar-in-jar entries (META-INF/jars/*.jar) are always scanned internally. If a dependency matches a bundled JAR's filename, it's removed from the external dependency list. The --include-jar-in-jar flag controls whether the jar-in-jar section appears in the output.
FFI / C bindings
Every core function is exposed as a C-compatible export:
| Function | Returns |
|---|---|
modcrawl_identify(path) |
Type string |
modcrawl_identify_bytes(data, len) |
Type string |
modcrawl_metadata(path) |
Human-readable metadata |
modcrawl_metadata_json(path) |
JSON metadata |
modcrawl_metadata_bytes(data, len) |
Human-readable metadata |
modcrawl_metadata_json_bytes(data, len) |
JSON metadata |
modcrawl_deps(path, include_jij) |
Human-readable deps |
modcrawl_deps_json(path, include_jij) |
JSON deps |
modcrawl_deps_bytes(data, len, include_jij) |
Human-readable deps |
modcrawl_deps_json_bytes(data, len, include_jij) |
JSON deps |
modcrawl_free_string(s) |
— (frees returned strings) |
All string-returning functions return null-terminated C strings owned by the caller — free with modcrawl_free_string. NULL means an error occurred (details printed to stderr).
char *type = ;
if
// Metadata as JSON
char *json = ;
if
CLI reference
| Command | Alias | What |
|---|---|---|
type |
t |
Detect mod/plugin type |
metadata |
m |
Read mod metadata (human or -j JSON) |
dep |
d, deps |
Analyze dependencies (-j JSON, --include-jar-in-jar/--jij) |
type
Reads from stdin when given no file arguments. Stdin can be raw ZIP bytes (detects EOCD boundaries for cat *.jar) or newline-separated file paths.
metadata
Takes one or more JAR paths. Multi-file output prefixes each result with the filename. --json / -j for compact JSON (one line per file).
dep / deps
Takes one or more JAR paths. --json / -j for pretty-printed JSON. --include-jar-in-jar / --jij to show embedded JARs. Bundled dependencies are always filtered out of the external dependency list regardless of this flag.
License
MIT